blob: 25540f1e34828fd6e2eb1da41dd80d37b613598b [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();
188
189 // 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
200 protected void onDestroy() {
201 super.onDestroy();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800202 mDelegate.cleanUp();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800203 if (mNetworkStatusListener != null) {
204 mNetworkStatusNotifier.unregisterListener(mNetworkStatusListener);
205 }
206
207 if (mRefreshWallpaperProgressDialog != null) {
208 mRefreshWallpaperProgressDialog.dismiss();
209 }
210 if (mSetWallpaperProgressDialog != null) {
211 mSetWallpaperProgressDialog.dismiss();
212 }
213
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800214 if (mDelegate.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP
215 && mWasCustomPhotoWallpaperSet) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800216 mUserEventLogger.logWallpaperPosition(mCustomPhotoWallpaperPosition);
217 }
218 }
219
220 @Override
221 public void requestCustomPhotoPicker(PermissionChangedListener listener) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800222 mDelegate.requestCustomPhotoPicker(listener);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800223 }
224
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800225 @Override
226 public void requestExternalStoragePermission(PermissionChangedListener listener) {
227 mDelegate.requestExternalStoragePermission(listener);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800228 }
229
230 /**
231 * Returns whether READ_EXTERNAL_STORAGE has been granted for the application.
232 */
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800233 public boolean isReadExternalStoragePermissionGranted() {
234 return mDelegate.isReadExternalStoragePermissionGranted();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800235 }
236
237 private void initializeMobile() {
Santiago Etchebehere008368d2018-12-13 15:23:17 -0800238 setContentView(R.layout.activity_single_fragment);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800239
240 // Set toolbar as the action bar.
241 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
242 setSupportActionBar(toolbar);
243
244 FragmentManager fm = getSupportFragmentManager();
245 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
246
247 boolean forceCategoryRefresh = false;
248 if (fragment == null) {
249 // App launch specific logic: log the "app launched" event and set up daily logging.
250 mUserEventLogger.logAppLaunched();
251 DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());
252
Santiago Etchebehereaa35e6e2019-01-25 10:30:11 -0800253 CategoryFragment newFragment = CategoryFragment.newInstance(
254 getString(R.string.wallpaper_app_name));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800255 fm.beginTransaction()
256 .add(R.id.fragment_container, newFragment)
257 .commit();
258
259 forceCategoryRefresh = true;
260 }
261
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800262 mDelegate.initialize(forceCategoryRefresh);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800263 }
264
265 private void initializeDesktop(Bundle savedInstanceState) {
266 setContentView(R.layout.activity_top_level_desktop);
267
268 mBottomSheet = (LinearLayout) findViewById(R.id.bottom_sheet);
269 mCurrentWallpaperImage = (ImageView) mBottomSheet.findViewById(R.id.current_wallpaper_image);
270 mCurrentWallpaperImage.getLayoutParams().width = getSingleWallpaperImageWidthPx();
271
272 mCurrentWallpaperPresentationMode =
273 (TextView) mBottomSheet.findViewById(R.id.current_wallpaper_presentation_mode);
274 mCurrentWallpaperTitle = (TextView) findViewById(R.id.current_wallpaper_title);
275 mCurrentWallpaperSubtitle = (TextView) findViewById(R.id.current_wallpaper_subtitle);
276 mCurrentWallpaperExploreButton = (Button) findViewById(
277 R.id.current_wallpaper_explore_button);
278 mCurrentWallpaperSkipWallpaperButton = (Button) findViewById(
279 R.id.current_wallpaper_skip_wallpaper_button);
280 mFragmentContainer = (FrameLayout) findViewById(R.id.fragment_container);
281 mLoadingIndicatorContainer = (FrameLayout) findViewById(R.id.loading_indicator_container);
282 mWallpaperPositionOptions = (LinearLayout) findViewById(
283 R.id.desktop_wallpaper_position_options);
284
285 final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
286 tabLayout.addOnTabSelectedListener(new OnTabSelectedListener() {
287 @Override
288 public void onTabSelected(Tab tab) {
289 Category category = (Category) tab.getTag();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800290 showCategoryDesktop(category.getCollectionId());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800291 mLastSelectedCategoryTabIndex = tabLayout.getSelectedTabPosition();
292 }
293
294 @Override
295 public void onTabUnselected(Tab tab) {
296 }
297
298 @Override
299 public void onTabReselected(Tab tab) {
300 Category category = (Category) tab.getTag();
301 // If offline, "My photos" may be the only visible category. In this case we want to allow
302 // re-selection so user can still select a photo as wallpaper while offline.
303 if (!category.isEnumerable()) {
304 onTabSelected(tab);
305 }
306 }
307 });
308
309 FragmentManager fm = getSupportFragmentManager();
310 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
311
312 if (fragment == null) {
313 // App launch specific logic: log the "app launched" event and set up daily logging.
314 mUserEventLogger.logAppLaunched();
315 DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());
316 }
317
318 mNetworkStatusListener = new NetworkStatusNotifier.Listener() {
319 @Override
320 public void onNetworkChanged(@NetworkStatus int networkStatus) {
321 initializeDesktopBasedOnNetwork(networkStatus, savedInstanceState);
322 }
323 };
324 // Upon registering a listener, the onNetworkChanged method is immediately called with the
325 // initial network status.
326 mNetworkStatusNotifier.registerListener(mNetworkStatusListener);
327 }
328
329 private void initializeDesktopBasedOnNetwork(@NetworkStatus int networkStatus,
330 Bundle savedInstanceState) {
331 if (networkStatus == NetworkStatusNotifier.NETWORK_CONNECTED) {
332 initializeDesktopOnline(savedInstanceState);
333 } else {
334 initializeDesktopOffline();
335 }
336 }
337
338 private void initializeDesktopOnline(Bundle savedInstanceState) {
339 FragmentManager fm = getSupportFragmentManager();
340 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
341
342 // Require a category refresh if this is the first load of the app or if the app is now
343 // returning online after having been offline.
344 boolean forceCategoryRefresh = fragment == null || fragment instanceof OfflineDesktopFragment;
345
346 if (fragment != null) {
347 fm.beginTransaction()
348 .remove(fragment)
349 .commit();
350 }
351
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800352 mLastSelectedCategoryTabIndex = savedInstanceState != null
Jon Miranda16ea1b12017-12-12 14:52:48 -0800353 ? savedInstanceState.getInt(KEY_SELECTED_CATEGORY_TAB) : -1;
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800354 mDelegate.populateCategories(forceCategoryRefresh);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800355
356 setDesktopLoading(true);
357 setUpBottomSheet();
358 refreshCurrentWallpapers(null /* refreshListener */);
359 }
360
361 private void initializeDesktopOffline() {
362 FragmentManager fm = getSupportFragmentManager();
363 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
364
365 if (fragment != null) {
366 fm.beginTransaction()
367 .remove(fragment)
368 .commit();
369 }
370 OfflineDesktopFragment newFragment = new OfflineDesktopFragment();
371 fm.beginTransaction()
372 .add(R.id.fragment_container, newFragment)
373 .commit();
374
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800375 // Reset the last selected category tab index to ensure the app doesn't try to reselect a
376 // tab for a category not yet repopulated.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800377 mLastSelectedCategoryTabIndex = -1;
378
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800379 mDelegate.populateCategories(true /* forceCategoryRefresh */);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800380
381 setDesktopLoading(false);
382 setCurrentWallpapersExpanded(false);
383 }
384
385 /**
386 * Sets the status of the loading indicator overlay in desktop mode.
387 *
388 * @param loading Whether an indeterminate loading indicator is displayed in place of the main
389 * fragment.
390 */
391 private void setDesktopLoading(boolean loading) {
392 if (loading) {
393 mLoadingIndicatorContainer.setVisibility(View.VISIBLE);
394 mFragmentContainer.setVisibility(View.GONE);
395 } else {
396 mLoadingIndicatorContainer.setVisibility(View.GONE);
397 mFragmentContainer.setVisibility(View.VISIBLE);
398 }
399 }
400
401 /**
402 * Returns the width (in physical px) to use for the "currently set wallpaper" thumbnail.
403 */
404 private int getSingleWallpaperImageWidthPx() {
405 Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(
406 getWindowManager().getDefaultDisplay());
407
408 int height = getResources().getDimensionPixelSize(
409 R.dimen.current_wallpaper_bottom_sheet_thumb_height);
410 return height * screenSize.x / screenSize.y;
411 }
412
413 /**
414 * Enables and populates the "Currently set" wallpaper BottomSheet.
415 */
416 private void setUpBottomSheet() {
417 mBottomSheet.setVisibility(View.VISIBLE);
418
Jon Miranda16ea1b12017-12-12 14:52:48 -0800419 if (Flags.skipDailyWallpaperButtonEnabled) {
420 // Add "next" icon to the Next Wallpaper button
421 Drawable nextWallpaperButtonDrawable = getResources().getDrawable(
Santiago Etchebehered24506c2018-04-05 17:02:42 -0700422 R.drawable.ic_refresh_18px);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800423
424 // This Drawable's state is shared across the app, so make a copy of it before applying a
425 // color tint as not to affect other clients elsewhere in the app.
426 nextWallpaperButtonDrawable =
427 nextWallpaperButtonDrawable.getConstantState().newDrawable().mutate();
428 // Color the "compass" icon with the accent color.
429 nextWallpaperButtonDrawable.setColorFilter(
430 getResources().getColor(R.color.accent_color), Mode.SRC_IN);
431 ButtonDrawableSetterCompat.setDrawableToButtonStart(
432 mCurrentWallpaperSkipWallpaperButton, nextWallpaperButtonDrawable);
433 }
434
435 final BottomSheetBehavior<LinearLayout> bottomSheetBehavior =
436 BottomSheetBehavior.from(mBottomSheet);
437 bottomSheetBehavior.setBottomSheetCallback(new BottomSheetCallback() {
438 @Override
439 public void onStateChanged(@NonNull View view, int i) {
440 }
441
442 @Override
443 public void onSlide(@NonNull View view, float slideOffset) {
444 float alpha;
445 if (slideOffset >= 0) {
446 alpha = slideOffset;
447 } else {
448 alpha = 1f - slideOffset;
449 }
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800450 LinearLayout bottomSheetContents = findViewById(R.id.bottom_sheet_contents);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800451 bottomSheetContents.setAlpha(alpha);
452 }
453 });
454 }
455
456 /**
457 * Enables a test mode of operation -- in which certain UI features are disabled to allow for
458 * UI tests to run correctly. Works around issue in ProgressDialog currently where the dialog
459 * constantly keeps the UI thread alive and blocks a test forever.
460 */
461 void setTestingMode(boolean testingMode) {
462 mTestingMode = testingMode;
463 }
464
465 /**
466 * Obtains the {@link WallpaperInfo} object(s) representing the wallpaper(s) currently set to the
467 * device from the {@link CurrentWallpaperInfoFactory} and displays them in the BottomSheet.
468 */
469 @Override
470 public void refreshCurrentWallpapers(@Nullable RefreshListener refreshListener) {
471 final Injector injector = InjectorProvider.getInjector();
472 final Context appContext = getApplicationContext();
473
474 CurrentWallpaperInfoFactory factory = injector.getCurrentWallpaperFactory(this);
475 factory.createCurrentWallpaperInfos(new WallpaperInfoCallback() {
476 @Override
477 public void onWallpaperInfoCreated(
478 final WallpaperInfo homeWallpaper,
479 @Nullable final WallpaperInfo lockWallpaper,
480 @PresentationMode final int presentationMode) {
481
482 if (isDestroyed()) {
483 return;
484 }
485
486 // Fetch the home wallpaper's thumbnail asset asynchronously to work around expensive
487 // method call to WallpaperManager#getWallpaperFile made from the CurrentWallpaperInfoVN
488 // getAsset() method.
489 AssetReceiver assetReceiver = (Asset thumbAsset) -> {
490 if (isDestroyed()) {
491 return;
492 }
493
494 homeWallpaper.getThumbAsset(appContext).loadDrawableWithTransition(
495 TopLevelPickerActivity.this,
496 mCurrentWallpaperImage,
497 200 /* transitionDurationMillis */,
498 () -> {
499 if (refreshListener != null) {
500 refreshListener.onCurrentWallpaperRefreshed();
501 }
502 },
503 Color.TRANSPARENT);
504 };
505 new FetchThumbAssetTask(appContext, homeWallpaper, assetReceiver).executeOnExecutor(
506 AsyncTask.THREAD_POOL_EXECUTOR);
507
508 mCurrentWallpaperPresentationMode.setText(
509 AttributionFormatter.getHumanReadableWallpaperPresentationMode(
510 TopLevelPickerActivity.this, presentationMode));
511
512 List<String> attributions = homeWallpaper.getAttributions(appContext);
513 if (attributions.size() > 0 && attributions.get(0) != null) {
514 mCurrentWallpaperTitle.setText(attributions.get(0));
515 }
516
517 mCurrentWallpaperSubtitle.setText(
518 AttributionFormatter.formatWallpaperSubtitle(appContext, homeWallpaper));
519
520 final String actionUrl = homeWallpaper.getActionUrl(appContext);
521 if (actionUrl != null && !actionUrl.isEmpty()) {
522 Uri exploreUri = Uri.parse(actionUrl);
523
524 ExploreIntentChecker intentChecker = injector.getExploreIntentChecker(appContext);
525 intentChecker.fetchValidActionViewIntent(exploreUri, (@Nullable Intent exploreIntent) -> {
526 if (exploreIntent != null && !isDestroyed()) {
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700527 // Set the icon for the button
528 Drawable exploreButtonDrawable = getResources().getDrawable(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700529 homeWallpaper.getActionIconRes(appContext));
Santiago Etchebehered1bd5092018-04-18 16:03:30 -0700530
531 // This Drawable's state is shared across the app, so make a copy of it
532 // before applying a color tint as not to affect other clients elsewhere
533 // in the app.
534 exploreButtonDrawable = exploreButtonDrawable.getConstantState()
535 .newDrawable().mutate();
536 // Color the "compass" icon with the accent color.
537 exploreButtonDrawable.setColorFilter(
538 getResources().getColor(R.color.accent_color), Mode.SRC_IN);
539
540 ButtonDrawableSetterCompat.setDrawableToButtonStart(
541 mCurrentWallpaperExploreButton, exploreButtonDrawable);
542 mCurrentWallpaperExploreButton.setText(getString(
Santiago Etchebeheree0810d02018-05-10 17:39:40 -0700543 homeWallpaper.getActionLabelRes(appContext)));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800544 mCurrentWallpaperExploreButton.setVisibility(View.VISIBLE);
545 mCurrentWallpaperExploreButton.setOnClickListener(new OnClickListener() {
546 @Override
547 public void onClick(View v) {
Santiago Etchebeherece5613f2018-06-01 13:22:47 -0700548 mUserEventLogger.logActionClicked(
549 homeWallpaper.getCollectionId(appContext),
550 homeWallpaper.getActionLabelRes(appContext));
Jon Miranda16ea1b12017-12-12 14:52:48 -0800551 startActivity(exploreIntent);
552 }
553 });
554 }
555 });
556 } else {
557 mCurrentWallpaperExploreButton.setVisibility(View.GONE);
558 }
559
560 // Hide the wallpaper position options UI if the current home wallpaper is not from
561 // "my photos".
562 String homeCollectionId = homeWallpaper.getCollectionId(TopLevelPickerActivity.this);
563 if (mWallpaperPositionOptions != null
564 && homeCollectionId != null // May be null if app is being used for the first time.
565 && !homeCollectionId.equals(getString(R.string.image_wallpaper_collection_id))) {
566 mWallpaperPositionOptions.setVisibility(View.GONE);
567 }
568
569 boolean showSkipWallpaperButton = Flags.skipDailyWallpaperButtonEnabled
570 && presentationMode == WallpaperPreferences.PRESENTATION_MODE_ROTATING;
571 if (showSkipWallpaperButton) {
572 mCurrentWallpaperSkipWallpaperButton.setVisibility(View.VISIBLE);
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800573 mCurrentWallpaperSkipWallpaperButton.setOnClickListener(
574 v -> refreshDailyWallpaper());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800575 } else {
576 mCurrentWallpaperSkipWallpaperButton.setVisibility(View.GONE);
577 }
578
579 if (refreshListener != null) {
580 refreshListener.onCurrentWallpaperRefreshed();
581 }
582 }
583 }, true /* forceRefresh */);
584 }
585
586 @Override
587 public void onSaveInstanceState(Bundle savedInstanceState) {
588 FormFactorChecker formFactorChecker = InjectorProvider.getInjector().getFormFactorChecker(this);
589 if (formFactorChecker.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP) {
590 TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
591
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800592 // tabLayout is only present when the main IndividualPickerFragment is present (as
593 // opposed to
Jon Miranda16ea1b12017-12-12 14:52:48 -0800594 // the WallpaperDisabledFragment), so need this null check.
595 if (tabLayout != null) {
596 savedInstanceState.putInt(KEY_SELECTED_CATEGORY_TAB, tabLayout.getSelectedTabPosition());
597 }
598 }
599
600 super.onSaveInstanceState(savedInstanceState);
601 }
602
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800603 @Override
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700604 @Nullable
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800605 public CategoryFragment getCategoryFragment() {
606 if (mDelegate.getFormFactor() != FormFactorChecker.FORM_FACTOR_MOBILE) {
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700607 return null;
608 }
609 FragmentManager fm = getSupportFragmentManager();
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800610 return (CategoryFragment) fm.findFragmentById(R.id.fragment_container);
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700611 }
612
Jon Miranda16ea1b12017-12-12 14:52:48 -0800613 /**
614 * Populates the category tabs on DESKTOP form factor.
615 *
616 * @param selectedTabPosition The position of the tab to show as selected, or -1 if no particular
617 * tab should be selected (in which case: the tab of the category for the currently set
618 * wallpaper will be selected if enumerable; if not, the first enumerable category's tab will
619 * be selected).
620 */
621 private void populateCategoryTabs(int selectedTabPosition) {
622 final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
623 tabLayout.removeAllTabs();
624
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800625 String currentlySetCollectionId = mDelegate.getPreferences().getHomeWallpaperCollectionId();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800626
627 Tab tabToSelect = null;
628 Tab firstEnumerableCategoryTab = null;
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800629 for (int i = 0; i < mDelegate.getCategoryProvider().getSize(); i++) {
630 Category category = mDelegate.getCategoryProvider().getCategory(i);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800631
632 Tab tab = tabLayout.newTab();
633 tab.setText(category.getTitle());
634 tab.setTag(category);
635 tabLayout.addTab(tab, false /* setSelected */);
636
637 if (firstEnumerableCategoryTab == null && category.isEnumerable()) {
638 firstEnumerableCategoryTab = tab;
639 }
640
641 boolean shouldSelectTab = (i == selectedTabPosition)
642 || (selectedTabPosition == -1
643 && tabToSelect == null
644 && category.isEnumerable()
645 && currentlySetCollectionId != null
646 && currentlySetCollectionId.equals(category.getCollectionId()));
647
648 if (shouldSelectTab) {
649 tabToSelect = tab;
650 }
651 }
652
653 // If the above loop did not identify a specific tab to select, then just select the tab for
654 // the first enumerable category.
655 if (tabToSelect == null) {
656 tabToSelect = firstEnumerableCategoryTab;
657 }
658
659 // There may be no enumerable tabs (e.g., offline case), so we need to null-check again.
660 if (tabToSelect != null) {
661 tabToSelect.select();
662 }
663 }
664
665 /**
666 * Refreshes the current wallpaper in a daily wallpaper rotation.
667 */
668 private void refreshDailyWallpaper() {
669 // ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore
670 // causes Espresso to hang once the dialog is shown.
671 if (!mTestingMode) {
672 int themeResId;
673 if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
674 themeResId = R.style.ProgressDialogThemePreL;
675 } else {
676 themeResId = R.style.LightDialogTheme;
677 }
678 mRefreshWallpaperProgressDialog = new ProgressDialog(this, themeResId);
679 mRefreshWallpaperProgressDialog.setTitle(null);
680 mRefreshWallpaperProgressDialog.setMessage(
681 getResources().getString(R.string.refreshing_daily_wallpaper_dialog_message));
682 mRefreshWallpaperProgressDialog.setIndeterminate(true);
683 mRefreshWallpaperProgressDialog.show();
684 }
685
686 WallpaperRotationRefresher wallpaperRotationRefresher =
687 InjectorProvider.getInjector().getWallpaperRotationRefresher();
688 wallpaperRotationRefresher.refreshWallpaper(this, new Listener() {
689 @Override
690 public void onRefreshed() {
691 if (isDestroyed()) {
692 return;
693 }
694
695 if (mRefreshWallpaperProgressDialog != null) {
696 mRefreshWallpaperProgressDialog.dismiss();
697 }
698
699 refreshCurrentWallpapers(null /* refreshListener */);
700 }
701
702 @Override
703 public void onError() {
704 if (mRefreshWallpaperProgressDialog != null) {
705 mRefreshWallpaperProgressDialog.dismiss();
706 }
707
708 AlertDialog errorDialog = new AlertDialog.Builder(
709 TopLevelPickerActivity.this, R.style.LightDialogTheme)
710 .setMessage(R.string.refresh_daily_wallpaper_failed_message)
711 .setPositiveButton(android.R.string.ok, null /* onClickListener */)
712 .create();
713 errorDialog.show();
714 }
715 });
716 }
717
718 @Override
719 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
720 super.onActivityResult(requestCode, resultCode, data);
721
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800722 if (requestCode == WallpaperPickerDelegate.SHOW_CATEGORY_REQUEST_CODE
723 && resultCode == Activity.RESULT_OK) {
Santiago Etchebeheree5e05842019-02-13 16:58:07 -0800724 if (mDelegate.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP) {
725 Uri imageUri = (data == null) ? null : data.getData();
726 if (imageUri != null) {
727 // User selected an image from the system picker, so launch the preview for that
728 // image.
729 ImageWallpaperInfo imageWallpaper = new ImageWallpaperInfo(imageUri);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800730 setCustomPhotoWallpaper(imageWallpaper);
731 return;
732 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800733 }
Santiago Etchebeheree5e05842019-02-13 16:58:07 -0800734 }
735 if (mDelegate.handleActivityResult(requestCode, resultCode, data)) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800736 finishActivityWithResultOk();
737 }
738 }
739
740 /**
741 * Shows the view-only preview activity for the given wallpaper.
742 */
743 public void showViewOnlyPreview(WallpaperInfo wallpaperInfo) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800744 mDelegate.showViewOnlyPreview(wallpaperInfo);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800745 }
746
747 @Override
748 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
749 @NonNull int[] grantResults) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800750 mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800751 }
752
753 /**
754 * Shows the picker activity for the given category.
755 */
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800756 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800757 public void show(String collectionId) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800758 mDelegate.show(collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800759 }
760
761 private void reselectLastTab() {
762 TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
763
764 // In the offline case, "My photos" could be the only category. Thus we need this check --
765 // to ensure that we don't try to select the "previously selected" category which was -1.
766 if (mLastSelectedCategoryTabIndex > -1) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800767 Tab tabToSelect = tabLayout.getTabAt(
768 mLastSelectedCategoryTabIndex);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800769 if (((Category) tabToSelect.getTag()).isEnumerable()) {
770 tabToSelect.select();
771 }
772 }
773 }
774
Jon Miranda16ea1b12017-12-12 14:52:48 -0800775 private void showCategoryDesktop(String collectionId) {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800776 Category category = mDelegate.findCategoryForCollectionId(collectionId);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800777 if (category == null) {
778 return;
779 }
780
781 if (category.isEnumerable()) {
782 // Replace contained IndividualPickerFragment with a new instance for the given category.
783 final FragmentManager fm = getSupportFragmentManager();
784 Fragment fragment = fm.findFragmentById(R.id.fragment_container);
785 if (fragment != null) {
786 fm.beginTransaction()
787 .remove(fragment)
788 .commit();
789 }
790 IndividualPickerFragment newFragment = IndividualPickerFragment.newInstance(collectionId);
791 fm.beginTransaction()
792 .add(R.id.fragment_container, newFragment)
793 .commit();
794 newFragment.setCurrentWallpaperBottomSheetPresenter(this);
795 newFragment.setWallpapersUiContainer(this);
796 } else {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800797 category.show(this, mDelegate.getPickerIntentFactory(),
798 WallpaperPickerDelegate.SHOW_CATEGORY_REQUEST_CODE);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800799
800 // Need to select the tab here in case we are coming back from a "My photos" in which case
801 // the tab would have been set to "My photos" while viewing a regular image category.
802 reselectLastTab();
803 }
804 }
805
806 private void finishActivityWithResultOk() {
807 overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
808 setResult(Activity.RESULT_OK);
809 finish();
810 }
811
Jon Miranda16ea1b12017-12-12 14:52:48 -0800812 @Override
813 public void setCurrentWallpapersExpanded(boolean expanded) {
814 final BottomSheetBehavior<LinearLayout> bottomSheetBehavior =
815 BottomSheetBehavior.from(mBottomSheet);
816 bottomSheetBehavior.setState(
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800817 expanded ? BottomSheetBehavior.STATE_EXPANDED
818 : BottomSheetBehavior.STATE_COLLAPSED);
819 }
820
821 @Override
822 public void doneFetchingCategories() {
823 populateCategoryTabs(mLastSelectedCategoryTabIndex);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800824 }
825
826 @Override
827 public void onWallpapersReady() {
828 setDesktopLoading(false);
829 setCurrentWallpapersExpanded(true);
830 }
831
832 @Override
Santiago Etchebeherefab49612019-01-15 12:22:42 -0800833 public MyPhotosStarter getMyPhotosStarter() {
834 return this;
835 }
836
837 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800838 public void onClickTryAgain(@Destination int unused) {
839 // Retry the set wallpaper operation with the default center-crop setting.
840 if (mPendingSetWallpaperInfo != null) {
841 setCustomPhotoWallpaper(mPendingSetWallpaperInfo);
842 }
843 }
844
845 /**
846 * Sets the provides wallpaper to the device with center-cropped and scaled to fit the device's
847 * default display.
848 */
849 private void setCustomPhotoWallpaper(final WallpaperInfo wallpaper) {
850 // Save this WallpaperInfo so we can retry this operation later if it fails.
851 mPendingSetWallpaperInfo = wallpaper;
852
853 showSettingWallpaperProgressDialog();
854
855 mWallpaperPersister.setIndividualWallpaperWithPosition(this, wallpaper,
856 WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP, new SetWallpaperCallback() {
857 @Override
858 public void onSuccess() {
859 dismissSettingWallpaperProgressDialog();
860 refreshCurrentWallpapers(null /* refreshListener */);
861
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800862 mDelegate.getPreferences().setPendingWallpaperSetStatus(
Jon Miranda16ea1b12017-12-12 14:52:48 -0800863 WallpaperPreferences.WALLPAPER_SET_NOT_PENDING);
864 mUserEventLogger.logWallpaperSet(
865 wallpaper.getCollectionId(getApplicationContext()),
866 wallpaper.getWallpaperId());
867 mUserEventLogger.logWallpaperSetResult(UserEventLogger.WALLPAPER_SET_RESULT_SUCCESS);
868
869 // The user may have closed the activity before the set wallpaper operation completed.
870 if (isDestroyed()) {
871 return;
872 }
873
874 // Show the wallpaper crop option selector and bind click event handlers.
875 mWallpaperPositionOptions.setVisibility(View.VISIBLE);
876
877 mWasCustomPhotoWallpaperSet = true;
878 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP;
879
880 initializeWallpaperPositionOptionClickHandlers(wallpaper);
881 }
882
883 @Override
884 public void onError(Throwable throwable) {
885 dismissSettingWallpaperProgressDialog();
886 showSetWallpaperErrorDialog();
887
Santiago Etchebehere635e96f2018-12-04 18:31:34 -0800888 mDelegate.getPreferences().setPendingWallpaperSetStatus(
Jon Miranda16ea1b12017-12-12 14:52:48 -0800889 WallpaperPreferences.WALLPAPER_SET_NOT_PENDING);
890 mUserEventLogger.logWallpaperSetResult(
891 UserEventLogger.WALLPAPER_SET_RESULT_FAILURE);
892 @WallpaperSetFailureReason int failureReason = ThrowableAnalyzer.isOOM(throwable)
893 ? UserEventLogger.WALLPAPER_SET_FAILURE_REASON_OOM
894 : UserEventLogger.WALLPAPER_SET_FAILURE_REASON_OTHER;
895 mUserEventLogger.logWallpaperSetFailureReason(failureReason);
896 Log.e(TAG, "Unable to set wallpaper from 'my photos'.");
897 }
898 });
899 }
900
901 /**
902 * Initializes the wallpaper position button click handlers to change the way the provided
903 * wallpaper is set to the device.
904 */
905 private void initializeWallpaperPositionOptionClickHandlers(final WallpaperInfo wallpaperInfo) {
906 Button centerCropOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_center_crop);
907 Button stretchOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_stretched);
908 Button centerOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_center);
909
910 // The "center crop" wallpaper position button is selected by default.
911 setCenterCropWallpaperPositionButtonSelected(centerCropOptionBtn, true /* isSelected */);
912 centerCropOptionBtn.setOnClickListener(new OnClickListener() {
913 @Override
914 public void onClick(View view) {
915 mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
916 wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP,
917 new SetWallpaperCallback() {
918 @Override
919 public void onSuccess() {
920 // The user may have closed the activity before the set wallpaper operation
921 // completed.
922 if (isDestroyed()) {
923 return;
924 }
925
926 refreshCurrentWallpapers(null /* refreshListener */);
927
928 setCenterCropWallpaperPositionButtonSelected(
929 centerCropOptionBtn, true /* isSelected */);
930 setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
931 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
932
933 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP;
934 }
935
936 @Override
937 public void onError(@Nullable Throwable throwable) {
938 // no-op
939 }
940 });
941 }
942 });
943
944 // "Stretch" is not selected by default.
945 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
946 stretchOptionBtn.setOnClickListener(new OnClickListener() {
947 @Override
948 public void onClick(View view) {
949 mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
950 wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_STRETCH,
951 new SetWallpaperCallback() {
952 @Override
953 public void onSuccess() {
954 // The user may have closed the activity before the set wallpaper operation
955 // completed.
956 if (isDestroyed()) {
957 return;
958 }
959
960 refreshCurrentWallpapers(null /* refreshListener */);
961
962 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, true /* isSelected */);
963 setCenterCropWallpaperPositionButtonSelected(
964 centerCropOptionBtn, false /* isSelected */);
965 setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
966
967 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_STRETCH;
968 }
969
970 @Override
971 public void onError(@Nullable Throwable throwable) {
972 // no-op
973 }
974 });
975 }
976 });
977
978 // "Center" is not selected by default.
979 setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
980 centerOptionBtn.setOnClickListener(new OnClickListener() {
981 @Override
982 public void onClick(View view) {
983 mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
984 wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_CENTER,
985 new SetWallpaperCallback() {
986 @Override
987 public void onSuccess() {
988 // The user may have closed the activity before the set wallpaper operation
989 // completed.
990 if (isDestroyed()) {
991 return;
992 }
993
994 refreshCurrentWallpapers(null /* refreshListener */);
995
996 setCenterWallpaperPositionButtonSelected(centerOptionBtn, true /* isSelected */);
997 setCenterCropWallpaperPositionButtonSelected(
998 centerCropOptionBtn, false /* isSelected */);
999 setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
1000
1001 mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER;
1002 }
1003
1004 @Override
1005 public void onError(@Nullable Throwable throwable) {
1006 // no-op
1007 }
1008 });
1009 }
1010 });
1011 }
1012
1013 private void setCenterWallpaperPositionButtonSelected(Button button, boolean isSelected) {
1014 int drawableId = isSelected ? R.drawable.center_blue : R.drawable.center_grey;
1015 ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
1016 button.setTextColor(getColor(getTextColorIdForWallpaperPositionButton(isSelected)));
1017 }
1018
1019 private void setCenterCropWallpaperPositionButtonSelected(Button button, boolean isSelected) {
1020 int drawableId = isSelected ? R.drawable.center_crop_blue : R.drawable.center_crop_grey;
1021 ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
1022 button.setTextColor(getColor(getTextColorIdForWallpaperPositionButton(isSelected)));
1023 }
1024
1025 private void setStretchWallpaperPositionButtonSelected(Button button, boolean isSelected) {
1026 int drawableId = isSelected ? R.drawable.stretch_blue : R.drawable.stretch_grey;
1027 ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
1028 button.setTextColor(getColor(getTextColorIdForWallpaperPositionButton(isSelected)));
1029 }
1030
1031 private void showSettingWallpaperProgressDialog() {
Santiago Etchebehere635e96f2018-12-04 18:31:34 -08001032 // ProgressDialog endlessly updates the UI thread, keeping it from going idle which
1033 // therefore causes Espresso to hang once the dialog is shown.
Jon Miranda16ea1b12017-12-12 14:52:48 -08001034 if (!mTestingMode) {
1035 int themeResId;
1036 if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
1037 themeResId = R.style.ProgressDialogThemePreL;
1038 } else {
1039 themeResId = R.style.LightDialogTheme;
1040 }
1041 mSetWallpaperProgressDialog = new ProgressDialog(this, themeResId);
1042 mSetWallpaperProgressDialog.setTitle(null);
1043 mSetWallpaperProgressDialog.setMessage(
1044 getResources().getString(R.string.set_wallpaper_progress_message));
1045 mSetWallpaperProgressDialog.setIndeterminate(true);
1046 mSetWallpaperProgressDialog.show();
1047 }
1048 }
1049
1050 private void dismissSettingWallpaperProgressDialog() {
1051 if (mSetWallpaperProgressDialog != null) {
1052 mSetWallpaperProgressDialog.dismiss();
1053 }
1054 }
1055
1056 private void showSetWallpaperErrorDialog() {
1057 SetWallpaperErrorDialogFragment dialogFragment = SetWallpaperErrorDialogFragment.newInstance(
1058 R.string.set_wallpaper_error_message, WallpaperPersister.DEST_BOTH);
1059
1060 if (isSafeToCommitFragmentTransaction()) {
1061 dialogFragment.show(getSupportFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
1062 } else {
1063 mStagedSetWallpaperErrorDialogFragment = dialogFragment;
1064 }
1065 }
1066
1067 private interface AssetReceiver {
1068 void onAssetReceived(Asset asset);
1069 }
1070
1071 /**
1072 * An AsyncTask for asynchronously fetching the thumbnail asset for a given WallpaperInfo.
1073 * Used to work around expensive method call to WallpaperManager#getWallpaperFile made from the
1074 * CurrentWallpaperInfoVN getAsset() method.
1075 */
1076 private static class FetchThumbAssetTask extends AsyncTask<Void, Void, Asset> {
1077 private Context mAppContext;
1078 private WallpaperInfo mWallpaperInfo;
1079 private AssetReceiver mReceiver;
1080
1081 public FetchThumbAssetTask(Context appContext, WallpaperInfo wallpaperInfo,
1082 AssetReceiver receiver) {
1083 mAppContext = appContext;
1084 mWallpaperInfo = wallpaperInfo;
1085 mReceiver = receiver;
1086 }
1087
1088 @Override
1089 protected Asset doInBackground(Void... params) {
1090 return mWallpaperInfo.getThumbAsset(mAppContext);
1091 }
1092
1093 @Override
1094 protected void onPostExecute(Asset thumbAsset) {
1095 mReceiver.onAssetReceived(thumbAsset);
1096 }
1097 }
1098}