blob: c49286a75552f90b2861e079e367d9e03ec13dca [file] [log] [blame]
Michael Jurka104c4562013-07-08 18:03:46 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher3;
18
Michael Jurkabe2f8dd2013-09-10 13:39:59 +020019import android.animation.LayoutTransition;
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -070020import android.annotation.TargetApi;
Michael Jurka104c4562013-07-08 18:03:46 -070021import android.app.ActionBar;
22import android.app.Activity;
Michael Jurka998e4ff2013-09-18 16:04:36 +020023import android.app.WallpaperManager;
Sunny Goyal1d0b0932015-03-20 18:51:38 -070024import android.content.ActivityNotFoundException;
Michael Jurka1e4e6dd2013-09-23 23:02:05 +010025import android.content.Context;
Michael Jurka104c4562013-07-08 18:03:46 -070026import android.content.Intent;
Michael Jurkaeadbfc52013-09-04 00:45:37 +020027import android.content.pm.ApplicationInfo;
Michael Jurka104c4562013-07-08 18:03:46 -070028import android.content.pm.PackageManager;
Michael Jurka104c4562013-07-08 18:03:46 -070029import android.content.res.Resources;
Michael Jurka42a71742013-09-18 00:45:45 +020030import android.database.Cursor;
Michael Jurka998e4ff2013-09-18 16:04:36 +020031import android.database.DataSetObserver;
Michael Jurkabe2f8dd2013-09-10 13:39:59 +020032import android.graphics.Bitmap;
Michael Jurkadb84e822013-09-23 23:02:05 +010033import android.graphics.BitmapFactory;
Michael Jurka12ca6132013-10-15 11:14:44 -070034import android.graphics.Canvas;
Michael Jurka8713a942013-10-10 21:28:40 -070035import android.graphics.Matrix;
Michael Jurka104c4562013-07-08 18:03:46 -070036import android.graphics.Point;
Michael Jurka998e4ff2013-09-18 16:04:36 +020037import android.graphics.PorterDuff;
Michael Jurka104c4562013-07-08 18:03:46 -070038import android.graphics.RectF;
Michael Jurkadb84e822013-09-23 23:02:05 +010039import android.graphics.drawable.BitmapDrawable;
Michael Jurka104c4562013-07-08 18:03:46 -070040import android.graphics.drawable.Drawable;
Michael Jurka104c4562013-07-08 18:03:46 -070041import android.net.Uri;
Michael Jurka862f7e32013-10-16 18:23:56 -070042import android.os.AsyncTask;
Michael Jurka12ca6132013-10-15 11:14:44 -070043import android.os.Build;
Michael Jurkad6dc6042013-09-10 13:39:59 +020044import android.os.Bundle;
Michael Jurka42a71742013-09-18 00:45:45 +020045import android.provider.MediaStore;
Michael Jurka104c4562013-07-08 18:03:46 -070046import android.util.Log;
Michael Jurkaeadbfc52013-09-04 00:45:37 +020047import android.util.Pair;
Michael Jurkad6dc6042013-09-10 13:39:59 +020048import android.view.ActionMode;
Michael Jurka104c4562013-07-08 18:03:46 -070049import android.view.LayoutInflater;
50import android.view.Menu;
Michael Jurkad6dc6042013-09-10 13:39:59 +020051import android.view.MenuInflater;
Michael Jurka104c4562013-07-08 18:03:46 -070052import android.view.MenuItem;
Michael Jurka104c4562013-07-08 18:03:46 -070053import android.view.View;
54import android.view.View.OnClickListener;
Michael Jurka12ca6132013-10-15 11:14:44 -070055import android.view.View.OnLayoutChangeListener;
Michael Jurka104c4562013-07-08 18:03:46 -070056import android.view.ViewGroup;
Michael Jurka7ad868b2013-12-12 15:04:25 +010057import android.view.ViewPropertyAnimator;
Michael Jurkafe0ace32013-10-03 01:05:14 -070058import android.view.ViewTreeObserver;
59import android.view.ViewTreeObserver.OnGlobalLayoutListener;
Selim Cinekffed6582014-02-28 17:18:59 +010060import android.view.WindowManager;
Daniel Sandler24f397d2013-10-12 00:02:45 -040061import android.view.animation.AccelerateInterpolator;
Michael Jurka4b940602013-09-05 12:14:12 +020062import android.view.animation.DecelerateInterpolator;
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -070063import android.widget.ArrayAdapter;
Michael Jurka104c4562013-07-08 18:03:46 -070064import android.widget.BaseAdapter;
65import android.widget.FrameLayout;
Michael Jurkafe0ace32013-10-03 01:05:14 -070066import android.widget.HorizontalScrollView;
Michael Jurka104c4562013-07-08 18:03:46 -070067import android.widget.ImageView;
68import android.widget.LinearLayout;
Michael Jurka619a1802013-10-29 15:50:06 +010069import android.widget.Toast;
Michael Jurka104c4562013-07-08 18:03:46 -070070
Sunny Goyal06a4d3f2015-02-12 11:19:39 -080071import com.android.gallery3d.common.BitmapCropTask;
72import com.android.gallery3d.common.BitmapUtils;
73import com.android.gallery3d.common.Utils;
Adam Cohen091440a2015-03-18 14:16:05 -070074import com.android.launcher3.util.Thunk;
Sunny Goyal6a1e95a2015-03-20 17:26:30 -070075import com.android.launcher3.util.WallpaperUtils;
Michael Jurka104c4562013-07-08 18:03:46 -070076import com.android.photos.BitmapRegionTileSource;
Michael Jurka619a1802013-10-29 15:50:06 +010077import com.android.photos.BitmapRegionTileSource.BitmapSource;
Sunny Goyal65b929d2015-02-12 15:34:41 -080078import com.android.photos.views.TiledImageRenderer.TileSource;
Michael Jurka104c4562013-07-08 18:03:46 -070079
Michael Jurkadb84e822013-09-23 23:02:05 +010080import java.io.File;
81import java.io.FileOutputStream;
Michael Jurka1e4e6dd2013-09-23 23:02:05 +010082import java.io.IOException;
Michael Jurka104c4562013-07-08 18:03:46 -070083import java.util.ArrayList;
Michael Jurka104c4562013-07-08 18:03:46 -070084
85public class WallpaperPickerActivity extends WallpaperCropActivity {
Michael Jurkabe2f8dd2013-09-10 13:39:59 +020086 static final String TAG = "Launcher.WallpaperPickerActivity";
Michael Jurka104c4562013-07-08 18:03:46 -070087
Michael Jurka1e4e6dd2013-09-23 23:02:05 +010088 public static final int IMAGE_PICK = 5;
89 public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
Michael Jurkad6dc6042013-09-10 13:39:59 +020090 private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES";
Jorim Jaggi1b921ef2014-01-14 16:00:17 -080091 private static final String SELECTED_INDEX = "SELECTED_INDEX";
Selim Cinekffed6582014-02-28 17:18:59 +010092 private static final int FLAG_POST_DELAY_MILLIS = 200;
Michael Jurka104c4562013-07-08 18:03:46 -070093
Adam Cohen091440a2015-03-18 14:16:05 -070094 @Thunk View mSelectedTile;
95 @Thunk boolean mIgnoreNextTap;
96 @Thunk OnClickListener mThumbnailOnClickListener;
Michael Jurka104c4562013-07-08 18:03:46 -070097
Adam Cohen091440a2015-03-18 14:16:05 -070098 @Thunk LinearLayout mWallpapersView;
99 @Thunk HorizontalScrollView mWallpaperScrollContainer;
Michael Jurkad6dc6042013-09-10 13:39:59 +0200100
Adam Cohen091440a2015-03-18 14:16:05 -0700101 @Thunk ActionMode.Callback mActionModeCallback;
102 @Thunk ActionMode mActionMode;
Michael Jurkad6dc6042013-09-10 13:39:59 +0200103
Adam Cohen091440a2015-03-18 14:16:05 -0700104 @Thunk View.OnLongClickListener mLongClickListener;
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200105
106 ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>();
107 private SavedWallpaperImages mSavedImages;
Adam Cohen091440a2015-03-18 14:16:05 -0700108 @Thunk int mSelectedIndex = -1;
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200109
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100110 public static abstract class WallpaperTileInfo {
Michael Jurka6b783a02013-10-04 12:26:48 -0700111 protected View mView;
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700112 public Drawable mThumb;
113
Michael Jurka6b783a02013-10-04 12:26:48 -0700114 public void setView(View v) {
115 mView = v;
116 }
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100117 public void onClick(WallpaperPickerActivity a) {}
118 public void onSave(WallpaperPickerActivity a) {}
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700119 public void onDelete(WallpaperPickerActivity a) {}
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100120 public boolean isSelectable() { return false; }
Michael Jurka6b783a02013-10-04 12:26:48 -0700121 public boolean isNamelessWallpaper() { return false; }
122 public void onIndexUpdated(CharSequence label) {
123 if (isNamelessWallpaper()) {
124 mView.setContentDescription(label);
125 }
126 }
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100127 }
128
129 public static class PickImageInfo extends WallpaperTileInfo {
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700130 @Override
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100131 public void onClick(WallpaperPickerActivity a) {
132 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
133 intent.setType("image/*");
Michael Jurka7ad868b2013-12-12 15:04:25 +0100134 a.startActivityForResultSafely(intent, IMAGE_PICK);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100135 }
136 }
137
138 public static class UriWallpaperInfo extends WallpaperTileInfo {
139 private Uri mUri;
Michael Jurka619a1802013-10-29 15:50:06 +0100140 private boolean mFirstClick = true;
Adam Cohen091440a2015-03-18 14:16:05 -0700141 @Thunk BitmapRegionTileSource.UriBitmapSource mBitmapSource;
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100142 public UriWallpaperInfo(Uri uri) {
143 mUri = uri;
144 }
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700145 @Override
Michael Jurka619a1802013-10-29 15:50:06 +0100146 public void onClick(final WallpaperPickerActivity a) {
147 final Runnable onLoad;
148 if (!mFirstClick) {
149 onLoad = null;
150 } else {
151 mFirstClick = false;
Selim Cinekffed6582014-02-28 17:18:59 +0100152 a.mSetWallpaperButton.setEnabled(false);
Michael Jurka619a1802013-10-29 15:50:06 +0100153 onLoad = new Runnable() {
154 public void run() {
155 if (mBitmapSource != null &&
156 mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
Michael Jurka619a1802013-10-29 15:50:06 +0100157 a.selectTile(mView);
Selim Cinekffed6582014-02-28 17:18:59 +0100158 a.mSetWallpaperButton.setEnabled(true);
Michael Jurka619a1802013-10-29 15:50:06 +0100159 } else {
160 ViewGroup parent = (ViewGroup) mView.getParent();
161 if (parent != null) {
162 parent.removeView(mView);
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700163 Toast.makeText(a.getContext(), R.string.image_load_fail,
Michael Jurka619a1802013-10-29 15:50:06 +0100164 Toast.LENGTH_SHORT).show();
165 }
166 }
167 }
168 };
169 }
170 mBitmapSource = new BitmapRegionTileSource.UriBitmapSource(
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700171 a.getContext(), mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
Sunny Goyal65b929d2015-02-12 15:34:41 -0800172 a.setCropViewTileSource(mBitmapSource, true, false, null, onLoad);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100173 }
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700174 @Override
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100175 public void onSave(final WallpaperPickerActivity a) {
176 boolean finishActivityWhenDone = true;
Sunny Goyal06a4d3f2015-02-12 11:19:39 -0800177 BitmapCropTask.OnBitmapCroppedHandler h = new BitmapCropTask.OnBitmapCroppedHandler() {
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100178 public void onBitmapCropped(byte[] imageBytes) {
179 Point thumbSize = getDefaultThumbnailSize(a.getResources());
Michael Jurka8713a942013-10-10 21:28:40 -0700180 // rotation is set to 0 since imageBytes has already been correctly rotated
181 Bitmap thumb = createThumbnail(
182 thumbSize, null, null, imageBytes, null, 0, 0, true);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100183 a.getSavedImages().writeImage(thumb, imageBytes);
184 }
185 };
186 a.cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone);
187 }
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700188 @Override
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100189 public boolean isSelectable() {
190 return true;
191 }
Michael Jurka6b783a02013-10-04 12:26:48 -0700192 @Override
193 public boolean isNamelessWallpaper() {
194 return true;
195 }
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100196 }
197
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700198 public static class FileWallpaperInfo extends WallpaperTileInfo {
199 private File mFile;
200
201 public FileWallpaperInfo(File target, Drawable thumb) {
202 mFile = target;
203 mThumb = thumb;
204 }
205 @Override
206 public void onClick(WallpaperPickerActivity a) {
207 BitmapRegionTileSource.UriBitmapSource bitmapSource =
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700208 new BitmapRegionTileSource.UriBitmapSource(a.getContext(),
209 Uri.fromFile(mFile), 1024);
Sunny Goyal65b929d2015-02-12 15:34:41 -0800210 a.setCropViewTileSource(bitmapSource, false, true, null, null);
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700211 }
212 @Override
213 public void onSave(WallpaperPickerActivity a) {
214 a.setWallpaper(Uri.fromFile(mFile), true);
215 }
216 @Override
217 public boolean isSelectable() {
218 return true;
219 }
220 @Override
221 public boolean isNamelessWallpaper() {
222 return true;
223 }
224 }
225
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100226 public static class ResourceWallpaperInfo extends WallpaperTileInfo {
227 private Resources mResources;
228 private int mResId;
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100229
230 public ResourceWallpaperInfo(Resources res, int resId, Drawable thumb) {
231 mResources = res;
232 mResId = resId;
233 mThumb = thumb;
234 }
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700235 @Override
Sunny Goyal65b929d2015-02-12 15:34:41 -0800236 public void onClick(final WallpaperPickerActivity a) {
Michael Jurka862f7e32013-10-16 18:23:56 -0700237 BitmapRegionTileSource.ResourceBitmapSource bitmapSource =
Michael Jurka83699e52013-10-23 20:59:51 +0200238 new BitmapRegionTileSource.ResourceBitmapSource(
239 mResources, mResId, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
Sunny Goyal65b929d2015-02-12 15:34:41 -0800240 a.setCropViewTileSource(bitmapSource, false, false, new CropViewScaleProvider() {
241
242 @Override
243 public float getScale(TileSource src) {
Sunny Goyal6a1e95a2015-03-20 17:26:30 -0700244 Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
Sunny Goyal65b929d2015-02-12 15:34:41 -0800245 a.getResources(), a.getWindowManager());
246 RectF crop = Utils.getMaxCropRect(
247 src.getImageWidth(), src.getImageHeight(),
248 wallpaperSize.x, wallpaperSize.y, false);
249 return wallpaperSize.x / crop.width();
250 }
251 }, null);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100252 }
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700253 @Override
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100254 public void onSave(WallpaperPickerActivity a) {
255 boolean finishActivityWhenDone = true;
256 a.cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone);
257 }
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700258 @Override
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100259 public boolean isSelectable() {
260 return true;
261 }
Michael Jurka6b783a02013-10-04 12:26:48 -0700262 @Override
263 public boolean isNamelessWallpaper() {
264 return true;
265 }
Michael Jurka104c4562013-07-08 18:03:46 -0700266 }
267
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700268 @TargetApi(Build.VERSION_CODES.KITKAT)
Michael Jurka12ca6132013-10-15 11:14:44 -0700269 public static class DefaultWallpaperInfo extends WallpaperTileInfo {
Michael Jurka12ca6132013-10-15 11:14:44 -0700270 public DefaultWallpaperInfo(Drawable thumb) {
271 mThumb = thumb;
272 }
273 @Override
274 public void onClick(WallpaperPickerActivity a) {
Michael Jurka83699e52013-10-23 20:59:51 +0200275 CropView c = a.getCropView();
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700276 Drawable defaultWallpaper = WallpaperManager.getInstance(a.getContext())
277 .getBuiltInDrawable(c.getWidth(), c.getHeight(), false, 0.5f, 0.5f);
Christoph Studer7084c602014-02-28 15:57:18 +0100278 if (defaultWallpaper == null) {
279 Log.w(TAG, "Null default wallpaper encountered.");
280 c.setTileSource(null, null);
281 return;
282 }
283
Sunny Goyal65b929d2015-02-12 15:34:41 -0800284 LoadRequest req = new LoadRequest();
285 req.moveToLeft = false;
286 req.touchEnabled = false;
287 req.scaleProvider = new CropViewScaleProvider() {
288
289 @Override
290 public float getScale(TileSource src) {
291 return 1f;
292 }
293 };
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700294 req.result = new DrawableTileSource(a.getContext(),
295 defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE);
Sunny Goyal65b929d2015-02-12 15:34:41 -0800296 a.onLoadRequestComplete(req, true);
Michael Jurka12ca6132013-10-15 11:14:44 -0700297 }
298 @Override
299 public void onSave(WallpaperPickerActivity a) {
300 try {
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700301 WallpaperManager.getInstance(a.getContext()).clear();
302 a.setResult(Activity.RESULT_OK);
Michael Jurka12ca6132013-10-15 11:14:44 -0700303 } catch (IOException e) {
304 Log.w("Setting wallpaper to default threw exception", e);
305 }
306 a.finish();
307 }
308 @Override
309 public boolean isSelectable() {
310 return true;
311 }
312 @Override
313 public boolean isNamelessWallpaper() {
314 return true;
315 }
316 }
317
Selim Cinekffed6582014-02-28 17:18:59 +0100318 /**
319 * shows the system wallpaper behind the window and hides the {@link
320 * #mCropView} if visible
321 * @param visible should the system wallpaper be shown
322 */
323 protected void setSystemWallpaperVisiblity(final boolean visible) {
324 // hide our own wallpaper preview if necessary
325 if(!visible) {
326 mCropView.setVisibility(View.VISIBLE);
327 } else {
328 changeWallpaperFlags(visible);
329 }
330 // the change of the flag must be delayed in order to avoid flickering,
331 // a simple post / double post does not suffice here
332 mCropView.postDelayed(new Runnable() {
333 @Override
334 public void run() {
335 if(!visible) {
336 changeWallpaperFlags(visible);
337 } else {
338 mCropView.setVisibility(View.INVISIBLE);
339 }
340 }
341 }, FLAG_POST_DELAY_MILLIS);
342 }
343
Adam Cohen091440a2015-03-18 14:16:05 -0700344 @Thunk void changeWallpaperFlags(boolean visible) {
Selim Cinekffed6582014-02-28 17:18:59 +0100345 int desiredWallpaperFlag = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
346 int currentWallpaperFlag = getWindow().getAttributes().flags
347 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
348 if (desiredWallpaperFlag != currentWallpaperFlag) {
349 getWindow().setFlags(desiredWallpaperFlag,
350 WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
351 }
352 }
353
354 @Override
Sunny Goyal65b929d2015-02-12 15:34:41 -0800355 protected void onLoadRequestComplete(LoadRequest req, boolean success) {
356 super.onLoadRequestComplete(req, success);
357 if (success) {
358 setSystemWallpaperVisiblity(false);
359 }
Selim Cinekffed6582014-02-28 17:18:59 +0100360 }
361
Michael Jurka2d8de582013-09-04 14:42:52 +0200362 // called by onCreate; this is subclassed to overwrite WallpaperCropActivity
363 protected void init() {
Michael Jurka104c4562013-07-08 18:03:46 -0700364 setContentView(R.layout.wallpaper_picker);
365
366 mCropView = (CropView) findViewById(R.id.cropView);
Selim Cinekffed6582014-02-28 17:18:59 +0100367 mCropView.setVisibility(View.INVISIBLE);
368
Sunny Goyal65b929d2015-02-12 15:34:41 -0800369 mProgressView = findViewById(R.id.loading);
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800370 mWallpaperScrollContainer = (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
Michael Jurka4b940602013-09-05 12:14:12 +0200371 mCropView.setTouchCallback(new CropView.TouchCallback() {
Michael Jurka7ad868b2013-12-12 15:04:25 +0100372 ViewPropertyAnimator mAnim;
Michael Jurkae8115d52013-09-20 03:52:24 +0200373 @Override
Michael Jurka4b940602013-09-05 12:14:12 +0200374 public void onTouchDown() {
375 if (mAnim != null) {
376 mAnim.cancel();
377 }
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800378 if (mWallpaperScrollContainer.getAlpha() == 1f) {
Michael Jurka4b940602013-09-05 12:14:12 +0200379 mIgnoreNextTap = true;
380 }
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800381 mAnim = mWallpaperScrollContainer.animate();
Daniel Sandler24f397d2013-10-12 00:02:45 -0400382 mAnim.alpha(0f)
Michael Jurka7ad868b2013-12-12 15:04:25 +0100383 .setDuration(150)
384 .withEndAction(new Runnable() {
385 public void run() {
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800386 mWallpaperScrollContainer.setVisibility(View.INVISIBLE);
Michael Jurka7ad868b2013-12-12 15:04:25 +0100387 }
388 });
Daniel Sandler24f397d2013-10-12 00:02:45 -0400389 mAnim.setInterpolator(new AccelerateInterpolator(0.75f));
Michael Jurka4b940602013-09-05 12:14:12 +0200390 mAnim.start();
391 }
Michael Jurkae8115d52013-09-20 03:52:24 +0200392 @Override
393 public void onTouchUp() {
394 mIgnoreNextTap = false;
395 }
396 @Override
Michael Jurka4b940602013-09-05 12:14:12 +0200397 public void onTap() {
398 boolean ignoreTap = mIgnoreNextTap;
399 mIgnoreNextTap = false;
400 if (!ignoreTap) {
401 if (mAnim != null) {
402 mAnim.cancel();
403 }
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800404 mWallpaperScrollContainer.setVisibility(View.VISIBLE);
405 mAnim = mWallpaperScrollContainer.animate();
Daniel Sandler24f397d2013-10-12 00:02:45 -0400406 mAnim.alpha(1f)
407 .setDuration(150)
408 .setInterpolator(new DecelerateInterpolator(0.75f));
Michael Jurka4b940602013-09-05 12:14:12 +0200409 mAnim.start();
410 }
411 }
412 });
Michael Jurka104c4562013-07-08 18:03:46 -0700413
Michael Jurka2d8de582013-09-04 14:42:52 +0200414 mThumbnailOnClickListener = new OnClickListener() {
415 public void onClick(View v) {
Michael Jurkad6dc6042013-09-10 13:39:59 +0200416 if (mActionMode != null) {
417 // When CAB is up, clicking toggles the item instead
418 if (v.isLongClickable()) {
419 mLongClickListener.onLongClick(v);
420 }
421 return;
422 }
Selim Cinekffed6582014-02-28 17:18:59 +0100423 mSetWallpaperButton.setEnabled(true);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100424 WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
Michael Jurka619a1802013-10-29 15:50:06 +0100425 if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
426 selectTile(v);
Michael Jurka2d8de582013-09-04 14:42:52 +0200427 }
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100428 info.onClick(WallpaperPickerActivity.this);
Michael Jurka2d8de582013-09-04 14:42:52 +0200429 }
430 };
Michael Jurkad6dc6042013-09-10 13:39:59 +0200431 mLongClickListener = new View.OnLongClickListener() {
432 // Called when the user long-clicks on someView
433 public boolean onLongClick(View view) {
434 CheckableFrameLayout c = (CheckableFrameLayout) view;
435 c.toggle();
436
437 if (mActionMode != null) {
438 mActionMode.invalidate();
439 } else {
440 // Start the CAB using the ActionMode.Callback defined below
441 mActionMode = startActionMode(mActionModeCallback);
442 int childCount = mWallpapersView.getChildCount();
443 for (int i = 0; i < childCount; i++) {
444 mWallpapersView.getChildAt(i).setSelected(false);
445 }
446 }
447 return true;
448 }
449 };
Michael Jurka2d8de582013-09-04 14:42:52 +0200450
Michael Jurka104c4562013-07-08 18:03:46 -0700451 // Populate the built-in wallpapers
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700452 ArrayList<WallpaperTileInfo> wallpapers = findBundledWallpapers();
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200453 mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700454 SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(getContext(), wallpapers);
Michael Jurka12ca6132013-10-15 11:14:44 -0700455 populateWallpapersFromAdapter(mWallpapersView, ia, false);
Michael Jurka104c4562013-07-08 18:03:46 -0700456
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200457 // Populate the saved wallpapers
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700458 mSavedImages = new SavedWallpaperImages(getContext());
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200459 mSavedImages.loadThumbnailsAndImageIdList();
Michael Jurka12ca6132013-10-15 11:14:44 -0700460 populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);
Michael Jurka998e4ff2013-09-18 16:04:36 +0200461
462 // Populate the live wallpapers
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100463 final LinearLayout liveWallpapersView =
464 (LinearLayout) findViewById(R.id.live_wallpaper_list);
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700465 final LiveWallpaperListAdapter a = new LiveWallpaperListAdapter(getContext());
Michael Jurka998e4ff2013-09-18 16:04:36 +0200466 a.registerDataSetObserver(new DataSetObserver() {
467 public void onChanged() {
468 liveWallpapersView.removeAllViews();
Michael Jurka12ca6132013-10-15 11:14:44 -0700469 populateWallpapersFromAdapter(liveWallpapersView, a, false);
Michael Jurkafe0ace32013-10-03 01:05:14 -0700470 initializeScrollForRtl();
Michael Jurka6b783a02013-10-04 12:26:48 -0700471 updateTileIndices();
Michael Jurka998e4ff2013-09-18 16:04:36 +0200472 }
473 });
474
475 // Populate the third-party wallpaper pickers
476 final LinearLayout thirdPartyWallpapersView =
477 (LinearLayout) findViewById(R.id.third_party_wallpaper_list);
478 final ThirdPartyWallpaperPickerListAdapter ta =
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700479 new ThirdPartyWallpaperPickerListAdapter(getContext());
Michael Jurka12ca6132013-10-15 11:14:44 -0700480 populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false);
Michael Jurka104c4562013-07-08 18:03:46 -0700481
Michael Jurka104c4562013-07-08 18:03:46 -0700482 // Add a tile for the Gallery
Michael Jurka998e4ff2013-09-18 16:04:36 +0200483 LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
Michael Jurka6b783a02013-10-04 12:26:48 -0700484 FrameLayout pickImageTile = (FrameLayout) getLayoutInflater().
Michael Jurka5b4b6902013-10-03 18:15:08 -0700485 inflate(R.layout.wallpaper_picker_image_picker_item, masterWallpaperList, false);
Michael Jurka6b783a02013-10-04 12:26:48 -0700486 masterWallpaperList.addView(pickImageTile, 0);
Michael Jurka104c4562013-07-08 18:03:46 -0700487
Michael Jurka42a71742013-09-18 00:45:45 +0200488 // Make its background the last photo taken on external storage
489 Bitmap lastPhoto = getThumbnailOfLastPhoto();
490 if (lastPhoto != null) {
491 ImageView galleryThumbnailBg =
Michael Jurka6b783a02013-10-04 12:26:48 -0700492 (ImageView) pickImageTile.findViewById(R.id.wallpaper_image);
Sunny Goyal6f553b92015-02-12 09:46:41 -0800493 galleryThumbnailBg.setImageBitmap(lastPhoto);
Michael Jurka998e4ff2013-09-18 16:04:36 +0200494 int colorOverlay = getResources().getColor(R.color.wallpaper_picker_translucent_gray);
495 galleryThumbnailBg.setColorFilter(colorOverlay, PorterDuff.Mode.SRC_ATOP);
Michael Jurka42a71742013-09-18 00:45:45 +0200496 }
497
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100498 PickImageInfo pickImageInfo = new PickImageInfo();
Michael Jurka6b783a02013-10-04 12:26:48 -0700499 pickImageTile.setTag(pickImageInfo);
500 pickImageInfo.setView(pickImageTile);
501 pickImageTile.setOnClickListener(mThumbnailOnClickListener);
Michael Jurka12ca6132013-10-15 11:14:44 -0700502
Michael Jurka12ca6132013-10-15 11:14:44 -0700503 // Select the first item; wait for a layout pass so that we initialize the dimensions of
504 // cropView or the defaultWallpaperView first
Michael Jurka83699e52013-10-23 20:59:51 +0200505 mCropView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
Michael Jurka12ca6132013-10-15 11:14:44 -0700506 @Override
507 public void onLayoutChange(View v, int left, int top, int right, int bottom,
508 int oldLeft, int oldTop, int oldRight, int oldBottom) {
509 if ((right - left) > 0 && (bottom - top) > 0) {
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800510 if (mSelectedIndex >= 0 && mSelectedIndex < mWallpapersView.getChildCount()) {
511 mThumbnailOnClickListener.onClick(
512 mWallpapersView.getChildAt(mSelectedIndex));
Selim Cinekffed6582014-02-28 17:18:59 +0100513 setSystemWallpaperVisiblity(false);
Michael Jurka12ca6132013-10-15 11:14:44 -0700514 }
515 v.removeOnLayoutChangeListener(this);
516 }
517 }
518 });
Michael Jurka6b783a02013-10-04 12:26:48 -0700519
520 updateTileIndices();
Michael Jurka104c4562013-07-08 18:03:46 -0700521
Michael Jurkafe0ace32013-10-03 01:05:14 -0700522 // Update the scroll for RTL
523 initializeScrollForRtl();
524
Michael Jurkad6dc6042013-09-10 13:39:59 +0200525 // Create smooth layout transitions for when items are deleted
526 final LayoutTransition transitioner = new LayoutTransition();
527 transitioner.setDuration(200);
528 transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
529 transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
530 mWallpapersView.setLayoutTransition(transitioner);
531
Michael Jurka104c4562013-07-08 18:03:46 -0700532 // Action bar
533 // Show the custom action bar view
534 final ActionBar actionBar = getActionBar();
535 actionBar.setCustomView(R.layout.actionbar_set_wallpaper);
536 actionBar.getCustomView().setOnClickListener(
537 new View.OnClickListener() {
538 @Override
539 public void onClick(View v) {
Michael Jurka619a1802013-10-29 15:50:06 +0100540 if (mSelectedTile != null) {
541 WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
Michael Jurkab92f4332013-09-24 12:53:49 +0100542 info.onSave(WallpaperPickerActivity.this);
Selim Cinekffed6582014-02-28 17:18:59 +0100543 } else {
544 // no tile was selected, so we just finish the activity and go back
545 setResult(Activity.RESULT_OK);
546 finish();
Michael Jurkab92f4332013-09-24 12:53:49 +0100547 }
Michael Jurka104c4562013-07-08 18:03:46 -0700548 }
549 });
Michael Jurka849aff72014-01-16 14:58:00 +0100550 mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
Michael Jurkad6dc6042013-09-10 13:39:59 +0200551
552 // CAB for deleting items
553 mActionModeCallback = new ActionMode.Callback() {
554 // Called when the action mode is created; startActionMode() was called
555 @Override
556 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
557 // Inflate a menu resource providing context menu items
558 MenuInflater inflater = mode.getMenuInflater();
559 inflater.inflate(R.menu.cab_delete_wallpapers, menu);
560 return true;
561 }
562
563 private int numCheckedItems() {
564 int childCount = mWallpapersView.getChildCount();
565 int numCheckedItems = 0;
566 for (int i = 0; i < childCount; i++) {
567 CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
568 if (c.isChecked()) {
569 numCheckedItems++;
570 }
571 }
572 return numCheckedItems;
573 }
574
575 // Called each time the action mode is shown. Always called after onCreateActionMode,
576 // but may be called multiple times if the mode is invalidated.
577 @Override
578 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
579 int numCheckedItems = numCheckedItems();
580 if (numCheckedItems == 0) {
581 mode.finish();
582 return true;
583 } else {
584 mode.setTitle(getResources().getQuantityString(
585 R.plurals.number_of_items_selected, numCheckedItems, numCheckedItems));
586 return true;
587 }
588 }
589
590 // Called when the user selects a contextual menu item
591 @Override
592 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Bjorn Bringertc639f8c2013-09-13 13:39:12 +0100593 int itemId = item.getItemId();
594 if (itemId == R.id.menu_delete) {
595 int childCount = mWallpapersView.getChildCount();
596 ArrayList<View> viewsToRemove = new ArrayList<View>();
Selim Cinekffed6582014-02-28 17:18:59 +0100597 boolean selectedTileRemoved = false;
Bjorn Bringertc639f8c2013-09-13 13:39:12 +0100598 for (int i = 0; i < childCount; i++) {
599 CheckableFrameLayout c =
600 (CheckableFrameLayout) mWallpapersView.getChildAt(i);
601 if (c.isChecked()) {
Michael Jurka8a34bdb2013-09-25 07:57:33 -0700602 WallpaperTileInfo info = (WallpaperTileInfo) c.getTag();
603 info.onDelete(WallpaperPickerActivity.this);
Bjorn Bringertc639f8c2013-09-13 13:39:12 +0100604 viewsToRemove.add(c);
Selim Cinekffed6582014-02-28 17:18:59 +0100605 if (i == mSelectedIndex) {
606 selectedTileRemoved = true;
607 }
Michael Jurkad6dc6042013-09-10 13:39:59 +0200608 }
Bjorn Bringertc639f8c2013-09-13 13:39:12 +0100609 }
610 for (View v : viewsToRemove) {
611 mWallpapersView.removeView(v);
612 }
Selim Cinekffed6582014-02-28 17:18:59 +0100613 if (selectedTileRemoved) {
614 mSelectedIndex = -1;
615 mSelectedTile = null;
616 setSystemWallpaperVisiblity(true);
617 }
Michael Jurka6b783a02013-10-04 12:26:48 -0700618 updateTileIndices();
Bjorn Bringertc639f8c2013-09-13 13:39:12 +0100619 mode.finish(); // Action picked, so close the CAB
620 return true;
621 } else {
622 return false;
Michael Jurkad6dc6042013-09-10 13:39:59 +0200623 }
624 }
625
626 // Called when the user exits the action mode
627 @Override
628 public void onDestroyActionMode(ActionMode mode) {
629 int childCount = mWallpapersView.getChildCount();
630 for (int i = 0; i < childCount; i++) {
631 CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
632 c.setChecked(false);
633 }
Selim Cinekffed6582014-02-28 17:18:59 +0100634 if (mSelectedTile != null) {
635 mSelectedTile.setSelected(true);
636 }
Michael Jurkad6dc6042013-09-10 13:39:59 +0200637 mActionMode = null;
638 }
639 };
640 }
Michael Jurka619a1802013-10-29 15:50:06 +0100641
Adam Cohen091440a2015-03-18 14:16:05 -0700642 @Thunk void selectTile(View v) {
Michael Jurka619a1802013-10-29 15:50:06 +0100643 if (mSelectedTile != null) {
644 mSelectedTile.setSelected(false);
645 mSelectedTile = null;
646 }
647 mSelectedTile = v;
648 v.setSelected(true);
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800649 mSelectedIndex = mWallpapersView.indexOfChild(v);
Michael Jurka619a1802013-10-29 15:50:06 +0100650 // TODO: Remove this once the accessibility framework and
651 // services have better support for selection state.
652 v.announceForAccessibility(
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700653 getContext().getString(R.string.announce_selection, v.getContentDescription()));
Michael Jurka862f7e32013-10-16 18:23:56 -0700654 }
Michael Jurka42a71742013-09-18 00:45:45 +0200655
Adam Cohen091440a2015-03-18 14:16:05 -0700656 @Thunk void initializeScrollForRtl() {
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800657 if (mWallpaperScrollContainer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
658 final ViewTreeObserver observer = mWallpaperScrollContainer.getViewTreeObserver();
Michael Jurkafe0ace32013-10-03 01:05:14 -0700659 observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
660 public void onGlobalLayout() {
661 LinearLayout masterWallpaperList =
662 (LinearLayout) findViewById(R.id.master_wallpaper_list);
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800663 mWallpaperScrollContainer.scrollTo(masterWallpaperList.getWidth(), 0);
664 mWallpaperScrollContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Michael Jurkafe0ace32013-10-03 01:05:14 -0700665 }
666 });
667 }
668 }
669
Michael Jurka42a71742013-09-18 00:45:45 +0200670 protected Bitmap getThumbnailOfLastPhoto() {
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700671 Cursor cursor = MediaStore.Images.Media.query(getContext().getContentResolver(),
Michael Jurka42a71742013-09-18 00:45:45 +0200672 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
673 new String[] { MediaStore.Images.ImageColumns._ID,
674 MediaStore.Images.ImageColumns.DATE_TAKEN},
675 null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC LIMIT 1");
Adam Cohenc8d31ff2014-06-12 12:29:50 -0700676
Michael Jurka42a71742013-09-18 00:45:45 +0200677 Bitmap thumb = null;
Adam Cohenc8d31ff2014-06-12 12:29:50 -0700678 if (cursor != null) {
679 if (cursor.moveToNext()) {
680 int id = cursor.getInt(0);
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700681 thumb = MediaStore.Images.Thumbnails.getThumbnail(getContext().getContentResolver(),
Adam Cohenc8d31ff2014-06-12 12:29:50 -0700682 id, MediaStore.Images.Thumbnails.MINI_KIND, null);
683 }
684 cursor.close();
Michael Jurka42a71742013-09-18 00:45:45 +0200685 }
Michael Jurka42a71742013-09-18 00:45:45 +0200686 return thumb;
687 }
Michael Jurka5664de22013-09-12 02:53:22 +0200688
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700689 public void onStop() {
Michael Jurka5664de22013-09-12 02:53:22 +0200690 super.onStop();
Sunny Goyal9c83a0d2015-02-13 10:40:07 -0800691 mWallpaperScrollContainer = (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
692 if (mWallpaperScrollContainer.getAlpha() < 1f) {
693 mWallpaperScrollContainer.setAlpha(1f);
694 mWallpaperScrollContainer.setVisibility(View.VISIBLE);
Michael Jurka5664de22013-09-12 02:53:22 +0200695 }
696 }
697
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700698 public void onSaveInstanceState(Bundle outState) {
Michael Jurkad6dc6042013-09-10 13:39:59 +0200699 outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles);
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800700 outState.putInt(SELECTED_INDEX, mSelectedIndex);
Michael Jurka104c4562013-07-08 18:03:46 -0700701 }
702
Michael Jurkad6dc6042013-09-10 13:39:59 +0200703 protected void onRestoreInstanceState(Bundle savedInstanceState) {
704 ArrayList<Uri> uris = savedInstanceState.getParcelableArrayList(TEMP_WALLPAPER_TILES);
705 for (Uri uri : uris) {
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800706 addTemporaryWallpaperTile(uri, true);
Michael Jurkad6dc6042013-09-10 13:39:59 +0200707 }
Selim Cinekffed6582014-02-28 17:18:59 +0100708 mSelectedIndex = savedInstanceState.getInt(SELECTED_INDEX, -1);
Michael Jurkad6dc6042013-09-10 13:39:59 +0200709 }
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200710
Adam Cohen091440a2015-03-18 14:16:05 -0700711 @Thunk void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter,
Michael Jurka12ca6132013-10-15 11:14:44 -0700712 boolean addLongPressHandler) {
Michael Jurka998e4ff2013-09-18 16:04:36 +0200713 for (int i = 0; i < adapter.getCount(); i++) {
714 FrameLayout thumbnail = (FrameLayout) adapter.getView(i, null, parent);
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200715 parent.addView(thumbnail, i);
Michael Jurka6b783a02013-10-04 12:26:48 -0700716 WallpaperTileInfo info = (WallpaperTileInfo) adapter.getItem(i);
717 thumbnail.setTag(info);
718 info.setView(thumbnail);
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200719 if (addLongPressHandler) {
720 addLongPressHandler(thumbnail);
721 }
722 thumbnail.setOnClickListener(mThumbnailOnClickListener);
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200723 }
724 }
725
Adam Cohen091440a2015-03-18 14:16:05 -0700726 @Thunk void updateTileIndices() {
Michael Jurka6b783a02013-10-04 12:26:48 -0700727 LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
728 final int childCount = masterWallpaperList.getChildCount();
Michael Jurka6b783a02013-10-04 12:26:48 -0700729 final Resources res = getResources();
730
731 // Do two passes; the first pass gets the total number of tiles
732 int numTiles = 0;
733 for (int passNum = 0; passNum < 2; passNum++) {
734 int tileIndex = 0;
735 for (int i = 0; i < childCount; i++) {
736 View child = masterWallpaperList.getChildAt(i);
737 LinearLayout subList;
738
739 int subListStart;
740 int subListEnd;
741 if (child.getTag() instanceof WallpaperTileInfo) {
742 subList = masterWallpaperList;
743 subListStart = i;
744 subListEnd = i + 1;
745 } else { // if (child instanceof LinearLayout) {
746 subList = (LinearLayout) child;
747 subListStart = 0;
748 subListEnd = subList.getChildCount();
749 }
750
751 for (int j = subListStart; j < subListEnd; j++) {
752 WallpaperTileInfo info = (WallpaperTileInfo) subList.getChildAt(j).getTag();
753 if (info.isNamelessWallpaper()) {
754 if (passNum == 0) {
755 numTiles++;
756 } else {
757 CharSequence label = res.getString(
758 R.string.wallpaper_accessibility_name, ++tileIndex, numTiles);
759 info.onIndexUpdated(label);
760 }
761 }
762 }
763 }
764 }
765 }
766
Adam Cohen091440a2015-03-18 14:16:05 -0700767 @Thunk static Point getDefaultThumbnailSize(Resources res) {
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100768 return new Point(res.getDimensionPixelSize(R.dimen.wallpaperThumbnailWidth),
769 res.getDimensionPixelSize(R.dimen.wallpaperThumbnailHeight));
770
771 }
772
Adam Cohen091440a2015-03-18 14:16:05 -0700773 @Thunk static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes,
Michael Jurka8713a942013-10-10 21:28:40 -0700774 Resources res, int resId, int rotation, boolean leftAligned) {
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100775 int width = size.x;
776 int height = size.y;
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200777
778 BitmapCropTask cropTask;
779 if (uri != null) {
Michael Jurka8713a942013-10-10 21:28:40 -0700780 cropTask = new BitmapCropTask(
781 context, uri, null, rotation, width, height, false, true, null);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100782 } else if (imageBytes != null) {
Michael Jurka8713a942013-10-10 21:28:40 -0700783 cropTask = new BitmapCropTask(
784 imageBytes, null, rotation, width, height, false, true, null);
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100785 } else {
Michael Jurka8713a942013-10-10 21:28:40 -0700786 cropTask = new BitmapCropTask(
787 context, res, resId, null, rotation, width, height, false, true, null);
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200788 }
789 Point bounds = cropTask.getImageBounds();
Michael Jurkadb84e822013-09-23 23:02:05 +0100790 if (bounds == null || bounds.x == 0 || bounds.y == 0) {
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200791 return null;
792 }
793
Michael Jurka8713a942013-10-10 21:28:40 -0700794 Matrix rotateMatrix = new Matrix();
795 rotateMatrix.setRotate(rotation);
796 float[] rotatedBounds = new float[] { bounds.x, bounds.y };
797 rotateMatrix.mapPoints(rotatedBounds);
798 rotatedBounds[0] = Math.abs(rotatedBounds[0]);
799 rotatedBounds[1] = Math.abs(rotatedBounds[1]);
800
Sunny Goyal06a4d3f2015-02-12 11:19:39 -0800801 RectF cropRect = Utils.getMaxCropRect(
Michael Jurka8713a942013-10-10 21:28:40 -0700802 (int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned);
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200803 cropTask.setCropBounds(cropRect);
804
805 if (cropTask.cropBitmap()) {
806 return cropTask.getCroppedBitmap();
807 } else {
808 return null;
809 }
810 }
811
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800812 private void addTemporaryWallpaperTile(final Uri uri, boolean fromRestore) {
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200813 mTempWallpaperTiles.add(uri);
814 // Add a tile for the image picked from Gallery
Michael Jurka619a1802013-10-29 15:50:06 +0100815 final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200816 inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
Michael Jurka619a1802013-10-29 15:50:06 +0100817 pickedImageThumbnail.setVisibility(View.GONE);
Michael Jurka862f7e32013-10-16 18:23:56 -0700818 mWallpapersView.addView(pickedImageThumbnail, 0);
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200819
820 // Load the thumbnail
Michael Jurka862f7e32013-10-16 18:23:56 -0700821 final ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
822 final Point defaultSize = getDefaultThumbnailSize(this.getResources());
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700823 final Context context = getContext();
Michael Jurka862f7e32013-10-16 18:23:56 -0700824 new AsyncTask<Void, Bitmap, Bitmap>() {
825 protected Bitmap doInBackground(Void...args) {
Adam Cohen8dc6e1b2014-07-24 10:39:57 -0700826 try {
Sunny Goyal06a4d3f2015-02-12 11:19:39 -0800827 int rotation = BitmapUtils.getRotationFromExif(context, uri);
Adam Cohen8dc6e1b2014-07-24 10:39:57 -0700828 return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
829 } catch (SecurityException securityException) {
830 if (isDestroyed()) {
831 // Temporarily granted permissions are revoked when the activity
832 // finishes, potentially resulting in a SecurityException here.
833 // Even though {@link #isDestroyed} might also return true in different
834 // situations where the configuration changes, we are fine with
835 // catching these cases here as well.
836 cancel(false);
837 } else {
838 // otherwise it had a different cause and we throw it further
839 throw securityException;
840 }
841 return null;
842 }
Michael Jurka862f7e32013-10-16 18:23:56 -0700843 }
844 protected void onPostExecute(Bitmap thumb) {
Adam Cohen8dc6e1b2014-07-24 10:39:57 -0700845 if (!isCancelled() && thumb != null) {
Michael Jurka862f7e32013-10-16 18:23:56 -0700846 image.setImageBitmap(thumb);
847 Drawable thumbDrawable = image.getDrawable();
848 thumbDrawable.setDither(true);
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800849 pickedImageThumbnail.setVisibility(View.VISIBLE);
Michael Jurka862f7e32013-10-16 18:23:56 -0700850 } else {
851 Log.e(TAG, "Error loading thumbnail for uri=" + uri);
852 }
853 }
854 }.execute();
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200855
Michael Jurka1e4e6dd2013-09-23 23:02:05 +0100856 UriWallpaperInfo info = new UriWallpaperInfo(uri);
857 pickedImageThumbnail.setTag(info);
Michael Jurka6b783a02013-10-04 12:26:48 -0700858 info.setView(pickedImageThumbnail);
Michael Jurka8713a942013-10-10 21:28:40 -0700859 addLongPressHandler(pickedImageThumbnail);
Michael Jurka7b715492013-10-09 11:22:34 -0700860 updateTileIndices();
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200861 pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener);
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800862 if (!fromRestore) {
863 mThumbnailOnClickListener.onClick(pickedImageThumbnail);
864 }
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200865 }
866
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700867 public void onActivityResult(int requestCode, int resultCode, Intent data) {
868 if (requestCode == IMAGE_PICK && resultCode == Activity.RESULT_OK) {
Michael Jurka2fe15302013-10-04 12:35:27 -0700869 if (data != null && data.getData() != null) {
870 Uri uri = data.getData();
Jorim Jaggi1b921ef2014-01-14 16:00:17 -0800871 addTemporaryWallpaperTile(uri, false);
Michael Jurka2fe15302013-10-04 12:35:27 -0700872 }
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700873 } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY
874 && resultCode == Activity.RESULT_OK) {
Sunny Goyalfddef462015-02-12 09:51:48 -0800875 // Something was set on the third-party activity.
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700876 setResult(Activity.RESULT_OK);
Michael Jurka2d8de582013-09-04 14:42:52 +0200877 finish();
878 }
879 }
880
Michael Jurkabe2f8dd2013-09-10 13:39:59 +0200881 private void addLongPressHandler(View v) {
882 v.setOnLongClickListener(mLongClickListener);
883 }
884
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700885 private ArrayList<WallpaperTileInfo> findBundledWallpapers() {
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700886 final PackageManager pm = getContext().getPackageManager();
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700887 final ArrayList<WallpaperTileInfo> bundled = new ArrayList<WallpaperTileInfo>(24);
Jeff Sharkey5aeef582014-04-14 13:26:42 -0700888
889 Partner partner = Partner.get(pm);
890 if (partner != null) {
891 final Resources partnerRes = partner.getResources();
Adam Cohen4ae96ce2014-08-29 15:05:48 -0700892 final int resId = partnerRes.getIdentifier(Partner.RES_WALLPAPERS, "array",
Jeff Sharkey5aeef582014-04-14 13:26:42 -0700893 partner.getPackageName());
894 if (resId != 0) {
895 addWallpapers(bundled, partnerRes, partner.getPackageName(), resId);
896 }
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700897
898 // Add system wallpapers
899 File systemDir = partner.getWallpaperDirectory();
900 if (systemDir != null && systemDir.isDirectory()) {
901 for (File file : systemDir.listFiles()) {
902 if (!file.isFile()) {
903 continue;
904 }
905 String name = file.getName();
906 int dotPos = name.lastIndexOf('.');
907 String extension = "";
908 if (dotPos >= -1) {
909 extension = name.substring(dotPos);
910 name = name.substring(0, dotPos);
911 }
912
913 if (name.endsWith("_small")) {
914 // it is a thumbnail
915 continue;
916 }
917
918 File thumbnail = new File(systemDir, name + "_small" + extension);
919 Bitmap thumb = BitmapFactory.decodeFile(thumbnail.getAbsolutePath());
920 if (thumb != null) {
921 bundled.add(new FileWallpaperInfo(file, new BitmapDrawable(thumb)));
922 }
923 }
924 }
Jeff Sharkey5aeef582014-04-14 13:26:42 -0700925 }
Michael Jurka104c4562013-07-08 18:03:46 -0700926
Michael Jurkaeadbfc52013-09-04 00:45:37 +0200927 Pair<ApplicationInfo, Integer> r = getWallpaperArrayResourceId();
928 if (r != null) {
929 try {
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700930 Resources wallpaperRes = getContext().getPackageManager()
931 .getResourcesForApplication(r.first);
Jeff Sharkey5aeef582014-04-14 13:26:42 -0700932 addWallpapers(bundled, wallpaperRes, r.first.packageName, r.second);
Michael Jurkaeadbfc52013-09-04 00:45:37 +0200933 } catch (PackageManager.NameNotFoundException e) {
934 }
935 }
Michael Jurkadb84e822013-09-23 23:02:05 +0100936
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -0700937 if (partner == null || !partner.hideDefaultWallpaper()) {
938 // Add an entry for the default wallpaper (stored in system resources)
939 WallpaperTileInfo defaultWallpaperInfo =
940 (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
941 ? getPreKKDefaultWallpaperInfo()
942 : getDefaultWallpaper();
Michael Jurka12ca6132013-10-15 11:14:44 -0700943 if (defaultWallpaperInfo != null) {
Jeff Sharkey5aeef582014-04-14 13:26:42 -0700944 bundled.add(0, defaultWallpaperInfo);
Michael Jurka12ca6132013-10-15 11:14:44 -0700945 }
Michael Jurkadb84e822013-09-23 23:02:05 +0100946 }
Jeff Sharkey5aeef582014-04-14 13:26:42 -0700947 return bundled;
Michael Jurkaeadbfc52013-09-04 00:45:37 +0200948 }
949
Michael Jurka12ca6132013-10-15 11:14:44 -0700950 private boolean writeImageToFileAsJpeg(File f, Bitmap b) {
951 try {
952 f.createNewFile();
953 FileOutputStream thumbFileStream =
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700954 getContext().openFileOutput(f.getName(), Context.MODE_PRIVATE);
Michael Jurka12ca6132013-10-15 11:14:44 -0700955 b.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
956 thumbFileStream.close();
957 return true;
958 } catch (IOException e) {
959 Log.e(TAG, "Error while writing bitmap to file " + e);
960 f.delete();
961 }
962 return false;
963 }
964
Sunny Goyal0af0d842014-08-13 12:12:48 -0700965 private File getDefaultThumbFile() {
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700966 return new File(getContext().getFilesDir(), Build.VERSION.SDK_INT
Helena Josol28db2802014-10-09 17:04:09 +0100967 + "_" + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL);
Sunny Goyal0af0d842014-08-13 12:12:48 -0700968 }
969
970 private boolean saveDefaultWallpaperThumb(Bitmap b) {
971 // Delete old thumbnails.
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700972 new File(getContext().getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL_OLD).delete();
973 new File(getContext().getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
Sunny Goyal0af0d842014-08-13 12:12:48 -0700974
975 for (int i = Build.VERSION_CODES.JELLY_BEAN; i < Build.VERSION.SDK_INT; i++) {
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700976 new File(getContext().getFilesDir(), i + "_"
977 + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
Sunny Goyal0af0d842014-08-13 12:12:48 -0700978 }
979 return writeImageToFileAsJpeg(getDefaultThumbFile(), b);
980 }
981
Michael Jurka12ca6132013-10-15 11:14:44 -0700982 private ResourceWallpaperInfo getPreKKDefaultWallpaperInfo() {
Michael Jurkadb84e822013-09-23 23:02:05 +0100983 Resources sysRes = Resources.getSystem();
984 int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android");
985
Sunny Goyal0af0d842014-08-13 12:12:48 -0700986 File defaultThumbFile = getDefaultThumbFile();
Michael Jurkadb84e822013-09-23 23:02:05 +0100987 Bitmap thumb = null;
988 boolean defaultWallpaperExists = false;
989 if (defaultThumbFile.exists()) {
990 thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath());
991 defaultWallpaperExists = true;
992 } else {
Michael Jurka8713a942013-10-10 21:28:40 -0700993 Resources res = getResources();
994 Point defaultThumbSize = getDefaultThumbnailSize(res);
Sunny Goyal06a4d3f2015-02-12 11:19:39 -0800995 int rotation = BitmapUtils.getRotationFromExif(res, resId);
Michael Jurka8713a942013-10-10 21:28:40 -0700996 thumb = createThumbnail(
Sunny Goyal1d0b0932015-03-20 18:51:38 -0700997 defaultThumbSize, getContext(), null, null, sysRes, resId, rotation, false);
Michael Jurkadb84e822013-09-23 23:02:05 +0100998 if (thumb != null) {
Sunny Goyal0af0d842014-08-13 12:12:48 -0700999 defaultWallpaperExists = saveDefaultWallpaperThumb(thumb);
Michael Jurkadb84e822013-09-23 23:02:05 +01001000 }
1001 }
1002 if (defaultWallpaperExists) {
1003 return new ResourceWallpaperInfo(sysRes, resId, new BitmapDrawable(thumb));
1004 }
1005 return null;
1006 }
1007
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -07001008 @TargetApi(Build.VERSION_CODES.KITKAT)
Michael Jurka12ca6132013-10-15 11:14:44 -07001009 private DefaultWallpaperInfo getDefaultWallpaper() {
Sunny Goyal0af0d842014-08-13 12:12:48 -07001010 File defaultThumbFile = getDefaultThumbFile();
Michael Jurka12ca6132013-10-15 11:14:44 -07001011 Bitmap thumb = null;
1012 boolean defaultWallpaperExists = false;
1013 if (defaultThumbFile.exists()) {
1014 thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath());
1015 defaultWallpaperExists = true;
1016 } else {
1017 Resources res = getResources();
1018 Point defaultThumbSize = getDefaultThumbnailSize(res);
Sunny Goyal1d0b0932015-03-20 18:51:38 -07001019 Drawable wallpaperDrawable = WallpaperManager.getInstance(getContext()).getBuiltInDrawable(
Michael Jurka12ca6132013-10-15 11:14:44 -07001020 defaultThumbSize.x, defaultThumbSize.y, true, 0.5f, 0.5f);
1021 if (wallpaperDrawable != null) {
1022 thumb = Bitmap.createBitmap(
1023 defaultThumbSize.x, defaultThumbSize.y, Bitmap.Config.ARGB_8888);
1024 Canvas c = new Canvas(thumb);
Michael Jurkaa7d82b92013-11-08 15:45:48 +01001025 wallpaperDrawable.setBounds(0, 0, defaultThumbSize.x, defaultThumbSize.y);
Michael Jurka12ca6132013-10-15 11:14:44 -07001026 wallpaperDrawable.draw(c);
1027 c.setBitmap(null);
1028 }
1029 if (thumb != null) {
Sunny Goyal0af0d842014-08-13 12:12:48 -07001030 defaultWallpaperExists = saveDefaultWallpaperThumb(thumb);
Michael Jurka12ca6132013-10-15 11:14:44 -07001031 }
1032 }
1033 if (defaultWallpaperExists) {
1034 return new DefaultWallpaperInfo(new BitmapDrawable(thumb));
1035 }
1036 return null;
1037 }
1038
Michael Jurkaeadbfc52013-09-04 00:45:37 +02001039 public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() {
Michael Jurka104c4562013-07-08 18:03:46 -07001040 // Context.getPackageName() may return the "original" package name,
1041 // com.android.launcher3; Resources needs the real package name,
1042 // com.android.launcher3. So we ask Resources for what it thinks the
1043 // package name should be.
Michael Jurkaeadbfc52013-09-04 00:45:37 +02001044 final String packageName = getResources().getResourcePackageName(R.array.wallpapers);
1045 try {
Sunny Goyal1d0b0932015-03-20 18:51:38 -07001046 ApplicationInfo info = getContext().getPackageManager().getApplicationInfo(packageName, 0);
Michael Jurkaeadbfc52013-09-04 00:45:37 +02001047 return new Pair<ApplicationInfo, Integer>(info, R.array.wallpapers);
1048 } catch (PackageManager.NameNotFoundException e) {
1049 return null;
1050 }
Michael Jurka104c4562013-07-08 18:03:46 -07001051 }
1052
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -07001053 private void addWallpapers(ArrayList<WallpaperTileInfo> known, Resources res,
Jeff Sharkey5aeef582014-04-14 13:26:42 -07001054 String packageName, int listResId) {
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001055 final String[] extras = res.getStringArray(listResId);
Michael Jurka104c4562013-07-08 18:03:46 -07001056 for (String extra : extras) {
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001057 int resId = res.getIdentifier(extra, "drawable", packageName);
1058 if (resId != 0) {
1059 final int thumbRes = res.getIdentifier(extra + "_small", "drawable", packageName);
Michael Jurka104c4562013-07-08 18:03:46 -07001060
1061 if (thumbRes != 0) {
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001062 ResourceWallpaperInfo wallpaperInfo =
1063 new ResourceWallpaperInfo(res, resId, res.getDrawable(thumbRes));
Jeff Sharkey5aeef582014-04-14 13:26:42 -07001064 known.add(wallpaperInfo);
Michael Jurka104c4562013-07-08 18:03:46 -07001065 // Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");
1066 }
Michael Jurka6218e5b2013-09-10 14:07:20 +02001067 } else {
1068 Log.e(TAG, "Couldn't find wallpaper " + extra);
Michael Jurka104c4562013-07-08 18:03:46 -07001069 }
1070 }
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001071 }
1072
1073 public CropView getCropView() {
1074 return mCropView;
1075 }
1076
1077 public SavedWallpaperImages getSavedImages() {
1078 return mSavedImages;
1079 }
1080
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -07001081 private static class SimpleWallpapersAdapter extends ArrayAdapter<WallpaperTileInfo> {
1082 private final LayoutInflater mLayoutInflater;
Michael Jurka104c4562013-07-08 18:03:46 -07001083
Sunny Goyal1d0b0932015-03-20 18:51:38 -07001084 SimpleWallpapersAdapter(Context context, ArrayList<WallpaperTileInfo> wallpapers) {
1085 super(context, R.layout.wallpaper_picker_item, wallpapers);
1086 mLayoutInflater = LayoutInflater.from(context);
Michael Jurka104c4562013-07-08 18:03:46 -07001087 }
1088
1089 public View getView(int position, View convertView, ViewGroup parent) {
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -07001090 Drawable thumb = getItem(position).mThumb;
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001091 if (thumb == null) {
Michael Jurkaeadbfc52013-09-04 00:45:37 +02001092 Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
Michael Jurka104c4562013-07-08 18:03:46 -07001093 }
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -07001094 return createImageTileView(mLayoutInflater, convertView, parent, thumb);
Michael Jurka104c4562013-07-08 18:03:46 -07001095 }
1096 }
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001097
Sunny Goyalcdc4dbd2014-07-16 16:04:08 -07001098 public static View createImageTileView(LayoutInflater layoutInflater,
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001099 View convertView, ViewGroup parent, Drawable thumb) {
1100 View view;
1101
1102 if (convertView == null) {
1103 view = layoutInflater.inflate(R.layout.wallpaper_picker_item, parent, false);
1104 } else {
1105 view = convertView;
1106 }
1107
Michael Jurka1e4e6dd2013-09-23 23:02:05 +01001108 ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);
1109
1110 if (thumb != null) {
1111 image.setImageDrawable(thumb);
1112 thumb.setDither(true);
1113 }
1114
1115 return view;
1116 }
Michael Jurka7ad868b2013-12-12 15:04:25 +01001117
Michael Jurka7ad868b2013-12-12 15:04:25 +01001118 public void startActivityForResultSafely(Intent intent, int requestCode) {
Sunny Goyal1d0b0932015-03-20 18:51:38 -07001119 Utilities.startActivityForResultSafely(getActivity(), intent, requestCode);
Sunny Goyal6a1e95a2015-03-20 17:26:30 -07001120 }
1121
1122 @Override
1123 public boolean enableRotation() {
Sunny Goyal1d0b0932015-03-20 18:51:38 -07001124 return Utilities.isRotationEnabled(getContext());
Michael Jurka7ad868b2013-12-12 15:04:25 +01001125 }
Michael Jurka104c4562013-07-08 18:03:46 -07001126}