diff options
40 files changed, 312 insertions, 299 deletions
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java index f2bb50944..f2459dd3e 100644 --- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java +++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java @@ -223,14 +223,12 @@ public class WallpaperCropActivity extends BaseActivity implements Handler.Callb @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) protected boolean isActivityDestroyed() { - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) - && isDestroyed(); + return Utilities.ATLEAST_JB_MR1 && isDestroyed(); } @Thunk void addReusableBitmap(TileSource src) { synchronized (mReusableBitmaps) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT - && src instanceof BitmapRegionTileSource) { + if (Utilities.ATLEAST_KITKAT && src instanceof BitmapRegionTileSource) { Bitmap preview = ((BitmapRegionTileSource) src).getBitmap(); if (preview != null && preview.isMutable()) { mReusableBitmaps.add(preview); diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java index 75d874552..59858501a 100644 --- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java +++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java @@ -977,10 +977,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { if (partner == null || !partner.hideDefaultWallpaper()) { // Add an entry for the default wallpaper (stored in system resources) - WallpaperTileInfo defaultWallpaperInfo = - (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) - ? getPreKKDefaultWallpaperInfo() - : getDefaultWallpaper(); + WallpaperTileInfo defaultWallpaperInfo = Utilities.ATLEAST_KITKAT + ? getDefaultWallpaper() : getPreKKDefaultWallpaperInfo(); if (defaultWallpaperInfo != null) { bundled.add(0, defaultWallpaperInfo); } diff --git a/res/layout/all_apps_search_bar.xml b/res/layout/all_apps_search_bar.xml index 0c183eaee..69a66c817 100644 --- a/res/layout/all_apps_search_bar.xml +++ b/res/layout/all_apps_search_bar.xml @@ -38,7 +38,7 @@ android:contentDescription="@string/all_apps_button_label" android:src="@drawable/ic_arrow_back_grey" /> - <com.android.launcher3.allapps.AllAppsSearchEditView + <com.android.launcher3.ExtendedEditText android:id="@+id/search_box_input" android:layout_width="match_parent" android:layout_height="match_parent" diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml index ecf7def48..275840def 100644 --- a/res/layout/user_folder.xml +++ b/res/layout/user_folder.xml @@ -53,7 +53,7 @@ android:paddingLeft="8dp" android:paddingRight="8dp" > - <com.android.launcher3.FolderEditText + <com.android.launcher3.ExtendedEditText android:id="@+id/folder_name" android:layout_width="0dp" android:layout_height="wrap_content" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 856690da8..84e1594b4 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -32,7 +32,7 @@ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Rechercher dans les applications"</string> <string name="all_apps_loading_message" msgid="7557140873644765180">"Chargement des applications en cours…"</string> <string name="all_apps_no_search_results" msgid="6332185285860416787">"Aucune application ne correspond à la requête \"<xliff:g id="QUERY">%1$s</xliff:g>\"."</string> - <string name="all_apps_search_market_message" msgid="5470761048755751471">"Accéder au service <xliff:g id="QUERY">%1$s</xliff:g>"</string> + <string name="all_apps_search_market_message" msgid="5470761048755751471">"Accéder à <xliff:g id="QUERY">%1$s</xliff:g>"</string> <string name="out_of_space" msgid="4691004494942118364">"Pas d\'espace libre sur cet écran d\'accueil."</string> <string name="hotseat_out_of_space" msgid="7448809638125333693">"Plus d\'espace disponible dans la zone de favoris."</string> <string name="all_apps_button_label" msgid="9110807029020582876">"Applications"</string> diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml index 46a234355..290033088 100644 --- a/res/values-ka-rGE/strings.xml +++ b/res/values-ka-rGE/strings.xml @@ -32,8 +32,7 @@ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"აპების ძიება"</string> <string name="all_apps_loading_message" msgid="7557140873644765180">"აპები იტვირთება..."</string> <string name="all_apps_no_search_results" msgid="6332185285860416787">"„<xliff:g id="QUERY">%1$s</xliff:g>“-ის თანხვედრი აპები არ მოიძებნა"</string> - <!-- no translation found for all_apps_search_market_message (5470761048755751471) --> - <skip /> + <string name="all_apps_search_market_message" msgid="5470761048755751471">"გადადი <xliff:g id="QUERY">%1$s</xliff:g>-ში"</string> <string name="out_of_space" msgid="4691004494942118364">"ამ მთავარ ეკრანზე ადგილი აღარ არის."</string> <string name="hotseat_out_of_space" msgid="7448809638125333693">"რჩეულების თაროზე ადგილი არ არის"</string> <string name="all_apps_button_label" msgid="9110807029020582876">"აპები"</string> diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 495a14b37..77f07c955 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -32,8 +32,7 @@ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜索应用"</string> <string name="all_apps_loading_message" msgid="7557140873644765180">"正在加载应用…"</string> <string name="all_apps_no_search_results" msgid="6332185285860416787">"未找到与“<xliff:g id="QUERY">%1$s</xliff:g>”相符的应用"</string> - <!-- no translation found for all_apps_search_market_message (5470761048755751471) --> - <skip /> + <string name="all_apps_search_market_message" msgid="5470761048755751471">"转到 <xliff:g id="QUERY">%1$s</xliff:g>"</string> <string name="out_of_space" msgid="4691004494942118364">"此主屏幕上已没有空间。"</string> <string name="hotseat_out_of_space" msgid="7448809638125333693">"收藏栏已满"</string> <string name="all_apps_button_label" msgid="9110807029020582876">"应用"</string> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 589d69666..b9fb6e257 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -129,4 +129,8 @@ <dimen name="blur_size_click_shadow">4dp</dimen> <dimen name="click_shadow_high_shift">2dp</dimen> +<!-- Pending widget --> + <dimen name="pending_widget_min_padding">8dp</dimen> + <dimen name="pending_widget_elevation">2dp</dimen> + </resources> diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java index 5e7a012d2..b1d51ece0 100644 --- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java +++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java @@ -13,6 +13,7 @@ import android.os.AsyncTask; import android.util.Log; import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.compat.AppWidgetManagerCompat; import java.util.ArrayList; import java.util.List; @@ -48,7 +49,8 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]); final int state; if (LauncherModel.isValidProvider(provider)) { - state = LauncherAppWidgetInfo.RESTORE_COMPLETED; + // This will ensure that we show 'Click to setup' UI if required. + state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY; } else { state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY; } diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 1bcaab519..507087824 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -510,7 +510,7 @@ public class BubbleTextView extends TextView mIcon.setBounds(0, 0, iconSize, iconSize); } if (mLayoutHorizontal) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { setCompoundDrawablesRelative(mIcon, null, null, null); } else { setCompoundDrawables(mIcon, null, null, null); diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java index b7f89d02a..2baa6d8ee 100644 --- a/src/com/android/launcher3/ButtonDropTarget.java +++ b/src/com/android/launcher3/ButtonDropTarget.java @@ -24,7 +24,6 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.annotation.TargetApi; import android.content.Context; import android.content.res.ColorStateList; -import android.content.res.Configuration; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.PointF; @@ -93,7 +92,7 @@ public abstract class ButtonDropTarget extends TextView // drawableLeft and drawableStart. mDrawable = getResources().getDrawable(resId); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { setCompoundDrawablesRelativeWithIntrinsicBounds(mDrawable, null, null, null); } else { setCompoundDrawablesWithIntrinsicBounds(mDrawable, null, null, null); @@ -114,7 +113,7 @@ public abstract class ButtonDropTarget extends TextView @Override public final void onDragEnter(DragObject d) { d.dragView.setColor(mHoverColor); - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { animateTextColor(mHoverColor); } else { if (mCurrentFilter == null) { @@ -131,8 +130,8 @@ public abstract class ButtonDropTarget extends TextView // Do nothing } - protected void resetHoverColor() { - if (Utilities.isLmpOrAbove()) { + protected void resetHoverColor() { + if (Utilities.ATLEAST_LOLLIPOP) { animateTextColor(mOriginalTextColor.getDefaultColor()); } else { mDrawable.setColorFilter(null); diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java index dfa8202a7..2acfc6140 100644 --- a/src/com/android/launcher3/DragView.java +++ b/src/com/android/launcher3/DragView.java @@ -131,7 +131,7 @@ public class DragView extends View { measure(ms, ms); mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { setElevation(getResources().getDimension(R.dimen.drag_elevation)); } } @@ -252,14 +252,14 @@ public class DragView extends View { setColorScale(color, m2); m1.postConcat(m2); - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { animateFilterTo(m1.getArray()); } else { mPaint.setColorFilter(new ColorMatrixColorFilter(m1)); invalidate(); } } else { - if (!Utilities.isLmpOrAbove() || mCurrentFilter == null) { + if (!Utilities.ATLEAST_LOLLIPOP || mCurrentFilter == null) { mPaint.setColorFilter(null); invalidate(); } else { diff --git a/src/com/android/launcher3/allapps/AllAppsSearchEditView.java b/src/com/android/launcher3/ExtendedEditText.java index b7dcd66ed..c7b64ec7d 100644 --- a/src/com/android/launcher3/allapps/AllAppsSearchEditView.java +++ b/src/com/android/launcher3/ExtendedEditText.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.launcher3.allapps; +package com.android.launcher3; import android.content.Context; import android.util.AttributeSet; @@ -22,28 +22,28 @@ import android.widget.EditText; /** - * The edit text for the search container + * The edit text that reports back when the back key has been pressed. */ -public class AllAppsSearchEditView extends EditText { +public class ExtendedEditText extends EditText { /** * Implemented by listeners of the back key. */ public interface OnBackKeyListener { - public void onBackKey(); + public boolean onBackKey(); } private OnBackKeyListener mBackKeyListener; - public AllAppsSearchEditView(Context context) { - this(context, null); + public ExtendedEditText(Context context) { + super(context); } - public AllAppsSearchEditView(Context context, AttributeSet attrs) { - this(context, attrs, 0); + public ExtendedEditText(Context context, AttributeSet attrs) { + super(context, attrs); } - public AllAppsSearchEditView(Context context, AttributeSet attrs, int defStyleAttr) { + public ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -56,7 +56,7 @@ public class AllAppsSearchEditView extends EditText { // If this is a back key, propagate the key back to the listener if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mBackKeyListener != null) { - mBackKeyListener.onBackKey(); + return mBackKeyListener.onBackKey(); } return false; } diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 5e713b21f..c1aa35669 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -124,7 +124,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Thunk FolderPagedView mContent; @Thunk View mContentWrapper; - FolderEditText mFolderName; + ExtendedEditText mFolderName; private View mFooter; private int mFooterHeight; @@ -196,8 +196,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mContent = (FolderPagedView) findViewById(R.id.folder_content); mContent.setFolder(this); - mFolderName = (FolderEditText) findViewById(R.id.folder_name); - mFolderName.setFolder(this); + mFolderName = (ExtendedEditText) findViewById(R.id.folder_name); + mFolderName.setOnBackKeyListener(new ExtendedEditText.OnBackKeyListener() { + @Override + public boolean onBackKey() { + // Close the activity on back key press + doneEditingFolderName(true); + return false; + } + }); mFolderName.setOnFocusChangeListener(this); // We disable action mode for now since it messes up the view on phones @@ -446,7 +453,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList Animator openFolderAnim = null; final Runnable onCompleteRunnable; - if (!Utilities.isLmpOrAbove()) { + if (!Utilities.ATLEAST_LOLLIPOP) { positionAndSizeAsIcon(); centerAboutIcon(); @@ -561,7 +568,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void onAnimationEnd(Animator animation) { mFolderName.animate().setDuration(FOLDER_NAME_ANIMATION_DURATION) .translationX(0) - .setInterpolator(Utilities.isLmpOrAbove() ? + .setInterpolator(Utilities.ATLEAST_LOLLIPOP ? AnimationUtils.loadInterpolator(mLauncher, android.R.interpolator.fast_out_slow_in) : new LogDecelerateInterpolator(100, 0)); diff --git a/src/com/android/launcher3/FolderEditText.java b/src/com/android/launcher3/FolderEditText.java deleted file mode 100644 index c31100899..000000000 --- a/src/com/android/launcher3/FolderEditText.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.android.launcher3; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.KeyEvent; -import android.widget.EditText; - -public class FolderEditText extends EditText { - - private Folder mFolder; - - public FolderEditText(Context context) { - super(context); - } - - public FolderEditText(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public FolderEditText(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public void setFolder(Folder folder) { - mFolder = folder; - } - - @Override - public boolean onKeyPreIme(int keyCode, KeyEvent event) { - // Catch the back button on the soft keyboard so that we can just close the activity - if (event.getKeyCode() == android.view.KeyEvent.KEYCODE_BACK) { - mFolder.doneEditingFolderName(true); - } - return super.onKeyPreIme(keyCode, event); - } -} diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 203e2247c..6f2458c11 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -116,8 +116,6 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collection; @@ -360,18 +358,6 @@ public class Launcher extends Activity } } - // TODO: remove this field and call method directly when Launcher3 can depend on M APIs - private static Method sClipRevealMethod = null; - static { - Class<?> activityOptionsClass = ActivityOptions.class; - try { - sClipRevealMethod = activityOptionsClass.getDeclaredMethod("makeClipRevealAnimation", - View.class, int.class, int.class, int.class, int.class); - } catch (Exception e) { - // Earlier version - } - } - @Thunk Runnable mBuildLayersRunnable = new Runnable() { public void run() { if (mWorkspace != null) { @@ -667,7 +653,7 @@ public class Launcher extends Activity @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static int generateViewId() { - if (Build.VERSION.SDK_INT >= 17) { + if (Utilities.ATLEAST_JB_MR1) { return View.generateViewId(); } else { // View.generateViewId() is not available. The following fallback logic is a copy @@ -1653,18 +1639,18 @@ public class Launcher extends Activity } registerReceiver(mReceiver, filter); FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView()); - setupTransparentSystemBarsForLmp(); + setupTransparentSystemBarsForLollipop(); mAttached = true; mVisible = true; } /** - * Sets up transparent navigation and status bars in LMP. + * Sets up transparent navigation and status bars in Lollipop. * This method is a no-op for other platform versions. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private void setupTransparentSystemBarsForLmp() { - if (Utilities.isLmpOrAbove()) { + private void setupTransparentSystemBarsForLollipop() { + if (Utilities.ATLEAST_LOLLIPOP) { Window window = getWindow(); window.getAttributes().systemUiVisibility |= (View.SYSTEM_UI_FLAG_LAYOUT_STABLE @@ -2893,8 +2879,7 @@ public class Launcher extends Activity Bundle optsBundle = null; if (useLaunchAnimation) { ActivityOptions opts = null; - if (sClipRevealMethod != null) { - // TODO: call method directly when Launcher3 can depend on M APIs + if (Utilities.ATLEAST_MARSHMALLOW) { int left = 0, top = 0; int width = v.getMeasuredWidth(), height = v.getMeasuredHeight(); if (v instanceof TextView) { @@ -2908,22 +2893,12 @@ public class Launcher extends Activity height = bounds.height(); } } - try { - opts = (ActivityOptions) sClipRevealMethod.invoke(null, v, - left, top, width, height); - } catch (IllegalAccessException e) { - Log.d(TAG, "Could not call makeClipRevealAnimation: " + e); - sClipRevealMethod = null; - } catch (InvocationTargetException e) { - Log.d(TAG, "Could not call makeClipRevealAnimation: " + e); - sClipRevealMethod = null; - } - } - if (opts == null && !Utilities.isLmpOrAbove()) { + opts = ActivityOptions.makeClipRevealAnimation(v, left, top, width, height); + } else if (!Utilities.ATLEAST_LOLLIPOP) { // Below L, we use a scale up animation opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); - } else if (opts == null && Utilities.isLmpMR1()) { + } else if (Utilities.ATLEAST_LOLLIPOP_MR1) { // On L devices, we use the device default slide-up transition. // On L MR1 devices, we a custom version of the slide-up transition which // doesn't have the delay present in the device default. @@ -3038,7 +3013,7 @@ public class Launcher extends Activity ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(mFolderIconImageView, alpha, scaleX, scaleY); - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { oa.setInterpolator(new LogDecelerateInterpolator(100, 0)); } oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration)); @@ -3899,7 +3874,8 @@ public class Launcher extends Activity if (!mIsSafeModeEnabled && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0) - && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) { + && (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) { + if (appWidgetInfo == null) { if (DEBUG_WIDGETS) { Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId @@ -3909,42 +3885,51 @@ public class Launcher extends Activity 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(this, appWidgetInfo, null); - pendingInfo.spanX = item.spanX; - pendingInfo.spanY = item.spanY; - pendingInfo.minSpanX = item.minSpanX; - pendingInfo.minSpanY = item.minSpanY; - Bundle options = null; - WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo); - - int newWidgetId = mAppWidgetHost.allocateAppWidgetId(); - boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( - newWidgetId, appWidgetInfo, options); - // 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"); + // If we do not have a valid id, try to bind an id. + if ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0) { + // 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(this, appWidgetInfo, null); + pendingInfo.spanX = item.spanX; + pendingInfo.spanY = item.spanY; + pendingInfo.minSpanX = item.minSpanX; + pendingInfo.minSpanY = item.minSpanY; + Bundle options = null; + WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo); + + int newWidgetId = mAppWidgetHost.allocateAppWidgetId(); + boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( + newWidgetId, appWidgetInfo, options); + + // 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; } - LauncherModel.deleteItemFromDatabase(this, item); - return; - } - item.appWidgetId = newWidgetId; + 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; + // 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); + LauncherModel.updateItemInDatabase(this, item); + } else if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0) + && (appWidgetInfo.configure == null)) { + // If the ID is already valid, verify if we need to configure or not. + item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED; + LauncherModel.updateItemInDatabase(this, item); + } } if (!mIsSafeModeEnabled && item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) { @@ -4324,13 +4309,14 @@ public class Launcher extends Activity return oriMap[(d.getRotation() + indexOffset) % 4]; } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public void lockScreenOrientation() { if (mRotationEnabled) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + if (Utilities.ATLEAST_JB_MR2) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); + } else { setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources() .getConfiguration().orientation)); - } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); } } } @@ -4534,7 +4520,7 @@ public class Launcher extends Activity public ItemInfo createAppDragInfo(Intent appLaunchIntent) { // Called from search suggestion UserHandleCompat user = null; - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { UserHandle userHandle = appLaunchIntent.getParcelableExtra(Intent.EXTRA_USER); if (userHandle != null) { user = UserHandleCompat.fromUser(userHandle); diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 52f85ea42..d87ad67e5 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -127,7 +127,7 @@ public class LauncherAppState { LauncherModel setLauncher(Launcher launcher) { getLauncherProvider().setLauncherProviderChangeListener(launcher); mModel.initialize(launcher); - mAccessibilityDelegate = ((launcher != null) && Utilities.isLmpOrAbove()) ? + mAccessibilityDelegate = ((launcher != null) && Utilities.ATLEAST_LOLLIPOP) ? new LauncherAccessibilityDelegate(launcher) : null; return mModel; } diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java index 3debef60e..8eb4e6369 100644 --- a/src/com/android/launcher3/LauncherBackupAgentHelper.java +++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java @@ -65,7 +65,7 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper { @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { - if (!Utilities.isLmpOrAbove()) { + if (!Utilities.ATLEAST_LOLLIPOP) { // No restore for old devices. Log.i(TAG, "You shall not pass!!!"); Log.d(TAG, "Restore is only supported on devices running Lollipop and above."); diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java index c44ea6bcd..747028474 100644 --- a/src/com/android/launcher3/LauncherClings.java +++ b/src/com/android/launcher3/LauncherClings.java @@ -16,8 +16,6 @@ package com.android.launcher3; -import android.accounts.Account; -import android.accounts.AccountManager; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.annotation.TargetApi; @@ -36,6 +34,7 @@ import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.accessibility.AccessibilityManager; + import com.android.launcher3.util.Thunk; class LauncherClings implements OnClickListener { @@ -225,7 +224,7 @@ class LauncherClings implements OnClickListener { // 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 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + if (Utilities.ATLEAST_JB_MR2) { UserManager um = (UserManager) mLauncher.getSystemService(Context.USER_SERVICE); Bundle restrictions = um.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 397db6dc2..27486822a 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -2195,7 +2195,7 @@ public class LauncherModel extends BroadcastReceiver // Id would be valid only if the widget restore broadcast was received. if (isIdValid) { - status = LauncherAppWidgetInfo.RESTORE_COMPLETED; + status = LauncherAppWidgetInfo.FLAG_UI_NOT_READY; } else { status &= ~LauncherAppWidgetInfo .FLAG_PROVIDER_NOT_READY; @@ -3197,6 +3197,12 @@ public class LauncherModel extends BroadcastReceiver widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY & ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED; + + // adding this flag ensures that launcher shows 'click to setup' + // if the widget has a config activity. In case there is no config + // activity, it will be marked as 'restored' during bind. + widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY; + widgets.add(widgetInfo); updateItemInDatabase(context, widgetInfo); } diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 6cbb267be..20844ec13 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -77,8 +77,6 @@ public class LauncherProvider extends ContentProvider { static final String TABLE_WORKSPACE_SCREENS = LauncherSettings.WorkspaceScreens.TABLE_NAME; static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED"; - private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd"; - private static final String RESTRICTION_PACKAGE_NAME = "workspace.configuration.package.name"; @Thunk LauncherProviderChangeListener mListener; @@ -140,14 +138,21 @@ public class LauncherProvider extends ContentProvider { return db.insert(table, nullColumnHack, values); } + private void reloadLauncherIfExternal() { + if (Binder.getCallingPid() != Process.myPid()) { + LauncherAppState app = LauncherAppState.getInstanceNoCreate(); + if (app != null) { + app.reloadWorkspace(); + } + } + } + @Override public Uri insert(Uri uri, ContentValues initialValues) { SqlArguments args = new SqlArguments(uri); - // In very limited cases, we support system|signature permission apps to add to the db - String externalAdd = uri.getQueryParameter(URI_PARAM_IS_EXTERNAL_ADD); - final boolean isExternalAll = externalAdd != null && "true".equals(externalAdd); - if (isExternalAll) { + // In very limited cases, we support system|signature permission apps to modify the db. + if (Binder.getCallingPid() != Process.myPid()) { if (!mOpenHelper.initializeExternalAdd(initialValues)) { return null; } @@ -161,13 +166,7 @@ public class LauncherProvider extends ContentProvider { uri = ContentUris.withAppendedId(uri, rowId); notifyListeners(); - if (isExternalAll) { - LauncherAppState app = LauncherAppState.getInstanceNoCreate(); - if (app != null) { - app.reloadWorkspace(); - } - } - + reloadLauncherIfExternal(); return uri; } @@ -192,6 +191,7 @@ public class LauncherProvider extends ContentProvider { } notifyListeners(); + reloadLauncherIfExternal(); return values.length; } @@ -203,6 +203,7 @@ public class LauncherProvider extends ContentProvider { try { ContentProviderResult[] result = super.applyBatch(operations); db.setTransactionSuccessful(); + reloadLauncherIfExternal(); return result; } finally { db.endTransaction(); @@ -217,6 +218,7 @@ public class LauncherProvider extends ContentProvider { int count = db.delete(args.table, args.where, args.args); if (count > 0) notifyListeners(); + reloadLauncherIfExternal(); return count; } @@ -229,6 +231,7 @@ public class LauncherProvider extends ContentProvider { int count = db.update(args.table, values, args.where, args.args); if (count > 0) notifyListeners(); + reloadLauncherIfExternal(); return count; } @@ -399,7 +402,7 @@ public class LauncherProvider extends ContentProvider { @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction() { // UserManager.getApplicationRestrictions() requires minSdkVersion >= 18 - if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + if (!Utilities.ATLEAST_JB_MR2) { return null; } diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java index 5a3f3dc7a..cdde8c13f 100644 --- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java +++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java @@ -205,7 +205,7 @@ public class LauncherStateTransitionAnimation { final boolean animated, final PrivateTransitionCallbacks pCb) { final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet(); final Resources res = mLauncher.getResources(); - final boolean material = Utilities.isLmpOrAbove(); + final boolean material = Utilities.ATLEAST_LOLLIPOP; final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime); final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger); @@ -358,12 +358,11 @@ public class LauncherStateTransitionAnimation { dispatchOnLauncherTransitionStart(toView, animated, false); // Enable all necessary layers - boolean isLmpOrAbove = Utilities.isLmpOrAbove(); for (View v : layerViews.keySet()) { if (layerViews.get(v) == BUILD_AND_SET_LAYER) { v.setLayerType(View.LAYER_TYPE_HARDWARE, null); } - if (isLmpOrAbove && Utilities.isViewAttachedToWindow(v)) { + if (Utilities.ATLEAST_LOLLIPOP && Utilities.isViewAttachedToWindow(v)) { v.buildLayer(); } } @@ -486,7 +485,7 @@ public class LauncherStateTransitionAnimation { final PrivateTransitionCallbacks pCb) { final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet(); final Resources res = mLauncher.getResources(); - final boolean material = Utilities.isLmpOrAbove(); + final boolean material = Utilities.ATLEAST_LOLLIPOP; final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime); final int itemsAlphaStagger = res.getInteger(R.integer.config_overlayItemsAlphaStagger); @@ -668,12 +667,11 @@ public class LauncherStateTransitionAnimation { dispatchOnLauncherTransitionStart(toView, animated, false); // Enable all necessary layers - boolean isLmpOrAbove = Utilities.isLmpOrAbove(); for (View v : layerViews.keySet()) { if (layerViews.get(v) == BUILD_AND_SET_LAYER) { v.setLayerType(View.LAYER_TYPE_HARDWARE, null); } - if (isLmpOrAbove && Utilities.isViewAttachedToWindow(v)) { + if (Utilities.ATLEAST_LOLLIPOP && Utilities.isViewAttachedToWindow(v)) { v.buildLayer(); } } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 218c1a36f..05f0a0553 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -2293,7 +2293,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // Besides disabling the accessibility long-click, this also prevents this view from getting // accessibility focus. info.setLongClickable(false); - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK); } } diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java index 08f8e5601..40eadabd5 100644 --- a/src/com/android/launcher3/PendingAppWidgetHostView.java +++ b/src/com/android/launcher3/PendingAppWidgetHostView.java @@ -16,13 +16,17 @@ package com.android.launcher3; +import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.content.res.Resources.Theme; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.text.Layout; import android.text.StaticLayout; @@ -32,6 +36,8 @@ import android.view.View; import android.view.View.OnClickListener; public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implements OnClickListener { + private static final float SETUP_ICON_SIZE_FACTOR = 2f / 5; + private static final float MIN_SATUNATION = 0.7f; private static Theme sPreloaderTheme; @@ -47,13 +53,14 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen private Bitmap mIcon; private Drawable mCenterDrawable; - private Drawable mTopCornerDrawable; + private Drawable mSettingIconDrawable; private boolean mDrawableSizeChanged; private final TextPaint mPaint; private Layout mSetupTextLayout; + @TargetApi(Build.VERSION_CODES.LOLLIPOP) public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info, boolean disabledForSafeMode) { super(context); @@ -70,6 +77,10 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen mLauncher.getDeviceProfile().iconTextSizePx, getResources().getDisplayMetrics())); setBackgroundResource(R.drawable.quantum_panel_dark); setWillNotDraw(false); + + if (Utilities.ATLEAST_LOLLIPOP) { + setElevation(getResources().getDimension(R.dimen.pending_widget_elevation)); + } } @Override @@ -124,10 +135,12 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen FastBitmapDrawable disabledIcon = mLauncher.createIconDrawable(mIcon); disabledIcon.setGhostModeEnabled(true); mCenterDrawable = disabledIcon; - mTopCornerDrawable = null; + mSettingIconDrawable = null; } else if (isReadyForClickSetup()) { - mCenterDrawable = getResources().getDrawable(R.drawable.ic_setting); - mTopCornerDrawable = new FastBitmapDrawable(mIcon); + mCenterDrawable = new FastBitmapDrawable(mIcon); + mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate(); + + updateSettingColor(); } else { if (sPreloaderTheme == null) { sPreloaderTheme = getResources().newTheme(); @@ -137,13 +150,25 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen FastBitmapDrawable drawable = mLauncher.createIconDrawable(mIcon); mCenterDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme); mCenterDrawable.setCallback(this); - mTopCornerDrawable = null; + mSettingIconDrawable = null; applyState(); } mDrawableSizeChanged = true; } } + private void updateSettingColor() { + int color = Utilities.findDominantColorByHue(mIcon, 20); + // Make the dominant color bright. + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + hsv[1] = Math.min(hsv[1], MIN_SATUNATION); + hsv[2] = 1; + color = Color.HSVToColor(hsv); + + mSettingIconDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); + } + @Override protected boolean verifyDrawable(Drawable who) { return (who == mCenterDrawable) || super.verifyDrawable(who); @@ -169,6 +194,83 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen && (mInfo.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0; } + private void updateDrawableBounds() { + DeviceProfile grid = mLauncher.getDeviceProfile(); + int paddingTop = getPaddingTop(); + int paddingBottom = getPaddingBottom(); + int paddingLeft = getPaddingLeft(); + int paddingRight = getPaddingRight(); + + int minPadding = getResources() + .getDimensionPixelSize(R.dimen.pending_widget_min_padding); + + int availableWidth = getWidth() - paddingLeft - paddingRight - 2 * minPadding; + int availableHeight = getHeight() - paddingTop - paddingBottom - 2 * minPadding; + + if (mSettingIconDrawable == null) { + int outset = (mCenterDrawable instanceof PreloadIconDrawable) ? + ((PreloadIconDrawable) mCenterDrawable).getOutset() : 0; + int maxSize = grid.iconSizePx + 2 * outset; + int size = Math.min(maxSize, Math.min(availableWidth, availableHeight)); + + mRect.set(0, 0, size, size); + mRect.inset(outset, outset); + mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2); + mCenterDrawable.setBounds(mRect); + } else { + float iconSize = Math.min(availableWidth, availableHeight); + + // Use twice the setting size factor, as the setting is drawn at a corner and the + // icon is drawn in the center. + float settingIconScaleFactor = 1 + SETUP_ICON_SIZE_FACTOR * 2; + int maxSize = Math.max(availableWidth, availableHeight); + if (iconSize * settingIconScaleFactor > maxSize) { + // There is an overlap + iconSize = maxSize / settingIconScaleFactor; + } + + int actualIconSize = (int) Math.min(iconSize, grid.iconSizePx); + + // Recreate the setup text. + mSetupTextLayout = new StaticLayout( + getResources().getText(R.string.gadget_setup_text), mPaint, availableWidth, + Layout.Alignment.ALIGN_CENTER, 1, 0, true); + int textHeight = mSetupTextLayout.getHeight(); + + // Extra icon size due to the setting icon + float minHeightWithText = textHeight + actualIconSize * settingIconScaleFactor + + grid.iconDrawablePaddingPx; + + int iconTop; + if (minHeightWithText < availableHeight) { + // We can draw the text as well + iconTop = (getHeight() - textHeight - + grid.iconDrawablePaddingPx - actualIconSize) / 2; + + } else { + // The text will not fit. Only draw the icons. + iconTop = (getHeight() - actualIconSize) / 2; + mSetupTextLayout = null; + } + + mRect.set(0, 0, actualIconSize, actualIconSize); + mRect.offset((getWidth() - actualIconSize) / 2, iconTop); + mCenterDrawable.setBounds(mRect); + + mRect.left = paddingLeft + minPadding; + mRect.right = mRect.left + (int) (SETUP_ICON_SIZE_FACTOR * actualIconSize); + mRect.top = paddingTop + minPadding; + mRect.bottom = mRect.top + (int) (SETUP_ICON_SIZE_FACTOR * actualIconSize); + mSettingIconDrawable.setBounds(mRect); + + if (mSetupTextLayout != null) { + // Set up position for dragging the text + mRect.left = paddingLeft + minPadding; + mRect.top = mCenterDrawable.getBounds().bottom + grid.iconDrawablePaddingPx; + } + } + } + @Override protected void onDraw(Canvas canvas) { if (mCenterDrawable == null) { @@ -176,81 +278,21 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen return; } - DeviceProfile grid = mLauncher.getDeviceProfile(); - if (mTopCornerDrawable == null) { - if (mDrawableSizeChanged) { - int outset = (mCenterDrawable instanceof PreloadIconDrawable) ? - ((PreloadIconDrawable) mCenterDrawable).getOutset() : 0; - int maxSize = grid.iconSizePx + 2 * outset; - int size = Math.min(maxSize, Math.min( - getWidth() - getPaddingLeft() - getPaddingRight(), - getHeight() - getPaddingTop() - getPaddingBottom())); - - mRect.set(0, 0, size, size); - mRect.inset(outset, outset); - mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2); - mCenterDrawable.setBounds(mRect); - mDrawableSizeChanged = false; - } - mCenterDrawable.draw(canvas); - } else { - // Draw the top corner icon and "Setup" text is possible - if (mDrawableSizeChanged) { - int iconSize = grid.iconSizePx; - int paddingTop = getPaddingTop(); - int paddingBottom = getPaddingBottom(); - int paddingLeft = getPaddingLeft(); - int paddingRight = getPaddingRight(); - - int availableWidth = getWidth() - paddingLeft - paddingRight; - int availableHeight = getHeight() - paddingTop - paddingBottom; - - // Recreate the setup text. - mSetupTextLayout = new StaticLayout( - getResources().getText(R.string.gadget_setup_text), mPaint, availableWidth, - Layout.Alignment.ALIGN_CENTER, 1, 0, true); - if (mSetupTextLayout.getLineCount() == 1) { - // The text fits in a single line. No need to draw the setup icon. - int size = Math.min(iconSize, Math.min(availableWidth, - availableHeight - mSetupTextLayout.getHeight())); - mRect.set(0, 0, size, size); - mRect.offsetTo((getWidth() - mRect.width()) / 2, - (getHeight() - mRect.height() - mSetupTextLayout.getHeight() - - grid.iconDrawablePaddingPx) / 2); - - mTopCornerDrawable.setBounds(mRect); - - // Update left and top to indicate the position where the text will be drawn. - mRect.left = paddingLeft; - mRect.top = mRect.bottom + grid.iconDrawablePaddingPx; - } else { - // The text can't be drawn in a single line. Draw a setup icon instead. - mSetupTextLayout = null; - int size = Math.min(iconSize, Math.min( - getWidth() - paddingLeft - paddingRight, - getHeight() - paddingTop - paddingBottom)); - mRect.set(0, 0, size, size); - mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2); - mCenterDrawable.setBounds(mRect); - - size = Math.min(size / 2, - Math.max(mRect.top - paddingTop, mRect.left - paddingLeft)); - mTopCornerDrawable.setBounds(paddingLeft, paddingTop, - paddingLeft + size, paddingTop + size); - } - mDrawableSizeChanged = false; - } + if (mDrawableSizeChanged) { + updateDrawableBounds(); + mDrawableSizeChanged = false; + } - if (mSetupTextLayout == null) { - mCenterDrawable.draw(canvas); - mTopCornerDrawable.draw(canvas); - } else { - canvas.save(); - canvas.translate(mRect.left, mRect.top); - mSetupTextLayout.draw(canvas); - canvas.restore(); - mTopCornerDrawable.draw(canvas); - } + mCenterDrawable.draw(canvas); + if (mSettingIconDrawable != null) { + mSettingIconDrawable.draw(canvas); } + if (mSetupTextLayout != null) { + canvas.save(); + canvas.translate(mRect.left, mRect.top); + mSetupTextLayout.draw(canvas); + canvas.restore(); + } + } } diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java index 0819f8ce0..955d4013c 100644 --- a/src/com/android/launcher3/UninstallDropTarget.java +++ b/src/com/android/launcher3/UninstallDropTarget.java @@ -38,7 +38,7 @@ public class UninstallDropTarget extends ButtonDropTarget { @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public static boolean supportsDrop(Context context, Object info) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + if (Utilities.ATLEAST_JB_MR2) { UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = userManager.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false) diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 8fd298df7..adedd33b2 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -87,6 +87,24 @@ public final class Utilities { private static final int[] sLoc0 = new int[2]; private static final int[] sLoc1 = new int[2]; + // TODO: use Build.VERSION_CODES when available + public static final boolean ATLEAST_MARSHMALLOW = Build.VERSION.SDK_INT >= 23; + + public static final boolean ATLEAST_LOLLIPOP_MR1 = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1; + + public static final boolean ATLEAST_LOLLIPOP = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + + public static final boolean ATLEAST_KITKAT = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + public static final boolean ATLEAST_JB_MR1 = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; + + public static final boolean ATLEAST_JB_MR2 = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; + // To turn on these properties, type // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] private static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate"; @@ -110,23 +128,6 @@ public final class Utilities { return sForceEnableRotation || context.getResources().getBoolean(R.bool.allow_rotation); } - /** - * Indicates if the device is running LMP or higher. - */ - public static boolean isLmpOrAbove() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; - } - - public static boolean isLmpMR1OrAbove() { - // TODO(adamcohen): update to Build.VERSION_CODES.LOLLIPOP_MR1 once building against 22; - return Build.VERSION.SDK_INT >= 22; - } - - public static boolean isLmpMR1() { - // TODO(adamcohen): update to Build.VERSION_CODES.LOLLIPOP_MR1 once building against 22; - return Build.VERSION.SDK_INT == 22; - } - public static Bitmap createIconBitmap(Cursor c, int iconIndex, Context context) { byte[] data = c.getBlob(iconIndex); try { @@ -517,7 +518,7 @@ public final class Utilities { @TargetApi(Build.VERSION_CODES.KITKAT) public static boolean isViewAttachedToWindow(View v) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (ATLEAST_KITKAT) { return v.isAttachedToWindow(); } else { // A proxy call which returns null, if the view is not attached to the window. @@ -544,7 +545,7 @@ public final class Utilities { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) { if (info.provider.getPackageName().equals(providerPkg)) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (ATLEAST_JB_MR1) { if ((info.widgetCategory & AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX) != 0) { return info; } else if (defaultWidgetForSearchPackage == null) { @@ -655,7 +656,7 @@ public final class Utilities { @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static boolean isRtl(Resources res) { - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) && + return ATLEAST_JB_MR1 && (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 08e642948..61d09a95c 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -2013,7 +2013,7 @@ public class Workspace extends PagedView } public void updateAccessibilityFlags() { - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { int total = getPageCount(); for (int i = numCustomPages(); i < total; i++) { updateAccessibilityFlags((CellLayout) getPageAt(i), i); diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchController.java b/src/com/android/launcher3/allapps/DefaultAppSearchController.java index e1a2b7fda..3169f842a 100644 --- a/src/com/android/launcher3/allapps/DefaultAppSearchController.java +++ b/src/com/android/launcher3/allapps/DefaultAppSearchController.java @@ -25,6 +25,7 @@ import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.TextView; +import com.android.launcher3.ExtendedEditText; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.util.Thunk; @@ -54,7 +55,8 @@ final class DefaultAppSearchController extends AllAppsSearchBarController @Thunk View mSearchBarContainerView; private View mSearchButtonView; private View mDismissSearchButtonView; - @Thunk AllAppsSearchEditView mSearchBarEditView; + @Thunk + ExtendedEditText mSearchBarEditView; @Thunk AllAppsRecyclerView mAppsRecyclerView; @Thunk Runnable mFocusRecyclerViewRunnable = new Runnable() { @Override @@ -82,21 +84,23 @@ final class DefaultAppSearchController extends AllAppsSearchBarController mSearchBarContainerView = mSearchView.findViewById(R.id.search_container); mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button); mDismissSearchButtonView.setOnClickListener(this); - mSearchBarEditView = (AllAppsSearchEditView) + mSearchBarEditView = (ExtendedEditText) mSearchBarContainerView.findViewById(R.id.search_box_input); mSearchBarEditView.addTextChangedListener(this); mSearchBarEditView.setOnEditorActionListener(this); mSearchBarEditView.setOnBackKeyListener( - new AllAppsSearchEditView.OnBackKeyListener() { + new ExtendedEditText.OnBackKeyListener() { @Override - public void onBackKey() { + public boolean onBackKey() { // Only hide the search field if there is no query, or if there // are no filtered results String query = Utilities.trim( mSearchBarEditView.getEditableText().toString()); if (query.isEmpty() || mApps.hasNoFilteredResults()) { hideSearchField(true, mFocusRecyclerViewRunnable); + return true; } + return false; } }); return mSearchView; diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java index 7aa36d447..434f13dcc 100644 --- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java +++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java @@ -40,7 +40,7 @@ public abstract class AppWidgetManagerCompat { public static AppWidgetManagerCompat getInstance(Context context) { synchronized (sInstanceLock) { if (sInstance == null) { - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { sInstance = new AppWidgetManagerCompatVL(context.getApplicationContext()); } else { sInstance = new AppWidgetManagerCompatV16(context.getApplicationContext()); diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java index f7f4b7e4f..463cf902d 100644 --- a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java +++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java @@ -54,10 +54,10 @@ class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat { @Override public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info, Bundle options) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider); - } else { + if (Utilities.ATLEAST_JB_MR1) { return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider, options); + } else { + return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider); } } diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java index 5858bc8b9..95e3ba902 100644 --- a/src/com/android/launcher3/compat/LauncherAppsCompat.java +++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java @@ -53,7 +53,7 @@ public abstract class LauncherAppsCompat { public static LauncherAppsCompat getInstance(Context context) { synchronized (sInstanceLock) { if (sInstance == null) { - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { sInstance = new LauncherAppsCompatVL(context.getApplicationContext()); } else { sInstance = new LauncherAppsCompatV16(context.getApplicationContext()); diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java index ac3d252f5..339c457e1 100644 --- a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java +++ b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java @@ -31,6 +31,7 @@ import android.os.Build; import android.os.Bundle; import android.provider.Settings; +import com.android.launcher3.Utilities; import com.android.launcher3.util.Thunk; import java.util.ArrayList; @@ -188,7 +189,7 @@ public class LauncherAppsCompatV16 extends LauncherAppsCompat { // when moving a package or mounting/un-mounting external storage. Assume that // it is a replacing operation. final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, - Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT); + !Utilities.ATLEAST_KITKAT); String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); for (OnAppsChangedCallbackCompat callback : getCallbacks()) { callback.onPackagesAvailable(packages, user, replacing); diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java index c49908328..ec5014d7c 100644 --- a/src/com/android/launcher3/compat/PackageInstallerCompat.java +++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java @@ -34,7 +34,7 @@ public abstract class PackageInstallerCompat { public static PackageInstallerCompat getInstance(Context context) { synchronized (sInstanceLock) { if (sInstance == null) { - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { sInstance = new PackageInstallerCompatVL(context); } else { sInstance = new PackageInstallerCompatV16(); diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java index ab4b7216b..567022b43 100644 --- a/src/com/android/launcher3/compat/UserHandleCompat.java +++ b/src/com/android/launcher3/compat/UserHandleCompat.java @@ -34,7 +34,7 @@ public class UserHandleCompat { @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static UserHandleCompat myUserHandle() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { return new UserHandleCompat(android.os.Process.myUserHandle()); } else { return new UserHandleCompat(); @@ -55,7 +55,7 @@ public class UserHandleCompat { @Override public String toString() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { return mUser.toString(); } else { return ""; @@ -67,7 +67,7 @@ public class UserHandleCompat { if (!(other instanceof UserHandleCompat)) { return false; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { return mUser.equals(((UserHandleCompat) other).mUser); } else { return true; @@ -76,7 +76,7 @@ public class UserHandleCompat { @Override public int hashCode() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { return mUser.hashCode(); } else { return 0; @@ -89,7 +89,7 @@ public class UserHandleCompat { * profiles so this is a no-op. */ public void addToIntent(Intent intent, String name) { - if (Utilities.isLmpOrAbove() && mUser != null) { + if (Utilities.ATLEAST_LOLLIPOP && mUser != null) { intent.putExtra(name, mUser); } } diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java index 2ff1e7b74..f708004a3 100644 --- a/src/com/android/launcher3/compat/UserManagerCompat.java +++ b/src/com/android/launcher3/compat/UserManagerCompat.java @@ -34,9 +34,9 @@ public abstract class UserManagerCompat { public static UserManagerCompat getInstance(Context context) { synchronized (sInstanceLock) { if (sInstance == null) { - if (Utilities.isLmpOrAbove()) { + if (Utilities.ATLEAST_LOLLIPOP) { sInstance = new UserManagerCompatVL(context.getApplicationContext()); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + } else if (Utilities.ATLEAST_JB_MR1) { sInstance = new UserManagerCompatV17(context.getApplicationContext()); } else { sInstance = new UserManagerCompatV16(); diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java index b37f44719..74fc92a04 100644 --- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java +++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java @@ -68,7 +68,7 @@ public class ManagedProfileHeuristic { private static final long AUTO_ADD_TO_FOLDER_DURATION = 8 * 60 * 60 * 1000; public static ManagedProfileHeuristic get(Context context, UserHandleCompat user) { - if (Utilities.isLmpOrAbove() && !UserHandleCompat.myUserHandle().equals(user)) { + if (Utilities.ATLEAST_LOLLIPOP && !UserHandleCompat.myUserHandle().equals(user)) { return new ManagedProfileHeuristic(context, user); } return null; @@ -296,7 +296,7 @@ public class ManagedProfileHeuristic { * Verifies that entries corresponding to {@param users} exist and removes all invalid entries. */ public static void processAllUsers(List<UserHandleCompat> users, Context context) { - if (!Utilities.isLmpOrAbove()) { + if (!Utilities.ATLEAST_LOLLIPOP) { return; } UserManagerCompat userManager = UserManagerCompat.getInstance(context); diff --git a/src/com/android/launcher3/util/UiThreadCircularReveal.java b/src/com/android/launcher3/util/UiThreadCircularReveal.java index 3ca3aeeee..f2b5e5e15 100644 --- a/src/com/android/launcher3/util/UiThreadCircularReveal.java +++ b/src/com/android/launcher3/util/UiThreadCircularReveal.java @@ -47,7 +47,7 @@ public class UiThreadCircularReveal { float progress = arg0.getAnimatedFraction(); outlineProvider.setProgress(progress); revealView.invalidateOutline(); - if (!Utilities.isLmpMR1OrAbove()) { + if (!Utilities.ATLEAST_LOLLIPOP_MR1) { revealView.invalidate(); } } diff --git a/src/com/android/launcher3/util/WallpaperUtils.java b/src/com/android/launcher3/util/WallpaperUtils.java index 53b2acd84..b9fccbcfd 100644 --- a/src/com/android/launcher3/util/WallpaperUtils.java +++ b/src/com/android/launcher3/util/WallpaperUtils.java @@ -24,6 +24,8 @@ import android.graphics.Point; import android.os.Build; import android.view.WindowManager; +import com.android.launcher3.Utilities; + /** * Utility methods for wallpaper management. */ @@ -99,7 +101,7 @@ public final class WallpaperUtils { int maxDim = Math.max(maxDims.x, maxDims.y); int minDim = Math.max(minDims.x, minDims.y); - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { Point realSize = new Point(); windowManager.getDefaultDisplay().getRealSize(realSize); maxDim = Math.max(realSize.x, realSize.y); diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java index 30b3d581a..461aebb6b 100644 --- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java +++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java @@ -15,6 +15,7 @@ import com.android.launcher3.DragLayer; import com.android.launcher3.DragSource; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.Utilities; import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.util.Thunk; @@ -131,7 +132,7 @@ public class WidgetHostViewLoader implements DragListener { public static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) { Bundle options = null; Rect rect = new Rect(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, rect); Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher, info.componentName, null); diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java index a54626a39..f1cde299d 100644 --- a/src/com/android/launcher3/widget/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java @@ -169,7 +169,7 @@ public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> { // if the end padding is 0, then container view (horizontal scroll view) doesn't respect // the end of the linear layout width + the start padding and doesn't allow scrolling. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (Utilities.ATLEAST_JB_MR1) { cellList.setPaddingRelative(mIndent, 0, 1, 0); } else { cellList.setPadding(mIndent, 0, 1, 0); |