diff --git a/res/drawable-night/ic_enhanced_connectivity.xml b/res/drawable-night/ic_enhanced_connectivity.xml new file mode 100644 index 00000000000..cd256676316 --- /dev/null +++ b/res/drawable-night/ic_enhanced_connectivity.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/ic_enhanced_connectivity.xml b/res/drawable/ic_enhanced_connectivity.xml new file mode 100644 index 00000000000..45767bd7d44 --- /dev/null +++ b/res/drawable/ic_enhanced_connectivity.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/accessibility_autoclick_preview.xml b/res/layout/accessibility_autoclick_preview.xml deleted file mode 100644 index 4fa3f8ff8a0..00000000000 --- a/res/layout/accessibility_autoclick_preview.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml index 65c1497d9ff..5f828799269 100644 --- a/res/layout/fingerprint_enroll_introduction.xml +++ b/res/layout/fingerprint_enroll_introduction.xml @@ -98,7 +98,7 @@ android:paddingTop="24dp"> - + android:elevation="2dp" + settings:layout_constraintTop_toTopOf="parent"/> - + android:layout_height="wrap_content" + android:clipToPadding="false" + android:scrollbars="none" + android:visibility="invisible" + settings:fastScrollEnabled="true" + settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable" + settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable" + settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable" + settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable" + settings:layout_constraintTop_toBottomOf="@id/pinned_header"/> - + - - - - - - - + + diff --git a/res/layout/preference_animated_image.xml b/res/layout/preference_animated_image.xml deleted file mode 100644 index 64cfc982ef7..00000000000 --- a/res/layout/preference_animated_image.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/res/raw/lottie_swipe_for_notifications.json b/res/raw/lottie_swipe_for_notifications.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/values/dimens.xml b/res/values/dimens.xml index fe0ada08622..1b8179abdaf 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -149,8 +149,6 @@ 182dp 32dp 24dp - - 80dp 88dip diff --git a/res/values/strings.xml b/res/values/strings.xml index aeaea6116b8..26fbd795575 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -926,16 +926,8 @@ Cancel No thanks - - No thanks - - Continue I agree - - Skip - - Next Skip fingerprint? @@ -12892,6 +12884,8 @@ Restart No thanks + + Cancel Switch @@ -13389,7 +13383,7 @@ No connection - Internet won\u0027t auto\u2011connect + Mobile data won\u0027t auto\u2011connect No other networks available diff --git a/res/xml/accessibility_autoclick_settings.xml b/res/xml/accessibility_autoclick_settings.xml index ee27cea24e5..06b3dced4e2 100644 --- a/res/xml/accessibility_autoclick_settings.xml +++ b/res/xml/accessibility_autoclick_settings.xml @@ -19,14 +19,13 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/accessibility_autoclick_preference_title"> - + settings:searchable="false" + settings:lottie_rawRes="@drawable/accessibility_dwell" /> - + - + + diff --git a/src/com/android/settings/accessibility/AnimatedImagePreference.java b/src/com/android/settings/accessibility/AnimatedImagePreference.java deleted file mode 100644 index c707e5cc0a7..00000000000 --- a/src/com/android/settings/accessibility/AnimatedImagePreference.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.accessibility; - -import android.content.Context; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Animatable2; -import android.graphics.drawable.AnimationDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import androidx.preference.Preference; -import androidx.preference.PreferenceViewHolder; - -import com.android.settings.R; - -import com.airbnb.lottie.LottieAnimationView; -import com.airbnb.lottie.LottieDrawable; - -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.Objects; - -/** - * A custom {@link ImageView} preference for showing animated or static image, such as animated webp and static png. - */ -public class AnimatedImagePreference extends Preference { - - private static final String TAG = "AnimatedImagePreference"; - private Uri mImageUri; - private int mMaxHeight = -1; - - private final Animatable2.AnimationCallback mAnimationCallback = - new Animatable2.AnimationCallback() { - @Override - public void onAnimationEnd(Drawable drawable) { - ((Animatable2) drawable).start(); - } - }; - - AnimatedImagePreference(Context context) { - super(context); - setLayoutResource(R.layout.preference_animated_image); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - super.onBindViewHolder(holder); - - final ImageView imageView = holder.itemView.findViewById(R.id.animated_img); - final LottieAnimationView lottieView = holder.itemView.findViewById(R.id.lottie_view); - if (imageView == null || lottieView == null) { - return; - } - - if (mImageUri != null) { - resetAnimations(imageView, lottieView); - hideAllChildViews(holder.itemView); - - imageView.setImageURI(mImageUri); - if (imageView.getDrawable() != null) { - startAnimationWith(imageView); - } else { - // The lottie image from the raw folder also returns null. - startLottieAnimationWith(lottieView); - } - } - - if (mMaxHeight > -1) { - imageView.setMaxHeight(mMaxHeight); - lottieView.setMaxHeight(mMaxHeight); - } - } - - /** - * Sets image uri to display image in {@link ImageView} - * - * @param imageUri the Uri of an image - */ - public void setImageUri(Uri imageUri) { - if (imageUri != null && !imageUri.equals(mImageUri)) { - mImageUri = imageUri; - notifyChanged(); - } - } - - /** - * Sets the maximum height of the view. - * - * @param maxHeight the maximum height of ImageView in terms of pixels. - */ - public void setMaxHeight(int maxHeight) { - if (maxHeight != mMaxHeight) { - mMaxHeight = maxHeight; - notifyChanged(); - } - } - - private void startAnimationWith(ImageView imageView) { - startAnimation(imageView.getDrawable()); - - imageView.setVisibility(View.VISIBLE); - } - - private void startLottieAnimationWith(LottieAnimationView lottieView) { - final InputStream inputStream = getInputStreamFromUri(mImageUri); - Objects.requireNonNull(inputStream, "Invalid resource."); - lottieView.setAnimation(inputStream, /* cacheKey= */ null); - lottieView.setRepeatCount(LottieDrawable.INFINITE); - lottieView.playAnimation(); - - lottieView.setVisibility(View.VISIBLE); - } - - private void startAnimation(Drawable drawable) { - if (!(drawable instanceof Animatable)) { - return; - } - - if (drawable instanceof Animatable2) { - ((Animatable2) drawable).registerAnimationCallback(mAnimationCallback); - } else if (drawable instanceof AnimationDrawable) { - ((AnimationDrawable) drawable).setOneShot(false); - } - - ((Animatable) drawable).start(); - } - - private void resetAnimations(ImageView imageView, LottieAnimationView lottieView) { - resetAnimation(imageView.getDrawable()); - - lottieView.cancelAnimation(); - } - - private void resetAnimation(Drawable drawable) { - if (!(drawable instanceof Animatable)) { - return; - } - - if (drawable instanceof Animatable2) { - ((Animatable2) drawable).clearAnimationCallbacks(); - } - - ((Animatable) drawable).stop(); - } - - private InputStream getInputStreamFromUri(Uri uri) { - try { - return getContext().getContentResolver().openInputStream(uri); - } catch (FileNotFoundException e) { - Log.w(TAG, "Cannot find content uri: " + uri, e); - return null; - } - } - - private void hideAllChildViews(View itemView) { - final ViewGroup viewGroup = (ViewGroup) itemView; - for (int i = 0; i < viewGroup.getChildCount(); i++) { - viewGroup.getChildAt(i).setVisibility(View.GONE); - } - } -} diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index 640ae532161..510f8d3484a 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -59,6 +59,7 @@ import com.android.settings.widget.SettingsMainSwitchBar; import com.android.settings.widget.SettingsMainSwitchPreference; import com.android.settingslib.HelpUtils; import com.android.settingslib.accessibility.AccessibilityUtils; +import com.android.settingslib.widget.IllustrationPreference; import com.android.settingslib.widget.OnMainSwitchChangeListener; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -398,15 +399,13 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference return; } - final int screenHalfHeight = AccessibilityUtil.getScreenHeightPixels(getPrefContext()) / 2; - final AnimatedImagePreference animatedImagePreference = - new AnimatedImagePreference(getPrefContext()); - animatedImagePreference.setImageUri(mImageUri); - animatedImagePreference.setSelectable(false); - animatedImagePreference.setMaxHeight(screenHalfHeight); - animatedImagePreference.setKey(KEY_ANIMATED_IMAGE); + final IllustrationPreference illustrationPreference = + new IllustrationPreference(getPrefContext()); + illustrationPreference.setImageUri(mImageUri); + illustrationPreference.setSelectable(false); + illustrationPreference.setKey(KEY_ANIMATED_IMAGE); - getPreferenceScreen().addPreference(animatedImagePreference); + getPreferenceScreen().addPreference(illustrationPreference); } private void initToggleServiceSwitchPreference() { diff --git a/src/com/android/settings/applications/RunningServices.java b/src/com/android/settings/applications/RunningServices.java index 4d13241126f..b1689d5c591 100644 --- a/src/com/android/settings/applications/RunningServices.java +++ b/src/com/android/settings/applications/RunningServices.java @@ -72,7 +72,11 @@ public class RunningServices extends SettingsPreferenceFragment { public void onResume() { super.onResume(); boolean haveData = mRunningProcessesView.doResume(this, mRunningProcessesAvail); - mLoadingViewController.handleLoadingContainer(haveData /* done */, false /* animate */); + if (haveData) { + mLoadingViewController.showContent(false /* animate */); + } else { + mLoadingViewController.showLoadingView(); + } } @Override diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultAppPreferenceController.java index fd6f4c243e7..d962692e2df 100644 --- a/src/com/android/settings/applications/defaultapps/DefaultAppPreferenceController.java +++ b/src/com/android/settings/applications/defaultapps/DefaultAppPreferenceController.java @@ -65,11 +65,19 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC ((TwoTargetPreference) preference).setIconSize(ICON_SIZE_MEDIUM); } if (!TextUtils.isEmpty(defaultAppLabel)) { - preference.setSummary(defaultAppLabel); + if (showLabelAsTitle()) { + preference.setTitle(defaultAppLabel); + } else { + preference.setSummary(defaultAppLabel); + } preference.setIcon(Utils.getSafeIcon(getDefaultAppIcon())); } else { Log.d(TAG, "No default app"); - preference.setSummary(R.string.app_list_preference_none); + if (showLabelAsTitle()) { + preference.setTitle(R.string.app_list_preference_none); + } else { + preference.setSummary(R.string.app_list_preference_none); + } preference.setIcon(null); } mayUpdateGearIcon(app, preference); @@ -102,6 +110,13 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC return null; } + /** + * Whether to show the default app label as the title, instead of as the summary. + */ + protected boolean showLabelAsTitle() { + return false; + } + public Drawable getDefaultAppIcon() { if (!isAvailable()) { return null; diff --git a/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java index d32322b6fdb..1493e302881 100644 --- a/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java +++ b/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java @@ -69,4 +69,9 @@ public class DefaultAutofillPreferenceController extends DefaultAppPreferenceCon } return null; } + + @Override + protected boolean showLabelAsTitle() { + return true; + } } diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index 6d675240b64..43e929b8054 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -208,7 +208,6 @@ public class ManageApplications extends InstrumentedFragment private ApplicationsAdapter mApplications; private View mLoadingContainer; - private View mListContainer; private SearchView mSearchView; // Size resource used for packages whose size computation failed for some reason @@ -402,25 +401,21 @@ public class ManageApplications extends InstrumentedFragment mRootView = inflater.inflate(R.layout.manage_applications_apps, null); mLoadingContainer = mRootView.findViewById(R.id.loading_container); - mListContainer = mRootView.findViewById(R.id.list_container); - if (mListContainer != null) { - // Create adapter and list view here - mEmptyView = mListContainer.findViewById(android.R.id.empty); + mEmptyView = mRootView.findViewById(android.R.id.empty); + mRecyclerView = mRootView.findViewById(R.id.apps_list); - mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter, - savedInstanceState); - if (savedInstanceState != null) { - mApplications.mHasReceivedLoadEntries = - savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false); - mApplications.mHasReceivedBridgeCallback = - savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false); - } - mRecyclerView = mListContainer.findViewById(R.id.apps_list); - mRecyclerView.setItemAnimator(null); - mRecyclerView.setLayoutManager(new LinearLayoutManager( - getContext(), RecyclerView.VERTICAL, false /* reverseLayout */)); - mRecyclerView.setAdapter(mApplications); + mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter, + savedInstanceState); + if (savedInstanceState != null) { + mApplications.mHasReceivedLoadEntries = + savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false); + mApplications.mHasReceivedBridgeCallback = + savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false); } + mRecyclerView.setItemAnimator(null); + mRecyclerView.setLayoutManager(new LinearLayoutManager( + getContext(), RecyclerView.VERTICAL, false /* reverseLayout */)); + mRecyclerView.setAdapter(mApplications); // We have to do this now because PreferenceFrameLayout looks at it // only when the view is added. @@ -985,16 +980,8 @@ public class ManageApplications extends InstrumentedFragment // overlapped by floating filter. if (hasFilter) { mManageApplications.mSpinnerHeader.setVisibility(View.VISIBLE); - mManageApplications.mRecyclerView.setPadding(0 /* left */, - mContext.getResources().getDimensionPixelSize( - R.dimen.app_bar_height) /* top */, - 0 /* right */, - 0 /* bottom */); } else { mManageApplications.mSpinnerHeader.setVisibility(View.GONE); - mManageApplications.mRecyclerView.setPadding(0 /* left */, 0 /* top */, - 0 /* right */, - 0 /* bottom */); } } } @@ -1044,7 +1031,8 @@ public class ManageApplications extends InstrumentedFragment mManageApplications = manageApplications; mLoadingViewController = new LoadingViewController( mManageApplications.mLoadingContainer, - mManageApplications.mListContainer + mManageApplications.mRecyclerView, + mManageApplications.mEmptyView ); mContext = manageApplications.getActivity(); mIconDrawableFactory = IconDrawableFactory.newInstance(mContext); @@ -1303,11 +1291,9 @@ public class ManageApplications extends InstrumentedFragment mOriginalEntries = entries; notifyDataSetChanged(); if (getItemCount() == 0) { - mManageApplications.mRecyclerView.setVisibility(View.GONE); - mManageApplications.mEmptyView.setVisibility(View.VISIBLE); + mLoadingViewController.showEmpty(false /* animate */); } else { - mManageApplications.mEmptyView.setVisibility(View.GONE); - mManageApplications.mRecyclerView.setVisibility(View.VISIBLE); + mLoadingViewController.showContent(false /* animate */); if (mManageApplications.mSearchView != null && mManageApplications.mSearchView.isVisibleToUser()) { @@ -1324,10 +1310,6 @@ public class ManageApplications extends InstrumentedFragment mLastIndex = -1; } - if (mSession.getAllApps().size() != 0 - && mManageApplications.mListContainer.getVisibility() != View.VISIBLE) { - mLoadingViewController.showContent(true /* animate */); - } if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) { // No enabled or disabled filters for usage access. return; diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java index 8c3b1ceb89a..a75fb0f4526 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java @@ -64,9 +64,13 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction { super.onCreate(savedInstanceState); final ImageView iconFingerprint = findViewById(R.id.icon_fingerprint); + final ImageView iconDeviceLocked = findViewById(R.id.icon_device_locked); + final ImageView iconTrashCan = findViewById(R.id.icon_trash_can); final ImageView iconInfo = findViewById(R.id.icon_info); final ImageView iconLink = findViewById(R.id.icon_link); iconFingerprint.getDrawable().setColorFilter(getIconColorFilter()); + iconDeviceLocked.getDrawable().setColorFilter(getIconColorFilter()); + iconTrashCan.getDrawable().setColorFilter(getIconColorFilter()); iconInfo.getDrawable().setColorFilter(getIconColorFilter()); iconLink.getDrawable().setColorFilter(getIconColorFilter()); @@ -87,7 +91,7 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction { @StringRes int getNegativeButtonTextId() { - return R.string.security_settings_fingerprint_enroll_introduction_skip; + return R.string.security_settings_fingerprint_enroll_introduction_no_thanks; } @StringRes diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java index e1059119b16..4bd8afd98ed 100644 --- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java @@ -26,7 +26,6 @@ import android.os.UserHandle; import android.view.View; import com.android.internal.widget.LockPatternUtils; -import com.android.settings.R; import com.android.settings.SetupWizardUtils; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricUtils; @@ -34,8 +33,6 @@ import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.SetupChooseLockGeneric; import com.android.settings.password.SetupSkipDialog; -import com.google.android.setupcompat.template.FooterButton; - public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction { /** * Returns the number of fingerprint enrolled. @@ -56,11 +53,6 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu } } - @Override - int getNegativeButtonTextId() { - return R.string.security_settings_face_enroll_introduction_cancel; - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -78,19 +70,6 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu return intent; } - @Override - protected void initViews() { - super.initViews(); - - FooterButton nextButton = getNextButton(); - nextButton.setText( - this, R.string.security_settings_fingerprint_enroll_introduction_continue_setup); - - final FooterButton cancelButton = getCancelButton(); - cancelButton.setText( - this, R.string.security_settings_fingerprint_enroll_introduction_cancel_setup); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // if lock was already present, do not return intent data since it must have been diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java index 6d1cbfd35d9..51c6b663671 100644 --- a/src/com/android/settings/gestures/OneHandedSettings.java +++ b/src/com/android/settings/gestures/OneHandedSettings.java @@ -16,19 +16,18 @@ package com.android.settings.gestures; +import android.app.Activity; import android.app.settings.SettingsEnums; import android.content.ComponentName; import android.content.Context; import android.os.Bundle; import android.os.UserHandle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.settings.R; import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment; import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.widget.IllustrationPreference; /** * Fragment for One-handed mode settings @@ -37,13 +36,27 @@ import com.android.settings.search.BaseSearchIndexProvider; * providing basic accessibility shortcut service setup. */ public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { + private static final String ONE_HANDED_SHORTCUT_KEY = "one_handed_shortcuts_preference"; + private static final String ONE_HANDED_ILLUSTRATION_KEY = "one_handed_header"; private String mFeatureName; + private OneHandedSettingsUtils mUtils; @Override protected void updatePreferenceStates() { OneHandedSettingsUtils.setUserId(UserHandle.myUserId()); super.updatePreferenceStates(); + + final IllustrationPreference preference = + (IllustrationPreference) getPreferenceScreen().findPreference( + ONE_HANDED_ILLUSTRATION_KEY); + if (preference != null) { + final boolean isSwipeDownNotification = + OneHandedSettingsUtils.isSwipeDownNotificationEnabled(getContext()); + preference.setLottieAnimationResId( + isSwipeDownNotification ? R.raw.lottie_swipe_for_notifications + : R.raw.lottie_one_hand_mode); + } } @Override @@ -69,9 +82,21 @@ public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return super.onCreateView(inflater, container, savedInstanceState); + public void onStart() { + super.onStart(); + mUtils = new OneHandedSettingsUtils(this.getContext()); + mUtils.registerToggleAwareObserver(uri -> { + Activity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread(() -> updatePreferenceStates()); + } + }); + } + + @Override + public void onStop() { + super.onStop(); + mUtils.unregisterToggleAwareObserver(); } @Override diff --git a/src/com/android/settings/network/AdaptiveConnectivityTogglePreferenceController.java b/src/com/android/settings/network/AdaptiveConnectivityTogglePreferenceController.java index e1e56a8a6fa..e3d779ce938 100644 --- a/src/com/android/settings/network/AdaptiveConnectivityTogglePreferenceController.java +++ b/src/com/android/settings/network/AdaptiveConnectivityTogglePreferenceController.java @@ -22,12 +22,14 @@ import android.provider.Settings; import androidx.preference.PreferenceScreen; -import com.android.settings.core.TogglePreferenceController; +import com.android.settings.widget.SettingsMainSwitchPreferenceController; /** - * {@link TogglePreferenceController} that controls whether Adaptive connectivity option is enabled. + * {@link SettingsMainSwitchPreferenceController} + * that controls whether Adaptive connectivity option is enabled. */ -public class AdaptiveConnectivityTogglePreferenceController extends TogglePreferenceController { +public class AdaptiveConnectivityTogglePreferenceController extends + SettingsMainSwitchPreferenceController { private final WifiManager mWifiManager; diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java index 0064e6ccfd2..e67ac42af47 100644 --- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java +++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java @@ -338,7 +338,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc getString(R.string.sim_action_restart_title), getString(R.string.sim_action_enable_dsds_text), getString(R.string.sim_action_reboot), - getString(R.string.cancel)); + getString(R.string.sim_action_cancel)); } /* Displays the SIM toggling confirmation dialog. */ @@ -359,7 +359,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc title, null, getString(R.string.yes), - getString(R.string.cancel)); + getString(R.string.sim_action_cancel)); } private void showEnableSimConfirmDialog() { @@ -384,7 +384,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc getSwitchSubscriptionTitle(), getSwitchDialogBodyMsg(activeSub, isBetweenEsim), getSwitchDialogPosBtnText(), - getString(android.R.string.cancel)); + getString(R.string.sim_action_cancel)); } private void showNonSwitchSimConfirmDialog() { @@ -395,7 +395,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc getEnableSubscriptionTitle(), null /* msg */, getString(R.string.yes), - getString(android.R.string.cancel)); + getString(R.string.sim_action_cancel)); } private String getSwitchDialogPosBtnText() { diff --git a/src/com/android/settings/notification/history/NotificationSbnViewHolder.java b/src/com/android/settings/notification/history/NotificationSbnViewHolder.java index c98b036d7e2..166ee5d4ffc 100644 --- a/src/com/android/settings/notification/history/NotificationSbnViewHolder.java +++ b/src/com/android/settings/notification/history/NotificationSbnViewHolder.java @@ -65,9 +65,6 @@ public class NotificationSbnViewHolder extends RecyclerView.ViewHolder { } void setTitle(CharSequence title) { - if (title == null) { - return; - } mTitle.setText(title); } diff --git a/src/com/android/settings/widget/LoadingViewController.java b/src/com/android/settings/widget/LoadingViewController.java index 294e55e7ea8..66eebf387ba 100644 --- a/src/com/android/settings/widget/LoadingViewController.java +++ b/src/com/android/settings/widget/LoadingViewController.java @@ -22,34 +22,66 @@ import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import androidx.annotation.Nullable; + /** - * A helper class that manages show/hide loading spinner. + * A helper class that manages show/hide loading spinner, content view and empty view (optional). */ public class LoadingViewController { private static final long DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS = 100L; - public final Handler mFgHandler; - public final View mLoadingView; - public final View mContentView; + private final Handler mFgHandler; + private final View mLoadingView; + private final View mContentView; + private final View mEmptyView; public LoadingViewController(View loadingView, View contentView) { + this(loadingView, contentView, null /* emptyView*/); + } + + public LoadingViewController(View loadingView, View contentView, @Nullable View emptyView) { mLoadingView = loadingView; mContentView = contentView; + mEmptyView = emptyView; mFgHandler = new Handler(Looper.getMainLooper()); } private Runnable mShowLoadingContainerRunnable = new Runnable() { public void run() { - handleLoadingContainer(false /* done */, false /* animate */); + showLoadingView(); } }; + /** + * Shows content view and hides loading view & empty view. + */ public void showContent(boolean animate) { // Cancel any pending task to show the loading animation and show the list of // apps directly. mFgHandler.removeCallbacks(mShowLoadingContainerRunnable); - handleLoadingContainer(true /* show */, animate); + handleLoadingContainer(true /* showContent */, false /* showEmpty*/, animate); + } + + /** + * Shows empty view and hides loading view & content view. + */ + public void showEmpty(boolean animate) { + if (mEmptyView == null) { + return; + } + + // Cancel any pending task to show the loading animation and show the list of + // apps directly. + mFgHandler.removeCallbacks(mShowLoadingContainerRunnable); + handleLoadingContainer(false /* showContent */, true /* showEmpty */, animate); + } + + /** + * Shows loading view and hides content view & empty view. + */ + public void showLoadingView() { + handleLoadingContainer(false /* showContent */, false /* showEmpty */, false /* animate */); } public void showLoadingViewDelayed() { @@ -57,8 +89,9 @@ public class LoadingViewController { mShowLoadingContainerRunnable, DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS); } - public void handleLoadingContainer(boolean done, boolean animate) { - handleLoadingContainer(mLoadingView, mContentView, done, animate); + private void handleLoadingContainer(boolean showContent, boolean showEmpty, boolean animate) { + handleLoadingContainer(mLoadingView, mContentView, mEmptyView, + showContent, showEmpty, animate); } /** @@ -75,6 +108,25 @@ public class LoadingViewController { setViewShown(content, done, animate); } + /** + * Show/hide loading view and content view and empty view. + * + * @param loading The loading spinner view + * @param content The content view + * @param empty The empty view shows no item summary to users. + * @param showContent If true, content is set visible and loading is set invisible. + * @param showEmpty If true, empty is set visible and loading is set invisible. + * @param animate Whether or not content/loading views should animate in/out. + */ + public static void handleLoadingContainer(View loading, View content, View empty, + boolean showContent, boolean showEmpty, boolean animate) { + if (empty != null) { + setViewShown(empty, showEmpty, animate); + } + setViewShown(content, showContent, animate); + setViewShown(loading, !showContent && !showEmpty, animate); + } + private static void setViewShown(final View view, boolean shown, boolean animate) { if (animate) { Animation animation = AnimationUtils.loadAnimation(view.getContext(), diff --git a/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java deleted file mode 100644 index c7e5b13be83..00000000000 --- a/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.accessibility; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import android.content.ContentResolver; -import android.content.Context; -import android.graphics.drawable.AnimatedImageDrawable; -import android.graphics.drawable.AnimatedVectorDrawable; -import android.graphics.drawable.AnimationDrawable; -import android.net.Uri; -import android.view.ViewGroup; -import android.widget.ImageView; - -import androidx.preference.PreferenceViewHolder; - -import com.android.settings.R; - -import com.airbnb.lottie.LottieAnimationView; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -import java.io.InputStream; - -/** Tests for {@link AnimatedImagePreference}. */ -@RunWith(RobolectricTestRunner.class) -public class AnimatedImagePreferenceTest { - private final Context mContext = RuntimeEnvironment.application; - private Uri mImageUri; - private PreferenceViewHolder mViewHolder; - private AnimatedImagePreference mAnimatedImagePreference; - - @Mock - private ViewGroup mRootView; - - @Spy - private ImageView mImageView; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - - mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(mRootView)); - doReturn(new LottieAnimationView(mContext)).when(mRootView).findViewById(R.id.lottie_view); - mImageView = spy(new ImageView(mContext)); - - mAnimatedImagePreference = new AnimatedImagePreference(mContext); - mImageUri = new Uri.Builder().build(); - } - - @Test - public void playAnimation_animatedImageDrawable_success() { - final AnimatedImageDrawable drawable = mock(AnimatedImageDrawable.class); - doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img); - doReturn(drawable).when(mImageView).getDrawable(); - - mAnimatedImagePreference.setImageUri(mImageUri); - mAnimatedImagePreference.onBindViewHolder(mViewHolder); - - verify(drawable).start(); - } - - @Test - public void playAnimation_animatedVectorDrawable_success() { - final AnimatedVectorDrawable drawable = mock(AnimatedVectorDrawable.class); - doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img); - doReturn(drawable).when(mImageView).getDrawable(); - - mAnimatedImagePreference.setImageUri(mImageUri); - mAnimatedImagePreference.onBindViewHolder(mViewHolder); - - verify(drawable).start(); - } - - @Test - public void playAnimation_animationDrawable_success() { - final AnimationDrawable drawable = mock(AnimationDrawable.class); - doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img); - doReturn(drawable).when(mImageView).getDrawable(); - - mAnimatedImagePreference.setImageUri(mImageUri); - mAnimatedImagePreference.onBindViewHolder(mViewHolder); - - verify(drawable).start(); - } - - @Test - public void setImageUri_viewNotExist_setFail() { - doReturn(null).when(mRootView).findViewById(R.id.animated_img); - - mAnimatedImagePreference.setImageUri(mImageUri); - mAnimatedImagePreference.onBindViewHolder(mViewHolder); - - verify(mImageView, never()).setImageURI(mImageUri); - } - - @Test - public void setMaxHeight_success() { - final int maxHeight = 100; - doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img); - - mAnimatedImagePreference.setMaxHeight(maxHeight); - mAnimatedImagePreference.onBindViewHolder(mViewHolder); - - assertThat(mImageView.getMaxHeight()).isEqualTo(maxHeight); - } - - @Test - public void setImageUriAndRebindViewHolder_lottieImageFromRawFolder_setAnimation() { - final int fakeLottieResId = 111111; - final Uri lottieImageUri = - new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - .authority(mContext.getPackageName()) - .appendPath(String.valueOf(fakeLottieResId)) - .build(); - final LottieAnimationView lottieView = spy(new LottieAnimationView(mContext)); - doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img); - doReturn(lottieView).when(mRootView).findViewById(R.id.lottie_view); - - mAnimatedImagePreference.setImageUri(lottieImageUri); - mAnimatedImagePreference.onBindViewHolder(mViewHolder); - - verify(lottieView).setAnimation(any(InputStream.class), eq(null)); - } -} diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java index 86f5fe83c6c..25eca7adb22 100644 --- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java +++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java @@ -28,7 +28,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -49,7 +48,6 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.widget.SearchView; import androidx.fragment.app.FragmentActivity; @@ -155,22 +153,6 @@ public class ManageApplicationsTest { assertThat(mMenu.findItem(R.id.sort_order_frequent_notification).isVisible()).isFalse(); } - @Test - public void onCreateView_shouldNotShowLoadingContainer() { - ReflectionHelpers.setField(mFragment, "mResetAppsHelper", mock(ResetAppsHelper.class)); - doNothing().when(mFragment).createHeader(); - - final LayoutInflater layoutInflater = mock(LayoutInflater.class); - final View view = mock(View.class); - final View loadingContainer = mock(View.class); - when(layoutInflater.inflate(anyInt(), eq(null))).thenReturn(view); - when(view.findViewById(R.id.loading_container)).thenReturn(loadingContainer); - - mFragment.onCreateView(layoutInflater, mock(ViewGroup.class), null); - - verify(loadingContainer, never()).setVisibility(View.VISIBLE); - } - @Test public void onCreateOptionsMenu_shouldSetSearchQueryListener() { final SearchView searchView = mock(SearchView.class); @@ -221,7 +203,6 @@ public class ManageApplicationsTest { @Test public void updateLoading_appLoaded_shouldNotDelayCallToHandleLoadingContainer() { ReflectionHelpers.setField(mFragment, "mLoadingContainer", mock(View.class)); - ReflectionHelpers.setField(mFragment, "mListContainer", mock(View.class)); final ManageApplications.ApplicationsAdapter adapter = spy(new ManageApplications.ApplicationsAdapter(mState, mFragment, AppFilterRegistry.getInstance().get(FILTER_APPS_ALL), new Bundle())); @@ -243,7 +224,6 @@ public class ManageApplicationsTest { @Test public void updateLoading_appNotLoaded_shouldDelayCallToHandleLoadingContainer() { ReflectionHelpers.setField(mFragment, "mLoadingContainer", mock(View.class)); - ReflectionHelpers.setField(mFragment, "mListContainer", mock(View.class)); final ManageApplications.ApplicationsAdapter adapter = spy(new ManageApplications.ApplicationsAdapter(mState, mFragment, AppFilterRegistry.getInstance().get(FILTER_APPS_ALL), new Bundle())); @@ -272,7 +252,6 @@ public class ManageApplicationsTest { when(listContainer.getVisibility()).thenReturn(View.INVISIBLE); when(listContainer.getContext()).thenReturn(context); ReflectionHelpers.setField(mFragment, "mLoadingContainer", loadingContainer); - ReflectionHelpers.setField(mFragment, "mListContainer", listContainer); final ManageApplications.ApplicationsAdapter adapter = spy(new ManageApplications.ApplicationsAdapter(mState, mFragment, AppFilterRegistry.getInstance().get(FILTER_APPS_ALL), new Bundle())); @@ -296,7 +275,7 @@ public class ManageApplicationsTest { adapter.onRebuildComplete(null); - verify(loadingViewController).showContent(true /* animate */); + verify(loadingViewController).showEmpty(false /* animate */); } @Test @@ -304,15 +283,16 @@ public class ManageApplicationsTest { final String query = "Test"; final RecyclerView recyclerView = mock(RecyclerView.class); final View emptyView = mock(View.class); + final View loadingContainer = mock(View.class); ReflectionHelpers.setField(mFragment, "mRecyclerView", recyclerView); ReflectionHelpers.setField(mFragment, "mEmptyView", emptyView); + ReflectionHelpers.setField(mFragment, "mLoadingContainer", loadingContainer); final SearchView searchView = mock(SearchView.class); ReflectionHelpers.setField(mFragment, "mSearchView", searchView); when(searchView.isVisibleToUser()).thenReturn(true); when(searchView.getQuery()).thenReturn(query); final View listContainer = mock(View.class); when(listContainer.getVisibility()).thenReturn(View.VISIBLE); - ReflectionHelpers.setField(mFragment, "mListContainer", listContainer); ReflectionHelpers.setField( mFragment, "mFilterAdapter", mock(ManageApplications.FilterSpinnerAdapter.class)); final ArrayList appList = new ArrayList<>(); @@ -491,8 +471,6 @@ public class ManageApplicationsTest { mFragment.mFilterAdapter.updateFilterView(true); assertThat(mFragment.mSpinnerHeader.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mFragment.mRecyclerView.getPaddingTop()).isEqualTo( - mContext.getResources().getDimensionPixelSize(R.dimen.app_bar_height)); } @Test