blob: 7e0da5ea597aa265ea7c6c398002aa36f10cab7b [file] [log] [blame]
Jon Miranda16ea1b12017-12-12 14:52:48 -08001/*
2 * Copyright (C) 2017 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 */
16package com.android.wallpaper.picker;
17
Jon Miranda16ea1b12017-12-12 14:52:48 -080018import android.app.Activity;
19import android.app.ProgressDialog;
Jon Miranda16ea1b12017-12-12 14:52:48 -080020import android.content.Context;
21import android.content.Intent;
Jon Miranda16ea1b12017-12-12 14:52:48 -080022import android.graphics.Color;
23import android.graphics.Point;
24import android.graphics.PorterDuff.Mode;
25import android.graphics.drawable.Drawable;
26import android.net.Uri;
27import android.os.AsyncTask;
28import android.os.Build.VERSION;
29import android.os.Build.VERSION_CODES;
30import android.os.Bundle;
Jon Miranda16ea1b12017-12-12 14:52:48 -080031import android.util.Log;
32import android.view.View;
33import android.view.View.OnClickListener;
34import android.widget.Button;
35import android.widget.FrameLayout;
36import android.widget.ImageView;
37import android.widget.LinearLayout;
38import android.widget.TextView;
39
Santiago Etchebehere635e96f2018-12-04 18:31:34 -080040import androidx.annotation.NonNull;
41import androidx.annotation.Nullable;
42import androidx.appcompat.app.AlertDialog;
43import androidx.appcompat.widget.Toolbar;
44import androidx.fragment.app.Fragment;
45import androidx.fragment.app.FragmentManager;
46
Jon Miranda16ea1b12017-12-12 14:52:48 -080047import com.android.wallpaper.R;
48import com.android.wallpaper.asset.Asset;
49import com.android.wallpaper.compat.ButtonDrawableSetterCompat;
Jon Miranda16ea1b12017-12-12 14:52:48 -080050import com.android.wallpaper.config.Flags;
51import com.android.wallpaper.model.Category;
Jon Miranda16ea1b12017-12-12 14:52:48 -080052import com.android.wallpaper.model.ImageWallpaperInfo;
Jon Miranda16ea1b12017-12-12 14:52:48 -080053import com.android.wallpaper.model.WallpaperInfo;
54import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
55import com.android.wallpaper.module.CurrentWallpaperInfoFactory.WallpaperInfoCallback;
56import com.android.wallpaper.module.DailyLoggingAlarmScheduler;
57import com.android.wallpaper.module.ExploreIntentChecker;
58import com.android.wallpaper.module.FormFactorChecker;
Jon Miranda16ea1b12017-12-12 14:52:48 -080059import com.android.wallpaper.module.Injector;
60import com.android.wallpaper.module.InjectorProvider;
61import com.android.wallpaper.module.NetworkStatusNotifier;
62import com.android.wallpaper.module.NetworkStatusNotifier.NetworkStatus;
63import com.android.wallpaper.module.UserEventLogger;
64import com.android.wallpaper.module.UserEventLogger.WallpaperSetFailureReason;
65import com.android.wallpaper.module.WallpaperPersister;
66import com.android.wallpaper.module.WallpaperPersister.Destination;
67import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
68import com.android.wallpaper.module.WallpaperPersister.WallpaperPosition;
69import com.android.wallpaper.module.WallpaperPreferences;
70import com.android.wallpaper.module.WallpaperPreferences.PresentationMode;
71import com.android.wallpaper.module.WallpaperRotationRefresher;
72import com.android.wallpaper.module.WallpaperRotationRefresher.Listener;
Santiago Etchebehere635e96f2018-12-04 18:31:34 -080073import com.android.wallpaper.picker.CategoryFragment.CategoryFragmentHost;
Jon Miranda16ea1b12017-12-12 14:52:48 -080074import com.android.wallpaper.picker.WallpaperDisabledFragment.WallpaperSupportLevel;
Jon Miranda16ea1b12017-12-12 14:52:48 -080075import com.android.wallpaper.picker.individual.IndividualPickerFragment;
76import com.android.wallpaper.util.ScreenSizeCalculator;
77import com.android.wallpaper.util.ThrowableAnalyzer;
78
Sunny Goyal8600a3f2018-08-15 12:48:01 -070079import com.google.android.material.bottomsheet.BottomSheetBehavior;
80import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback;
81import com.google.android.material.tabs.TabLayout;
82import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
83import com.google.android.material.tabs.TabLayout.Tab;
84
Jon Miranda16ea1b12017-12-12 14:52:48 -080085import java.util.List;
86
87/**
88 * Activity allowing users to select a category of wallpapers to choose from.
89 */
90public class TopLevelPickerActivity extends BaseActivity implements WallpapersUiContainer,
91 CurrentWallpaperBottomSheetPresenter, SetWallpaperErrorDialogFragment.Listener,
Santiago Etchebeherefab49612019-01-15 12:22:42 -080092 MyPhotosStarter, CategoryFragmentHost {
Jon Miranda16ea1b12017-12-12 14:52:48 -080093
94 private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
95 "toplevel_set_wallpaper_error_dialog";
96
97 private static final String TAG = "TopLevelPicker";
98 private static final String KEY_SELECTED_CATEGORY_TAB = "selected_category_tab";
99
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800100 private WallpaperPickerDelegate mDelegate;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800101 private int mLastSelectedCategoryTabIndex;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800102 private UserEventLogger mUserEventLogger;
103 private NetworkStatusNotifier mNetworkStatusNotifier;
104 private NetworkStatusNotifier.Listener mNetworkStatusListener;
105 private WallpaperPersister mWallpaperPersister;
106 private boolean mWasCustomPhotoWallpaperSet;
107 @WallpaperPosition
108 private int mCustomPhotoWallpaperPosition;
109
110 /**
111 * Progress dialogs for "refresh daily wallpaper" and "set wallpaper" operations.
112 */
113 private ProgressDialog mRefreshWallpaperProgressDialog;
114 private ProgressDialog mSetWallpaperProgressDialog;
115
116 /**
117 * Designates a test mode of operation -- in which certain UI features are disabled to allow for
118 * UI tests to run correctly.
119 */
120 private boolean mTestingMode;
121
122 /**
123 * UI for the "currently set wallpaper" BottomSheet.
124 */
125 private LinearLayout mBottomSheet;
126 private ImageView mCurrentWallpaperImage;
127 private TextView mCurrentWallpaperPresentationMode;
128 private TextView mCurrentWallpaperTitle;
129 private TextView mCurrentWallpaperSubtitle;
130 private Button mCurrentWallpaperExploreButton;
131 private Button mCurrentWallpaperSkipWallpaperButton;
132 private FrameLayout mFragmentContainer;
133 private FrameLayout mLoadingIndicatorContainer;
134 private LinearLayout mWallpaperPositionOptions;
135
Jon Miranda16ea1b12017-12-12 14:52:48 -0800136 /**
137 * Staged error dialog fragments that were unable to be shown when the activity didn't allow
138 * committing fragment transactions.
139 */
140 private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;
141
142 /**
143 * A wallpaper pending set to the device--we retain a reference to this in order to facilitate
144 * retry or re-crop operations.
145 */
146 private WallpaperInfo mPendingSetWallpaperInfo;
147
148 private static int getTextColorIdForWallpaperPositionButton(boolean isSelected) {
149 return isSelected ? R.color.accent_color : R.color.material_grey500;
150 }
151
152 @Override
153 protected void onCreate(Bundle savedInstanceState) {
154 super.onCreate(savedInstanceState);
155
Jon Miranda16ea1b12017-12-12 14:52:48 -0800156 mLastSelectedCategoryTabIndex = -1;
157
158 Injector injector = InjectorProvider.getInjector();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800159 mDelegate = new WallpaperPickerDelegate(this, this, injector);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800160 mUserEventLogger = injector.getUserEventLogger(this);
161 mNetworkStatusNotifier = injector.getNetworkStatusNotifier(this);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800162 mWallpaperPersister = injector.getWallpaperPersister(this);
163 mWasCustomPhotoWallpaperSet = false;
164
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800165 @WallpaperSupportLevel int wallpaperSupportLevel = mDelegate.getWallpaperSupportLevel();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800166 if (wallpaperSupportLevel != WallpaperDisabledFragment.SUPPORTED_CAN_SET) {
167 setContentView(R.layout.activity_single_fragment);
168
169 FragmentManager fm = getSupportFragmentManager();
170 WallpaperDisabledFragment wallpaperDisabledFragment =
171 WallpaperDisabledFragment.newInstance(wallpaperSupportLevel);
172 fm.beginTransaction()
173 .add(R.id.fragment_container, wallpaperDisabledFragment)
174 .commit();
175 return;
176 }
177
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800178 if (mDelegate.getFormFactor() == FormFactorChecker.FORM_FACTOR_MOBILE) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800179 initializeMobile();
180 } else { // DESKTOP
181 initializeDesktop(savedInstanceState);
182 }
183 }
184
185 @Override
186 protected void onResume() {
187 super.onResume();
Santiago Etchebeherebd536c62019-04-09 15:25:51 -0300188 mUserEventLogger.logResumed();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800189 // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is one
190 // that was unable to be shown earlier when this fragment's hosting activity didn't allow
191 // committing fragment transactions.
192 if (mStagedSetWallpaperErrorDialogFragment != null) {
193 mStagedSetWallpaperErrorDialogFragment.show(
194 getSupportFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
195 mStagedSetWallpaperErrorDialogFragment = null;
196 }
197 }
198
199 @Override
Santiago Etchebeherebd536c62019-04-09 15:25:51 -0300200 protected void onStop() {
201 mUserEventLogger.logStopped();
202 super.onStop();
203 }
204
205 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800206 protected void onDestroy() {
207 super.onDestroy();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800208 mDelegate.cleanUp();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800209 if (mNetworkStatusListener != null) {
210 mNetworkStatusNotifier.unregisterListener(mNetworkStatusListener);
211 }
212
213 if (mRefreshWallpaperProgressDialog != null) {
214 mRefreshWallpaperProgressDialog.dismiss();
215 }
216 if (mSetWallpaperProgressDialog != null) {
217 mSetWallpaperProgressDialog.dismiss();
218 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800219 }
220
221 @Override
222 public void requestCustomPhotoPicker(PermissionChangedListener listener) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800223 mDelegate.requestCustomPhotoPicker(listener);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800224 }
225
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800226 @Override
227 public void requestExternalStoragePermission(PermissionChangedListener listener) {
228 mDelegate.requestExternalStoragePermission(listener);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800229 }
230
231 /**
232 * Returns whether READ_EXTERNAL_STORAGE has been granted for the application.
233 */
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800234 public boolean isReadExternalStoragePermissionGranted() {
235 return mDelegate.isReadExternalStoragePermissionGranted();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800236 }
237
238 private void initializeMobile() {
Santiago Etchebehere008368d2018-12-13 15:23:17 -0800239 setContentView(R.layout.activity_single_fragment);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800240
241 // Set toolbar as the action bar.
242 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
243 setSupportActionBar(toolbar);
244
245 FragmentManager fm = getSupportFragmentManager();
246 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
247
248 boolean forceCategoryRefresh = false;
249 if (fragment == null) {
250 // App launch specific logic: log the "app launched" event and set up daily logging.
251 mUserEventLogger.logAppLaunched();
252 DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());
253
Santiago Etchebehereaa35e6e2019-01-25 10:30:11 -0800254 CategoryFragment newFragment = CategoryFragment.newInstance(
255 getString(R.string.wallpaper_app_name));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800256 fm.beginTransaction()
257 .add(R.id.fragment_container, newFragment)
258 .commit();
259
260 forceCategoryRefresh = true;
261 }
262
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800263 mDelegate.initialize(forceCategoryRefresh);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800264 }
265
266 private void initializeDesktop(Bundle savedInstanceState) {
267 setContentView(R.layout.activity_top_level_desktop);
268
269 mBottomSheet = (LinearLayout) findViewById(R.id.bottom_sheet);
270 mCurrentWallpaperImage = (ImageView) mBottomSheet.findViewById(R.id.current_wallpaper_image);
271 mCurrentWallpaperImage.getLayoutParams().width = getSingleWallpaperImageWidthPx();
272
273 mCurrentWallpaperPresentationMode =
274 (TextView) mBottomSheet.findViewById(R.id.current_wallpaper_presentation_mode);
275 mCurrentWallpaperTitle = (TextView) findViewById(R.id.current_wallpaper_title);
276 mCurrentWallpaperSubtitle = (TextView) findViewById(R.id.current_wallpaper_subtitle);
277 mCurrentWallpaperExploreButton = (Button) findViewById(
278 R.id.current_wallpaper_explore_button);
279 mCurrentWallpaperSkipWallpaperButton = (Button) findViewById(
280 R.id.current_wallpaper_skip_wallpaper_button);
281 mFragmentContainer = (FrameLayout) findViewById(R.id.fragment_container);
282 mLoadingIndicatorContainer = (FrameLayout) findViewById(R.id.loading_indicator_container);
283 mWallpaperPositionOptions = (LinearLayout) findViewById(
284 R.id.desktop_wallpaper_position_options);
285
286 final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
287 tabLayout.addOnTabSelectedListener(new OnTabSelectedListener() {
288 @Override
289 public void onTabSelected(Tab tab) {
290 Category category = (Category) tab.getTag();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800291 showCategoryDesktop(category.getCollectionId());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800292 mLastSelectedCategoryTabIndex = tabLayout.getSelectedTabPosition();
293 }
294
295 @Override
296 public void onTabUnselected(Tab tab) {
297 }
298
299 @Override
300 public void onTabReselected(Tab tab) {
301 Category category = (Category) tab.getTag();
302 // If offline, "My photos" may be the only visible category. In this case we want to allow
303 // re-selection so user can still select a photo as wallpaper while offline.
304 if (!category.isEnumerable()) {
305 onTabSelected(tab);
306 }
307 }
308 });
309
310 FragmentManager fm = getSupportFragmentManager();
311 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
312
313 if (fragment == null) {
314 // App launch specific logic: log the "app launched" event and set up daily logging.
315 mUserEventLogger.logAppLaunched();
316 DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());
317 }
318
319 mNetworkStatusListener = new NetworkStatusNotifier.Listener() {
320 @Override
321 public void onNetworkChanged(@NetworkStatus int networkStatus) {
322 initializeDesktopBasedOnNetwork(networkStatus, savedInstanceState);
323 }
324 };
325 // Upon registering a listener, the onNetworkChanged method is immediately called with the
326 // initial network status.
327 mNetworkStatusNotifier.registerListener(mNetworkStatusListener);
328 }
329
330 private void initializeDesktopBasedOnNetwork(@NetworkStatus int networkStatus,
331 Bundle savedInstanceState) {
332 if (networkStatus == NetworkStatusNotifier.NETWORK_CONNECTED) {
333 initializeDesktopOnline(savedInstanceState);
334 } else {
335 initializeDesktopOffline();
336 }
337 }
338
339 private void initializeDesktopOnline(Bundle savedInstanceState) {
340 FragmentManager fm = getSupportFragmentManager();
341 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
342
343 // Require a category refresh if this is the first load of the app or if the app is now
344 // returning online after having been offline.
345 boolean forceCategoryRefresh = fragment == null || fragment instanceof OfflineDesktopFragment;
346
347 if (fragment != null) {
348 fm.beginTransaction()
349 .remove(fragment)
350 .commit();
351 }
352
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800353 mLastSelectedCategoryTabIndex = savedInstanceState != null
Jon Miranda16ea1b12017-12-12 14:52:48 -0800354 ? savedInstanceState.getInt(KEY_SELECTED_CATEGORY_TAB) : -1;
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800355 mDelegate.populateCategories(forceCategoryRefresh);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800356
357 setDesktopLoading(true);
358 setUpBottomSheet();
359 refreshCurrentWallpapers(null /* refreshListener */);
360 }
361
362 private void initializeDesktopOffline() {
363 FragmentManager fm = getSupportFragmentManager();
364 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
365
366 if (fragment != null) {
367 fm.beginTransaction()
368 .remove(fragment)
369 .commit();
370 }
371 OfflineDesktopFragment newFragment = new OfflineDesktopFragment();
372 fm.beginTransaction()
373 .add(R.id.fragment_container, newFragment)
374 .commit();
375
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800376 // Reset the last selected category tab index to ensure the app doesn't try to reselect a
377 // tab for a category not yet repopulated.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800378 mLastSelectedCategoryTabIndex = -1;
379
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800380 mDelegate.populateCategories(true /* forceCategoryRefresh */);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800381
382 setDesktopLoading(false);
383 setCurrentWallpapersExpanded(false);
384 }
385
386 /**
387 * Sets the status of the loading indicator overlay in desktop mode.
388 *
389 * @param loading Whether an indeterminate loading indicator is displayed in place of the main
390 * fragment.
391 */
392 private void setDesktopLoading(boolean loading) {
393 if (loading) {
394 mLoadingIndicatorContainer.setVisibility(View.VISIBLE);
395 mFragmentContainer.setVisibility(View.GONE);
396 } else {
397 mLoadingIndicatorContainer.setVisibility(View.GONE);
398 mFragmentContainer.setVisibility(View.VISIBLE);
399 }
400 }
401
402 /**
403 * Returns the width (in physical px) to use for the "currently set wallpaper" thumbnail.
404 */
405 private int getSingleWallpaperImageWidthPx() {
406 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(
407 getWindowManager().getDefaultDisplay());
408
409 int height = getResources().getDimensionPixelSize(
410 R.dimen.current_wallpaper_bottom_sheet_thumb_height);
411 return height * screenSize.x / screenSize.y;
412 }
413
414 /**
415 * Enables and populates the "Currently set" wallpaper BottomSheet.
416 */
417 private void setUpBottomSheet() {
418 mBottomSheet.setVisibility(View.VISIBLE);
419
Jon Miranda16ea1b12017-12-12 14:52:48 -0800420 if (Flags.skipDailyWallpaperButtonEnabled) {
421 // Add "next" icon to the Next Wallpaper button
422 Drawable nextWallpaperButtonDrawable = getResources().getDrawable(
Santiago Etchebehered24506c2018-04-05 17:02:42 -0700423 R.drawable.ic_refresh_18px);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800424
425 // This Drawable's state is shared across the app, so make a copy of it before applying a
426 // color tint as not to affect other clients elsewhere in the app.
427 nextWallpaperButtonDrawable =
428 nextWallpaperButtonDrawable.getConstantState().newDrawable().mutate();
429 // Color the "compass" icon with the accent color.
430 nextWallpaperButtonDrawable.setColorFilter(
431 getResources().getColor(R.color.accent_color), Mode.SRC_IN);
432 ButtonDrawableSetterCompat.setDrawableToButtonStart(
433 mCurrentWallpaperSkipWallpaperButton, nextWallpaperButtonDrawable);
434 }
435
436 final BottomSheetBehavior<LinearLayout> bottomSheetBehavior =
437 BottomSheetBehavior.from(mBottomSheet);
438 bottomSheetBehavior.setBottomSheetCallback(new BottomSheetCallback() {
439 @Override
440 public void onStateChanged(@NonNull View view, int i) {
441 }
442
443 @Override
444 public void onSlide(@NonNull View view, float slideOffset) {
445 float alpha;
446 if (slideOffset >= 0) {
447 alpha = slideOffset;
448 } else {
449 alpha = 1f - slideOffset;
450 }
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800451 LinearLayout bottomSheetContents = findViewById(R.id.bottom_sheet_contents);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800452 bottomSheetContents.setAlpha(alpha);
453 }
454 });
455 }
456
457 /**
458 * Enables a test mode of operation -- in which certain UI features are disabled to allow for
459 * UI tests to run correctly. Works around issue in ProgressDialog currently where the dialog
460 * constantly keeps the UI thread alive and blocks a test forever.
461 */
462 void setTestingMode(boolean testingMode) {
463 mTestingMode = testingMode;
464 }
465
466 /**
467 * Obtains the {@link WallpaperInfo} object(s) representing the wallpaper(s) currently set to the
468 * device from the {@link CurrentWallpaperInfoFactory} and displays them in the BottomSheet.
469 */
470 @Override
471 public void refreshCurrentWallpapers(@Nullable RefreshListener refreshListener) {
472 final Injector injector = InjectorProvider.getInjector();
473 final Context appContext = getApplicationContext();
474
475 CurrentWallpaperInfoFactory factory = injector.getCurrentWallpaperFactory(this);
476 factory.createCurrentWallpaperInfos(new WallpaperInfoCallback() {
477 @Override
478 public void onWallpaperInfoCreated(
479 final WallpaperInfo homeWallpaper,
480 @Nullable final WallpaperInfo lockWallpaper,
481 @PresentationMode final int presentationMode) {
482
483 if (isDestroyed()) {
484 return;
485 }
486
487 // Fetch the home wallpaper's thumbnail asset asynchronously to work around expensive
488 // method call to WallpaperManager#getWallpaperFile made from the CurrentWallpaperInfoVN
489 // getAsset() method.
490 AssetReceiver assetReceiver = (Asset thumbAsset) -> {
491 if (isDestroyed()) {
492 return;
493 }
494
495 homeWallpaper.getThumbAsset(appContext).loadDrawableWithTransition(
496 TopLevelPickerActivity.this,
497 mCurrentWallpaperImage,
498 200 /* transitionDurationMillis */,
499 () -> {
500 if (refreshListener != null) {
501 refreshListener.onCurrentWallpaperRefreshed();
502 }
503 },
504 Color.TRANSPARENT);
505 };
506 new FetchThumbAssetTask(appContext, homeWallpaper, assetReceiver).executeOnExecutor(
507 AsyncTask.THREAD_POOL_EXECUTOR);
508
509 mCurrentWallpaperPresentationMode.setText(
510 AttributionFormatter.getHumanReadableWallpaperPresentationMode(
511 TopLevelPickerActivity.this, presentationMode));
512
513 List<String> attributions = homeWallpaper.getAttributions(appContext);
514 if (attributions.size() > 0 && attributions.get(0) != null) {
515 mCurrentWallpaperTitle.setText(attributions.get(0));
516 }
517
518 mCurrentWallpaperSubtitle.setText(
519 AttributionFormatter.formatWallpaperSubtitle(appContext, homeWallpaper));
520
521 final String actionUrl = homeWallpaper.getActionUrl(appContext);
522 if (actionUrl != null && !actionUrl.isEmpty()) {
523 Uri exploreUri = Uri.parse(actionUrl);
524
525 ExploreIntentChecker intentChecker = injector.getExploreIntentChecker(appContext);
526 intentChecker.fetchValidActionViewIntent(exploreUri, (@Nullable Intent exploreIntent) -> {
527 if (exploreIntent != null && !isDestroyed()) {
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700528 // Set the icon for the button
529 Drawable exploreButtonDrawable = getResources().getDrawable(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700530 homeWallpaper.getActionIconRes(appContext));
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700531
532 // This Drawable's state is shared across the app, so make a copy of it
533 // before applying a color tint as not to affect other clients elsewhere
534 // in the app.
535 exploreButtonDrawable = exploreButtonDrawable.getConstantState()
536 .newDrawable().mutate();
537 // Color the "compass" icon with the accent color.
538 exploreButtonDrawable.setColorFilter(
539 getResources().getColor(R.color.accent_color), Mode.SRC_IN);
540
541 ButtonDrawableSetterCompat.setDrawableToButtonStart(
542 mCurrentWallpaperExploreButton, exploreButtonDrawable);
543 mCurrentWallpaperExploreButton.setText(getString(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700544 homeWallpaper.getActionLabelRes(appContext)));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800545 mCurrentWallpaperExploreButton.setVisibility(View.VISIBLE);
546 mCurrentWallpaperExploreButton.setOnClickListener(new OnClickListener() {
547 @Override
548 public void onClick(View v) {
Santiago Etchebeherece5613f2018-06-01 13:22:47 -0700549 mUserEventLogger.logActionClicked(
550 homeWallpaper.getCollectionId(appContext),
551 homeWallpaper.getActionLabelRes(appContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800552 startActivity(exploreIntent);
553 }
554 });
555 }
556 });
557 } else {
558 mCurrentWallpaperExploreButton.setVisibility(View.GONE);
559 }
560
561 // Hide the wallpaper position options UI if the current home wallpaper is not from
562 // "my photos".
563 String homeCollectionId = homeWallpaper.getCollectionId(TopLevelPickerActivity.this);
564 if (mWallpaperPositionOptions != null
565 && homeCollectionId != null // May be null if app is being used for the first time.
566 && !homeCollectionId.equals(getString(R.string.image_wallpaper_collection_id))) {
567 mWallpaperPositionOptions.setVisibility(View.GONE);
568 }
569
570 boolean showSkipWallpaperButton = Flags.skipDailyWallpaperButtonEnabled
571 && presentationMode == WallpaperPreferences.PRESENTATION_MODE_ROTATING;
572 if (showSkipWallpaperButton) {
573 mCurrentWallpaperSkipWallpaperButton.setVisibility(View.VISIBLE);
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800574 mCurrentWallpaperSkipWallpaperButton.setOnClickListener(
575 v -> refreshDailyWallpaper());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800576 } else {
577 mCurrentWallpaperSkipWallpaperButton.setVisibility(View.GONE);
578 }
579
580 if (refreshListener != null) {
581 refreshListener.onCurrentWallpaperRefreshed();
582 }
583 }
584 }, true /* forceRefresh */);
585 }
586
587 @Override
588 public void onSaveInstanceState(Bundle savedInstanceState) {
589 FormFactorChecker formFactorChecker = InjectorProvider.getInjector().getFormFactorChecker(this);
590 if (formFactorChecker.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP) {
591 TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
592
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800593 // tabLayout is only present when the main IndividualPickerFragment is present (as
594 // opposed to
Jon Miranda16ea1b12017-12-12 14:52:48 -0800595 // the WallpaperDisabledFragment), so need this null check.
596 if (tabLayout != null) {
597 savedInstanceState.putInt(KEY_SELECTED_CATEGORY_TAB, tabLayout.getSelectedTabPosition());
598 }
599 }
600
601 super.onSaveInstanceState(savedInstanceState);
602 }
603
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800604 @Override
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700605 @Nullable
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800606 public CategoryFragment getCategoryFragment() {
607 if (mDelegate.getFormFactor() != FormFactorChecker.FORM_FACTOR_MOBILE) {
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700608 return null;
609 }
610 FragmentManager fm = getSupportFragmentManager();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800611 return (CategoryFragment) fm.findFragmentById(R.id.fragment_container);
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700612 }
613
Jon Miranda16ea1b12017-12-12 14:52:48 -0800614 /**
615 * Populates the category tabs on DESKTOP form factor.
616 *
617 * @param selectedTabPosition The position of the tab to show as selected, or -1 if no particular
618 * tab should be selected (in which case: the tab of the category for the currently set
619 * wallpaper will be selected if enumerable; if not, the first enumerable category's tab will
620 * be selected).
621 */
622 private void populateCategoryTabs(int selectedTabPosition) {
623 final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
624 tabLayout.removeAllTabs();
625
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800626 String currentlySetCollectionId = mDelegate.getPreferences().getHomeWallpaperCollectionId();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800627
628 Tab tabToSelect = null;
629 Tab firstEnumerableCategoryTab = null;
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800630 for (int i = 0; i < mDelegate.getCategoryProvider().getSize(); i++) {
631 Category category = mDelegate.getCategoryProvider().getCategory(i);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800632
633 Tab tab = tabLayout.newTab();
634 tab.setText(category.getTitle());
635 tab.setTag(category);
636 tabLayout.addTab(tab, false /* setSelected */);
637
638 if (firstEnumerableCategoryTab == null && category.isEnumerable()) {
639 firstEnumerableCategoryTab = tab;
640 }
641
642 boolean shouldSelectTab = (i == selectedTabPosition)
643 || (selectedTabPosition == -1
644 && tabToSelect == null
645 && category.isEnumerable()
646 && currentlySetCollectionId != null
647 && currentlySetCollectionId.equals(category.getCollectionId()));
648
649 if (shouldSelectTab) {
650 tabToSelect = tab;
651 }
652 }
653
654 // If the above loop did not identify a specific tab to select, then just select the tab for
655 // the first enumerable category.
656 if (tabToSelect == null) {
657 tabToSelect = firstEnumerableCategoryTab;
658 }
659
660 // There may be no enumerable tabs (e.g., offline case), so we need to null-check again.
661 if (tabToSelect != null) {
662 tabToSelect.select();
663 }
664 }
665
666 /**
667 * Refreshes the current wallpaper in a daily wallpaper rotation.
668 */
669 private void refreshDailyWallpaper() {
670 // ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore
671 // causes Espresso to hang once the dialog is shown.
672 if (!mTestingMode) {
673 int themeResId;
674 if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
675 themeResId = R.style.ProgressDialogThemePreL;
676 } else {
677 themeResId = R.style.LightDialogTheme;
678 }
679 mRefreshWallpaperProgressDialog = new ProgressDialog(this, themeResId);
680 mRefreshWallpaperProgressDialog.setTitle(null);
681 mRefreshWallpaperProgressDialog.setMessage(
682 getResources().getString(R.string.refreshing_daily_wallpaper_dialog_message));
683 mRefreshWallpaperProgressDialog.setIndeterminate(true);
684 mRefreshWallpaperProgressDialog.show();
685 }
686
687 WallpaperRotationRefresher wallpaperRotationRefresher =
688 InjectorProvider.getInjector().getWallpaperRotationRefresher();
689 wallpaperRotationRefresher.refreshWallpaper(this, new Listener() {
690 @Override
691 public void onRefreshed() {
692 if (isDestroyed()) {
693 return;
694 }
695
696 if (mRefreshWallpaperProgressDialog != null) {
697 mRefreshWallpaperProgressDialog.dismiss();
698 }
699
700 refreshCurrentWallpapers(null /* refreshListener */);
701 }
702
703 @Override
704 public void onError() {
705 if (mRefreshWallpaperProgressDialog != null) {
706 mRefreshWallpaperProgressDialog.dismiss();
707 }
708
709 AlertDialog errorDialog = new AlertDialog.Builder(
710 TopLevelPickerActivity.this, R.style.LightDialogTheme)
711 .setMessage(R.string.refresh_daily_wallpaper_failed_message)
712 .setPositiveButton(android.R.string.ok, null /* onClickListener */)
713 .create();
714 errorDialog.show();
715 }
716 });
717 }
718
719 @Override
720 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
721 super.onActivityResult(requestCode, resultCode, data);
722
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800723 if (requestCode == WallpaperPickerDelegate.SHOW_CATEGORY_REQUEST_CODE
724 && resultCode == Activity.RESULT_OK) {
Santiago Etchebeheree5e05842019-02-13 16:58:07 -0800725 if (mDelegate.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP) {
726 Uri imageUri = (data == null) ? null : data.getData();
727 if (imageUri != null) {
728 // User selected an image from the system picker, so launch the preview for that
729 // image.
730 ImageWallpaperInfo imageWallpaper = new ImageWallpaperInfo(imageUri);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800731 setCustomPhotoWallpaper(imageWallpaper);
732 return;
733 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800734 }
Santiago Etchebeheree5e05842019-02-13 16:58:07 -0800735 }
736 if (mDelegate.handleActivityResult(requestCode, resultCode, data)) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800737 finishActivityWithResultOk();
738 }
739 }
740
741 /**
742 * Shows the view-only preview activity for the given wallpaper.
743 */
744 public void showViewOnlyPreview(WallpaperInfo wallpaperInfo) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800745 mDelegate.showViewOnlyPreview(wallpaperInfo);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800746 }
747
748 @Override
749 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
750 @NonNull int[] grantResults) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800751 mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800752 }
753
754 /**
755 * Shows the picker activity for the given category.
756 */
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800757 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800758 public void show(String collectionId) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800759 mDelegate.show(collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800760 }
761
762 private void reselectLastTab() {
763 TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
764
765 // In the offline case, "My photos" could be the only category. Thus we need this check --
766 // to ensure that we don't try to select the "previously selected" category which was -1.
767 if (mLastSelectedCategoryTabIndex > -1) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800768 Tab tabToSelect = tabLayout.getTabAt(
769 mLastSelectedCategoryTabIndex);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800770 if (((Category) tabToSelect.getTag()).isEnumerable()) {
771 tabToSelect.select();
772 }
773 }
774 }
775
Jon Miranda16ea1b12017-12-12 14:52:48 -0800776 private void showCategoryDesktop(String collectionId) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800777 Category category = mDelegate.findCategoryForCollectionId(collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800778 if (category == null) {
779 return;
780 }
781
782 if (category.isEnumerable()) {
783 // Replace contained IndividualPickerFragment with a new instance for the given category.
784 final FragmentManager fm = getSupportFragmentManager();
785 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
786 if (fragment != null) {
787 fm.beginTransaction()
788 .remove(fragment)
789 .commit();
790 }
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800791 Injector injector = InjectorProvider.getInjector();
792 IndividualPickerFragment newFragment = injector.getIndividualPickerFragment(
793 collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800794 fm.beginTransaction()
795 .add(R.id.fragment_container, newFragment)
796 .commit();
797 newFragment.setCurrentWallpaperBottomSheetPresenter(this);
798 newFragment.setWallpapersUiContainer(this);
799 } else {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800800 category.show(this, mDelegate.getPickerIntentFactory(),
801 WallpaperPickerDelegate.SHOW_CATEGORY_REQUEST_CODE);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800802
803 // Need to select the tab here in case we are coming back from a "My photos" in which case
804 // the tab would have been set to "My photos" while viewing a regular image category.
805 reselectLastTab();
806 }
807 }
808
809 private void finishActivityWithResultOk() {
810 overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
811 setResult(Activity.RESULT_OK);
812 finish();
813 }
814
Jon Miranda16ea1b12017-12-12 14:52:48 -0800815 @Override
816 public void setCurrentWallpapersExpanded(boolean expanded) {
817 final BottomSheetBehavior<LinearLayout> bottomSheetBehavior =
818 BottomSheetBehavior.from(mBottomSheet);
819 bottomSheetBehavior.setState(
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800820 expanded ? BottomSheetBehavior.STATE_EXPANDED
821 : BottomSheetBehavior.STATE_COLLAPSED);
822 }
823
824 @Override
825 public void doneFetchingCategories() {
826 populateCategoryTabs(mLastSelectedCategoryTabIndex);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800827 }
828
829 @Override
830 public void onWallpapersReady() {
831 setDesktopLoading(false);
832 setCurrentWallpapersExpanded(true);
833 }
834
835 @Override
Santiago Etchebeherefab49612019-01-15 12:22:42 -0800836 public MyPhotosStarter getMyPhotosStarter() {
837 return this;
838 }
839
840 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800841 public void onClickTryAgain(@Destination int unused) {
842 // Retry the set wallpaper operation with the default center-crop setting.
843 if (mPendingSetWallpaperInfo != null) {
844 setCustomPhotoWallpaper(mPendingSetWallpaperInfo);
845 }
846 }
847
848 /**
849 * Sets the provides wallpaper to the device with center-cropped and scaled to fit the device's
850 * default display.
851 */
852 private void setCustomPhotoWallpaper(final WallpaperInfo wallpaper) {
853 // Save this WallpaperInfo so we can retry this operation later if it fails.
854 mPendingSetWallpaperInfo = wallpaper;
855
856 showSettingWallpaperProgressDialog();
857
858 mWallpaperPersister.setIndividualWallpaperWithPosition(this, wallpaper,
859 WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP, new SetWallpaperCallback() {
860 @Override
861 public void onSuccess() {
862 dismissSettingWallpaperProgressDialog();
863 refreshCurrentWallpapers(null /* refreshListener */);
864
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800865 mDelegate.getPreferences().setPendingWallpaperSetStatus(
Jon Miranda16ea1b12017-12-12 14:52:48 -0800866 WallpaperPreferences.WALLPAPER_SET_NOT_PENDING);
867 mUserEventLogger.logWallpaperSet(
868 wallpaper.getCollectionId(getApplicationContext()),
869 wallpaper.getWallpaperId());
870 mUserEventLogger.logWallpaperSetResult(UserEventLogger.WALLPAPER_SET_RESULT_SUCCESS);
871
872 // The user may have closed the activity before the set wallpaper operation completed.
873 if (isDestroyed()) {
874 return;
875 }
876
877 // Show the wallpaper crop option selector and bind click event handlers.
878 mWallpaperPositionOptions.setVisibility(View.VISIBLE);
879
880 mWasCustomPhotoWallpaperSet = true;
881 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP;
882
883 initializeWallpaperPositionOptionClickHandlers(wallpaper);
884 }
885
886 @Override
887 public void onError(Throwable throwable) {
888 dismissSettingWallpaperProgressDialog();
889 showSetWallpaperErrorDialog();
890
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800891 mDelegate.getPreferences().setPendingWallpaperSetStatus(
Jon Miranda16ea1b12017-12-12 14:52:48 -0800892 WallpaperPreferences.WALLPAPER_SET_NOT_PENDING);
893 mUserEventLogger.logWallpaperSetResult(
894 UserEventLogger.WALLPAPER_SET_RESULT_FAILURE);
895 @WallpaperSetFailureReason int failureReason = ThrowableAnalyzer.isOOM(throwable)
896 ? UserEventLogger.WALLPAPER_SET_FAILURE_REASON_OOM
897 : UserEventLogger.WALLPAPER_SET_FAILURE_REASON_OTHER;
898 mUserEventLogger.logWallpaperSetFailureReason(failureReason);
899 Log.e(TAG, "Unable to set wallpaper from 'my photos'.");
900 }
901 });
902 }
903
904 /**
905 * Initializes the wallpaper position button click handlers to change the way the provided
906 * wallpaper is set to the device.
907 */
908 private void initializeWallpaperPositionOptionClickHandlers(final WallpaperInfo wallpaperInfo) {
909 Button centerCropOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_center_crop);
910 Button stretchOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_stretched);
911 Button centerOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_center);
912
913 // The "center crop" wallpaper position button is selected by default.
914 setCenterCropWallpaperPositionButtonSelected(centerCropOptionBtn, true /* isSelected */);
915 centerCropOptionBtn.setOnClickListener(new OnClickListener() {
916 @Override
917 public void onClick(View view) {
918 mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
919 wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP,
920 new SetWallpaperCallback() {
921 @Override
922 public void onSuccess() {
923 // The user may have closed the activity before the set wallpaper operation
924 // completed.
925 if (isDestroyed()) {
926 return;
927 }
928
929 refreshCurrentWallpapers(null /* refreshListener */);
930
931 setCenterCropWallpaperPositionButtonSelected(
932 centerCropOptionBtn, true /* isSelected */);
933 setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
934 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
935
936 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP;
937 }
938
939 @Override
940 public void onError(@Nullable Throwable throwable) {
941 // no-op
942 }
943 });
944 }
945 });
946
947 // "Stretch" is not selected by default.
948 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
949 stretchOptionBtn.setOnClickListener(new OnClickListener() {
950 @Override
951 public void onClick(View view) {
952 mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
953 wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_STRETCH,
954 new SetWallpaperCallback() {
955 @Override
956 public void onSuccess() {
957 // The user may have closed the activity before the set wallpaper operation
958 // completed.
959 if (isDestroyed()) {
960 return;
961 }
962
963 refreshCurrentWallpapers(null /* refreshListener */);
964
965 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, true /* isSelected */);
966 setCenterCropWallpaperPositionButtonSelected(
967 centerCropOptionBtn, false /* isSelected */);
968 setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
969
970 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_STRETCH;
971 }
972
973 @Override
974 public void onError(@Nullable Throwable throwable) {
975 // no-op
976 }
977 });
978 }
979 });
980
981 // "Center" is not selected by default.
982 setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
983 centerOptionBtn.setOnClickListener(new OnClickListener() {
984 @Override
985 public void onClick(View view) {
986 mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
987 wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_CENTER,
988 new SetWallpaperCallback() {
989 @Override
990 public void onSuccess() {
991 // The user may have closed the activity before the set wallpaper operation
992 // completed.
993 if (isDestroyed()) {
994 return;
995 }
996
997 refreshCurrentWallpapers(null /* refreshListener */);
998
999 setCenterWallpaperPositionButtonSelected(centerOptionBtn, true /* isSelected */);
1000 setCenterCropWallpaperPositionButtonSelected(
1001 centerCropOptionBtn, false /* isSelected */);
1002 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
1003
1004 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER;
1005 }
1006
1007 @Override
1008 public void onError(@Nullable Throwable throwable) {
1009 // no-op
1010 }
1011 });
1012 }
1013 });
1014 }
1015
1016 private void setCenterWallpaperPositionButtonSelected(Button button, boolean isSelected) {
1017 int drawableId = isSelected ? R.drawable.center_blue : R.drawable.center_grey;
1018 ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
1019 button.setTextColor(getColor(getTextColorIdForWallpaperPositionButton(isSelected)));
1020 }
1021
1022 private void setCenterCropWallpaperPositionButtonSelected(Button button, boolean isSelected) {
1023 int drawableId = isSelected ? R.drawable.center_crop_blue : R.drawable.center_crop_grey;
1024 ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
1025 button.setTextColor(getColor(getTextColorIdForWallpaperPositionButton(isSelected)));
1026 }
1027
1028 private void setStretchWallpaperPositionButtonSelected(Button button, boolean isSelected) {
1029 int drawableId = isSelected ? R.drawable.stretch_blue : R.drawable.stretch_grey;
1030 ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
1031 button.setTextColor(getColor(getTextColorIdForWallpaperPositionButton(isSelected)));
1032 }
1033
1034 private void showSettingWallpaperProgressDialog() {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -08001035 // ProgressDialog endlessly updates the UI thread, keeping it from going idle which
1036 // therefore causes Espresso to hang once the dialog is shown.
Jon Miranda16ea1b12017-12-12 14:52:48 -08001037 if (!mTestingMode) {
1038 int themeResId;
1039 if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
1040 themeResId = R.style.ProgressDialogThemePreL;
1041 } else {
1042 themeResId = R.style.LightDialogTheme;
1043 }
1044 mSetWallpaperProgressDialog = new ProgressDialog(this, themeResId);
1045 mSetWallpaperProgressDialog.setTitle(null);
1046 mSetWallpaperProgressDialog.setMessage(
1047 getResources().getString(R.string.set_wallpaper_progress_message));
1048 mSetWallpaperProgressDialog.setIndeterminate(true);
1049 mSetWallpaperProgressDialog.show();
1050 }
1051 }
1052
1053 private void dismissSettingWallpaperProgressDialog() {
1054 if (mSetWallpaperProgressDialog != null) {
1055 mSetWallpaperProgressDialog.dismiss();
1056 }
1057 }
1058
1059 private void showSetWallpaperErrorDialog() {
1060 SetWallpaperErrorDialogFragment dialogFragment = SetWallpaperErrorDialogFragment.newInstance(
1061 R.string.set_wallpaper_error_message, WallpaperPersister.DEST_BOTH);
1062
1063 if (isSafeToCommitFragmentTransaction()) {
1064 dialogFragment.show(getSupportFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
1065 } else {
1066 mStagedSetWallpaperErrorDialogFragment = dialogFragment;
1067 }
1068 }
1069
1070 private interface AssetReceiver {
1071 void onAssetReceived(Asset asset);
1072 }
1073
1074 /**
1075 * An AsyncTask for asynchronously fetching the thumbnail asset for a given WallpaperInfo.
1076 * Used to work around expensive method call to WallpaperManager#getWallpaperFile made from the
1077 * CurrentWallpaperInfoVN getAsset() method.
1078 */
1079 private static class FetchThumbAssetTask extends AsyncTask<Void, Void, Asset> {
1080 private Context mAppContext;
1081 private WallpaperInfo mWallpaperInfo;
1082 private AssetReceiver mReceiver;
1083
1084 public FetchThumbAssetTask(Context appContext, WallpaperInfo wallpaperInfo,
1085 AssetReceiver receiver) {
1086 mAppContext = appContext;
1087 mWallpaperInfo = wallpaperInfo;
1088 mReceiver = receiver;
1089 }
1090
1091 @Override
1092 protected Asset doInBackground(Void... params) {
1093 return mWallpaperInfo.getThumbAsset(mAppContext);
1094 }
1095
1096 @Override
1097 protected void onPostExecute(Asset thumbAsset) {
1098 mReceiver.onAssetReceived(thumbAsset);
1099 }
1100 }
1101}