Merge "Move the same-name-different-product configs from res folder to res-product folder" into udc-dev
diff --git a/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java b/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java
index 5353f89..8777b4f 100644
--- a/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java
+++ b/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java
@@ -16,8 +16,12 @@
package com.android.settings.biometrics2.data.repository;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import androidx.annotation.NonNull;
+
/**
* This repository is used to call all APIs in {@link AccessibilityManager}
*/
@@ -44,4 +48,21 @@
public boolean isEnabled() {
return mAccessibilityManager.isEnabled();
}
+
+ /**
+ * Sends an {@link AccessibilityEvent}.
+ *
+ * @param event The event to send.
+ *
+ * @throws IllegalStateException if accessibility is not enabled.
+ *
+ * <strong>Note:</strong> The preferred mechanism for sending custom accessibility
+ * events is through calling
+ * {@link android.view.ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
+ * instead of this method to allow predecessors to augment/filter events sent by
+ * their descendants.
+ */
+ public void sendAccessibilityEvent(@NonNull AccessibilityEvent event) {
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ }
}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java
index 842bf42..74ae6fb 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java
@@ -410,12 +410,6 @@
}
}
- @Override
- public void onDestroy() {
- // TODO stopListenOrientationEvent();
- super.onDestroy();
- }
-
private void animateProgress(int progress) {
if (mProgressAnim != null) {
mProgressAnim.cancel();
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
index 7d2ef9f..a91e206 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
@@ -27,35 +27,34 @@
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Animatable2;
-import android.graphics.drawable.AnimatedVectorDrawable;
-import android.graphics.drawable.Drawable;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ProgressBar;
-import android.widget.TextView;
+import android.widget.RelativeLayout;
+import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
-import androidx.transition.Transition;
-import androidx.transition.TransitionSet;
import com.android.settings.R;
+import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
-import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
-import com.android.settingslib.display.DisplayDensityUtils;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieCompositionFactory;
@@ -73,8 +72,10 @@
public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
private static final String TAG = FingerprintEnrollEnrollingSfpsFragment.class.getSimpleName();
+ private static final boolean DEBUG = false;
private static final int PROGRESS_BAR_MAX = 10000;
+ private static final long ANIMATION_DURATION = 250L;
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
@@ -86,101 +87,75 @@
private static final int SFPS_STAGE_RIGHT_EDGE = 4;
private FingerprintEnrollEnrollingViewModel mEnrollingViewModel;
- private DeviceRotationViewModel mRotationViewModel;
private FingerprintEnrollProgressViewModel mProgressViewModel;
private Interpolator mFastOutSlowInInterpolator;
- private Interpolator mLinearOutSlowInInterpolator;
- private Interpolator mFastOutLinearInInterpolator;
- private boolean mAnimationCancelled;
private GlifLayout mView;
private ProgressBar mProgressBar;
private ObjectAnimator mProgressAnim;
- private TextView mErrorText;
- private FooterBarMixin mFooterBarMixin;
- private AnimatedVectorDrawable mIconAnimationDrawable;
- private AnimatedVectorDrawable mIconBackgroundBlinksDrawable;
private LottieAnimationView mIllustrationLottie;
- private boolean mShouldShowLottie;
- private boolean mIsAccessibilityEnabled;
private boolean mHaveShownSfpsNoAnimationLottie;
private boolean mHaveShownSfpsCenterLottie;
private boolean mHaveShownSfpsTipLottie;
private boolean mHaveShownSfpsLeftEdgeLottie;
private boolean mHaveShownSfpsRightEdgeLottie;
+ private ObjectAnimator mHelpAnimation;
+ private int mIconTouchCount;
private final View.OnClickListener mOnSkipClickListener =
(v) -> mEnrollingViewModel.onCancelledDueToOnSkipPressed();
+
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
- // TODO
- };
- private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
- // TODO
- };
- private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
- // TODO
- };
- private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
- // TODO
- };
- private final Observer<Integer> mPointerDownObserver = sensorId -> {
- // TODO
- };
- private final Observer<Integer> mPointerUpObserver = sensorId -> {
- // TODO
+ if (DEBUG) {
+ Log.d(TAG, "mProgressObserver(" + progress + ")");
+ }
+ if (progress != null && progress.getSteps() >= 0) {
+ onEnrollmentProgressChange(progress);
+ }
};
- private int mIconTouchCount;
+ private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
+ if (DEBUG) {
+ Log.d(TAG, "mHelpMessageObserver(" + helpMessage + ")");
+ }
+ if (helpMessage != null) {
+ onEnrollmentHelp(helpMessage);
+ }
+ };
+
+ private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
+ if (DEBUG) {
+ Log.d(TAG, "mErrorMessageObserver(" + errorMessage + ")");
+ }
+ if (errorMessage != null) {
+ onEnrollmentError(errorMessage);
+ }
+ };
@Override
public void onAttach(@NonNull Context context) {
final FragmentActivity activity = getActivity();
final ViewModelProvider provider = new ViewModelProvider(activity);
mEnrollingViewModel = provider.get(FingerprintEnrollEnrollingViewModel.class);
- mRotationViewModel = provider.get(DeviceRotationViewModel.class);
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
super.onAttach(context);
- final TransitionSet transitionSet = (TransitionSet) getSharedElementEnterTransition();
- if (transitionSet != null) {
- transitionSet.addListener(new Transition.TransitionListener() {
- @Override
- public void onTransitionStart(@NonNull Transition transition) {
-
- }
-
- @Override
- public void onTransitionEnd(@NonNull Transition transition) {
- transition.removeListener(this);
- mAnimationCancelled = false;
- startIconAnimation();
- }
-
- @Override
- public void onTransitionCancel(@NonNull Transition transition) {
-
- }
-
- @Override
- public void onTransitionPause(@NonNull Transition transition) {
-
- }
-
- @Override
- public void onTransitionResume(@NonNull Transition transition) {
-
- }
- });
- }
+ requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
+ @Override
+ public void handleOnBackPressed() {
+ setEnabled(false);
+ mEnrollingViewModel.setOnBackPressed();
+ cancelEnrollment();
+ }
+ });
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mEnrollingViewModel.restoreSavedState(savedInstanceState);
- mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
}
@Override
@@ -193,6 +168,7 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = initSfpsLayout(inflater, container);
+ maybeHideSfpsText(getActivity().getResources().getConfiguration());
return mView;
}
@@ -204,13 +180,22 @@
new GlifLayoutHelper(activity, containView).setDescriptionText(
getString(R.string.security_settings_fingerprint_enroll_start_message));
- mShouldShowLottie = shouldShowLottie(); // Move shouldShowLottie into updateOrientation()?
+ // setHelpAnimation()
+ final float translationX = 40;
+ final int duration = 550;
+ final RelativeLayout progressLottieLayout = containView.findViewById(R.id.progress_lottie);
+ mHelpAnimation = ObjectAnimator.ofFloat(progressLottieLayout,
+ "translationX" /* propertyName */,
+ 0, translationX, -1 * translationX, translationX, 0f);
+ mHelpAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
+ mHelpAnimation.setDuration(duration);
+ mHelpAnimation.setAutoCancel(false);
+
mIllustrationLottie = containView.findViewById(R.id.illustration_lottie);
- mErrorText = containView.findViewById(R.id.error_text);
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
- mFooterBarMixin = containView.getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
+ final FooterBarMixin footerBarMixin = containView.getMixin(FooterBarMixin.class);
+ footerBarMixin.setSecondaryButton(
new FooterButton.Builder(activity)
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
.setListener(mOnSkipClickListener)
@@ -221,10 +206,6 @@
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
activity, android.R.interpolator.fast_out_slow_in);
- mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
- activity, android.R.interpolator.linear_out_slow_in);
- mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
- activity, android.R.interpolator.fast_out_linear_in);
mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.SRC);
mProgressBar.setOnTouchListener((v, event) -> {
@@ -243,7 +224,6 @@
return true;
});
- maybeHideSfpsText(activity.getResources().getConfiguration());
return containView;
}
@@ -251,46 +231,135 @@
public void onStart() {
super.onStart();
startEnrollment();
- updateProgress(false /* animate */);
- updateTitleAndDescription(new GlifLayoutHelper(getActivity(), mView));
- if (true /* TODO mRestoring */) {
- startIconAnimation();
- }
+ updateProgress(false /* animate */, mProgressViewModel.getProgressLiveData().getValue());
+ updateTitleAndDescription();
}
@Override
public void onStop() {
- stopIconAnimation();
- mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
- mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
- mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
- mProgressViewModel.getAcquireLiveData().removeObserver(mAcquireObserver);
- mProgressViewModel.getPointerDownLiveData().removeObserver(mPointerDownObserver);
- mProgressViewModel.getPointerUpLiveData().removeObserver(mPointerUpObserver);
- if (!getActivity().isChangingConfigurations()) {
+ removeEnrollmentObservers();
+ if (!getActivity().isChangingConfigurations() && mProgressViewModel.isEnrolling()) {
mProgressViewModel.cancelEnrollment();
}
super.onStop();
}
+ private void removeEnrollmentObservers() {
+ preRemoveEnrollmentObservers();
+ mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
+ }
+
+ private void preRemoveEnrollmentObservers() {
+ mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
+ mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
+ }
+
+ private void cancelEnrollment() {
+ preRemoveEnrollmentObservers();
+ mProgressViewModel.cancelEnrollment();
+ }
+
private void startEnrollment() {
+ final boolean startResult = mProgressViewModel.startEnrollment(ENROLL_ENROLL);
+ if (!startResult) {
+ Log.e(TAG, "startEnrollment(), failed");
+ }
mProgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
mProgressViewModel.getHelpMessageLiveData().observe(this, mHelpMessageObserver);
mProgressViewModel.getErrorMessageLiveData().observe(this, mErrorMessageObserver);
- mProgressViewModel.getAcquireLiveData().observe(this, mAcquireObserver);
- mProgressViewModel.getPointerDownLiveData().observe(this, mPointerDownObserver);
- mProgressViewModel.getPointerUpLiveData().observe(this, mPointerUpObserver);
- mProgressViewModel.startEnrollment(ENROLL_ENROLL);
}
- private void updateProgress(boolean animate) {
+ private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
+ new GlifLayoutHelper(getActivity(), mView).setDescriptionText(description);
+ LottieCompositionFactory.fromRawRes(getActivity(), lottie)
+ .addListener((c) -> {
+ mIllustrationLottie.setComposition(c);
+ mIllustrationLottie.setVisibility(View.VISIBLE);
+ mIllustrationLottie.playAnimation();
+ });
+ }
+
+ private int getCurrentSfpsStage() {
+ EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
+
+ if (progressLiveData == null) {
+ return STAGE_UNKNOWN;
+ }
+
+ final int progressSteps = progressLiveData.getSteps() - progressLiveData.getRemaining();
+ if (progressSteps < getStageThresholdSteps(0)) {
+ return SFPS_STAGE_NO_ANIMATION;
+ } else if (progressSteps < getStageThresholdSteps(1)) {
+ return SFPS_STAGE_CENTER;
+ } else if (progressSteps < getStageThresholdSteps(2)) {
+ return SFPS_STAGE_FINGERTIP;
+ } else if (progressSteps < getStageThresholdSteps(3)) {
+ return SFPS_STAGE_LEFT_EDGE;
+ } else {
+ return SFPS_STAGE_RIGHT_EDGE;
+ }
+ }
+
+ private void onEnrollmentHelp(@NonNull EnrollmentStatusMessage helpMessage) {
+ final CharSequence helpStr = helpMessage.getStr();
+ if (!TextUtils.isEmpty(helpStr)) {
+ showError(helpStr);
+ }
+ }
+
+ private void onEnrollmentError(@NonNull EnrollmentStatusMessage errorMessage) {
+ removeEnrollmentObservers();
+
+ if (mEnrollingViewModel.getOnBackPressed()
+ && errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ mEnrollingViewModel.onCancelledDueToOnBackPressed();
+ } else if (mEnrollingViewModel.getOnSkipPressed()
+ && errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ mEnrollingViewModel.onCancelledDueToOnSkipPressed();
+ } else {
+ final int errMsgId = errorMessage.getMsgId();
+ mEnrollingViewModel.showErrorDialog(
+ new FingerprintEnrollEnrollingViewModel.ErrorDialogData(
+ getString(FingerprintErrorDialog.getErrorMessage(errMsgId)),
+ getString(FingerprintErrorDialog.getErrorTitle(errMsgId)),
+ errMsgId
+ ));
+ mProgressViewModel.cancelEnrollment();
+ }
+ }
+
+ private void announceEnrollmentProgress(CharSequence announcement) {
+ AccessibilityEvent event = new AccessibilityEvent();
+ event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
+ event.setClassName(getClass().getName());
+ event.setPackageName(getClass().getPackageName());
+ event.getText().add(announcement);
+ mEnrollingViewModel.sendAccessibilityEvent(event);
+ }
+
+ private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
+ updateProgress(true /* animate */, progress);
+ if (mEnrollingViewModel.isAccessibilityEnabled()) {
+ final int percent = (int) (((float) (progress.getSteps() - progress.getRemaining())
+ / (float) progress.getSteps()) * 100);
+
+ CharSequence announcement = getString(
+ R.string.security_settings_sfps_enroll_progress_a11y_message, percent);
+ announceEnrollmentProgress(announcement);
+
+ mIllustrationLottie.setContentDescription(
+ getString(R.string.security_settings_sfps_animation_a11y_label, percent)
+ );
+ }
+ updateTitleAndDescription();
+ }
+
+ private void updateProgress(boolean animate, @NonNull EnrollmentProgress enrollmentProgress) {
if (!mProgressViewModel.isEnrolling()) {
Log.d(TAG, "Enrollment not started yet");
return;
}
- final EnrollmentProgress enrollmentProgress =
- mProgressViewModel.getProgressLiveData().getValue();
final int progress = getProgress(enrollmentProgress);
// Only clear the error when progress has been made.
// TODO (b/234772728) Add tests.
@@ -318,19 +387,43 @@
return PROGRESS_BAR_MAX * displayProgress / (progress.getSteps() + 1);
}
+ private void showError(CharSequence error) {
+ mView.setHeaderText(error);
+ mView.getHeaderTextView().setContentDescription(error);
+ new GlifLayoutHelper(getActivity(), mView).setDescriptionText("");
+ if (!mHelpAnimation.isRunning()) {
+ mHelpAnimation.start();
+ }
+ applySfpsErrorDynamicColors(true);
+ if (isResumed() && mEnrollingViewModel.isAccessibilityEnabled()) {
+ mEnrollingViewModel.vibrateError(getClass().getSimpleName() + "::showError");
+ }
+ }
+
private void clearError() {
applySfpsErrorDynamicColors(false);
}
+ private void animateProgress(int progress) {
+ if (mProgressAnim != null) {
+ mProgressAnim.cancel();
+ }
+ ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, "progress",
+ mProgressBar.getProgress(), progress);
+ anim.addListener(mProgressAnimationListener);
+ anim.setInterpolator(mFastOutSlowInInterpolator);
+ anim.setDuration(ANIMATION_DURATION);
+ anim.start();
+ mProgressAnim = anim;
+ }
+
/**
* Applies dynamic colors corresponding to showing or clearing errors on the progress bar
* and finger lottie for SFPS
*/
private void applySfpsErrorDynamicColors(boolean isError) {
applyProgressBarDynamicColor(isError);
- if (mIllustrationLottie != null) {
- applyLottieDynamicColor(isError);
- }
+ applyLottieDynamicColor(isError);
}
private void applyProgressBarDynamicColor(boolean isError) {
@@ -358,36 +451,39 @@
mIllustrationLottie.invalidate();
}
- @Override
- public void onDestroy() {
- // TODO stopListenOrientationEvent();
- super.onDestroy();
- }
+ private int getStageThresholdSteps(int index) {
+ final EnrollmentProgress progressLiveData =
+ mProgressViewModel.getProgressLiveData().getValue();
- private void animateProgress(int progress) {
- if (mProgressAnim != null) {
- mProgressAnim.cancel();
+ if (progressLiveData == null || progressLiveData.getSteps() == -1) {
+ Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
+ return 1;
}
- ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, "progress",
- mProgressBar.getProgress(), progress);
- anim.addListener(mProgressAnimationListener);
- anim.setInterpolator(mFastOutSlowInInterpolator);
- anim.setDuration(250);
- anim.start();
- mProgressAnim = anim;
+ return Math.round(progressLiveData.getSteps()
+ * mEnrollingViewModel.getEnrollStageThreshold(index));
}
- private void updateTitleAndDescription(@NonNull GlifLayoutHelper glifLayoutHelper) {
- if (mIsAccessibilityEnabled) {
+ private void updateTitleAndDescription() {
+ final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(getActivity(), mView);
+ if (mEnrollingViewModel.isAccessibilityEnabled()) {
mEnrollingViewModel.clearTalkback();
glifLayoutHelper.getGlifLayout().getDescriptionTextView().setAccessibilityLiveRegion(
View.ACCESSIBILITY_LIVE_REGION_POLITE);
}
- switch (getCurrentSfpsStage()) {
+ final int stage = getCurrentSfpsStage();
+ if (DEBUG) {
+ Log.d(TAG, "updateTitleAndDescription, stage:" + stage
+ + ", noAnimation:" + mHaveShownSfpsNoAnimationLottie
+ + ", center:" + mHaveShownSfpsCenterLottie
+ + ", tip:" + mHaveShownSfpsTipLottie
+ + ", leftEdge:" + mHaveShownSfpsLeftEdgeLottie
+ + ", rightEdge:" + mHaveShownSfpsRightEdgeLottie);
+ }
+ switch (stage) {
case SFPS_STAGE_NO_ANIMATION:
glifLayoutHelper.setHeaderText(
R.string.security_settings_fingerprint_enroll_repeat_title);
- if (!mHaveShownSfpsNoAnimationLottie && mIllustrationLottie != null) {
+ if (!mHaveShownSfpsNoAnimationLottie) {
mHaveShownSfpsNoAnimationLottie = true;
mIllustrationLottie.setContentDescription(
getString(
@@ -405,7 +501,7 @@
case SFPS_STAGE_CENTER:
glifLayoutHelper.setHeaderText(
R.string.security_settings_sfps_enroll_finger_center_title);
- if (!mHaveShownSfpsCenterLottie && mIllustrationLottie != null) {
+ if (!mHaveShownSfpsCenterLottie) {
mHaveShownSfpsCenterLottie = true;
configureEnrollmentStage(
getString(R.string.security_settings_sfps_enroll_start_message),
@@ -417,7 +513,7 @@
case SFPS_STAGE_FINGERTIP:
glifLayoutHelper.setHeaderText(
R.string.security_settings_sfps_enroll_fingertip_title);
- if (!mHaveShownSfpsTipLottie && mIllustrationLottie != null) {
+ if (!mHaveShownSfpsTipLottie) {
mHaveShownSfpsTipLottie = true;
configureEnrollmentStage("", R.raw.sfps_lottie_tip);
}
@@ -426,7 +522,7 @@
case SFPS_STAGE_LEFT_EDGE:
glifLayoutHelper.setHeaderText(
R.string.security_settings_sfps_enroll_left_edge_title);
- if (!mHaveShownSfpsLeftEdgeLottie && mIllustrationLottie != null) {
+ if (!mHaveShownSfpsLeftEdgeLottie) {
mHaveShownSfpsLeftEdgeLottie = true;
configureEnrollmentStage("", R.raw.sfps_lottie_left_edge);
}
@@ -435,7 +531,7 @@
case SFPS_STAGE_RIGHT_EDGE:
glifLayoutHelper.setHeaderText(
R.string.security_settings_sfps_enroll_right_edge_title);
- if (!mHaveShownSfpsRightEdgeLottie && mIllustrationLottie != null) {
+ if (!mHaveShownSfpsRightEdgeLottie) {
mHaveShownSfpsRightEdgeLottie = true;
configureEnrollmentStage("", R.raw.sfps_lottie_right_edge);
}
@@ -460,7 +556,38 @@
}
}
- private void maybeHideSfpsText(@android.annotation.NonNull Configuration newConfig) {
+ private void showIconTouchDialog() {
+ mIconTouchCount = 0;
+ //TODO EnrollingActivity should observe live data and add dialog fragment
+ mEnrollingViewModel.onIconTouchDialogShow();
+ }
+
+ private final Runnable mShowDialogRunnable = () -> showIconTouchDialog();
+
+ private final Animator.AnimatorListener mProgressAnimationListener =
+ new Animator.AnimatorListener() {
+
+ @Override
+ public void onAnimationStart(Animator animation) { }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) { }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
+ mProgressBar.postDelayed(mDelayedFinishRunnable, ANIMATION_DURATION);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) { }
+ };
+
+ // Give the user a chance to see progress completed before jumping to the next stage.
+ private final Runnable mDelayedFinishRunnable = () -> mEnrollingViewModel.onEnrollingDone();
+
+ private void maybeHideSfpsText(@NonNull Configuration newConfig) {
final HeaderMixin headerMixin = ((GlifLayout) mView).getMixin(HeaderMixin.class);
final DescriptionMixin descriptionMixin = ((GlifLayout) mView).getMixin(
DescriptionMixin.class);
@@ -480,137 +607,4 @@
}
}
-
- private int getCurrentSfpsStage() {
- EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
-
- if (progressLiveData == null || progressLiveData.getSteps() == -1) {
- return STAGE_UNKNOWN;
- }
-
- final int progressSteps = progressLiveData.getSteps() - progressLiveData.getRemaining();
- if (progressSteps < getStageThresholdSteps(0)) {
- return SFPS_STAGE_NO_ANIMATION;
- } else if (progressSteps < getStageThresholdSteps(1)) {
- return SFPS_STAGE_CENTER;
- } else if (progressSteps < getStageThresholdSteps(2)) {
- return SFPS_STAGE_FINGERTIP;
- } else if (progressSteps < getStageThresholdSteps(3)) {
- return SFPS_STAGE_LEFT_EDGE;
- } else {
- return SFPS_STAGE_RIGHT_EDGE;
- }
- }
-
- private int getStageThresholdSteps(int index) {
- final EnrollmentProgress progressLiveData =
- mProgressViewModel.getProgressLiveData().getValue();
-
- if (progressLiveData == null || progressLiveData.getSteps() == -1) {
- Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
- return 1;
- }
- return Math.round(progressLiveData.getSteps()
- * mEnrollingViewModel.getEnrollStageThreshold(index));
- }
-
- private void updateOrientation() {
- mIllustrationLottie = mView.findViewById(R.id.illustration_lottie);
- }
-
- private boolean shouldShowLottie() {
- DisplayDensityUtils displayDensity = new DisplayDensityUtils(getContext());
- int currentDensityIndex = displayDensity.getCurrentIndexForDefaultDisplay();
- final int currentDensity = displayDensity.getDefaultDisplayDensityValues()
- [currentDensityIndex];
- final int defaultDensity = displayDensity.getDefaultDensityForDefaultDisplay();
- return defaultDensity == currentDensity;
- }
-
-
- private void startIconAnimation() {
- if (mIconAnimationDrawable != null) {
- mIconAnimationDrawable.start();
- }
- }
-
- private void stopIconAnimation() {
- mAnimationCancelled = true;
- if (mIconAnimationDrawable != null) {
- mIconAnimationDrawable.stop();
- }
- }
-
- private void showIconTouchDialog() {
- mIconTouchCount = 0;
- //TODO EnrollingActivity should observe live data and add dialog fragment
- mEnrollingViewModel.onIconTouchDialogShow();
- }
-
- private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
- new GlifLayoutHelper(getActivity(), mView).setDescriptionText(description);
- LottieCompositionFactory.fromRawRes(getActivity(), lottie)
- .addListener((c) -> {
- mIllustrationLottie.setComposition(c);
- mIllustrationLottie.setVisibility(View.VISIBLE);
- mIllustrationLottie.playAnimation();
- });
- }
-
- private final Runnable mShowDialogRunnable = new Runnable() {
- @Override
- public void run() {
- showIconTouchDialog();
- }
- };
-
- private final Animator.AnimatorListener mProgressAnimationListener =
- new Animator.AnimatorListener() {
-
- @Override
- public void onAnimationStart(Animator animation) {
- startIconAnimation();
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) { }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- stopIconAnimation();
-
- if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
- mProgressBar.postDelayed(mDelayedFinishRunnable, 250L);
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) { }
- };
-
- // Give the user a chance to see progress completed before jumping to the next stage.
- private final Runnable mDelayedFinishRunnable = new Runnable() {
- @Override
- public void run() {
- /* TODO launchFinish(); */
- }
- };
-
- private final Animatable2.AnimationCallback mIconAnimationCallback =
- new Animatable2.AnimationCallback() {
- @Override
- public void onAnimationEnd(Drawable d) {
- if (mAnimationCancelled) {
- return;
- }
-
- // Start animation after it has ended.
- mProgressBar.post(new Runnable() {
- @Override
- public void run() {
- startIconAnimation();
- }
- });
- }
- };
}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.java
index 1ea26fa..61f8e82 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -32,6 +33,7 @@
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
@@ -39,6 +41,7 @@
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
+import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
@@ -67,12 +70,23 @@
private FingerprintEnrollFindSensorViewModel mViewModel;
private FingerprintEnrollProgressViewModel mProgressViewModel;
+ private DeviceRotationViewModel mRotationViewModel;
private View mView;
private GlifLayout mGlifLayout;
private FooterBarMixin mFooterBarMixin;
private final OnClickListener mOnSkipClickListener = (v) -> mViewModel.onSkipButtonClick();
@Nullable private FingerprintFindSensorAnimation mAnimation;
+ @Surface.Rotation private int mLastRotation = -1;
+
+ private final Observer<Integer> mRotationObserver = rotation -> {
+ if (DEBUG) {
+ Log.d(TAG, "rotationObserver " + rotation);
+ }
+ if (rotation != null) {
+ onRotationChanged(rotation);
+ }
+ };
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
if (DEBUG) {
@@ -85,15 +99,10 @@
private final Observer<EnrollmentStatusMessage> mLastCancelMessageObserver = errorMessage -> {
if (DEBUG) {
- Log.d(TAG, "mErrorMessageObserver(" + errorMessage + ")");
+ Log.d(TAG, "mLastCancelMessageObserver(" + errorMessage + ")");
}
if (errorMessage != null) {
- if (errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
- mProgressViewModel.clearProgressLiveData();
- mViewModel.onStartButtonClick();
- } else {
- Log.e(TAG, "mErrorMessageObserver(" + errorMessage + ")");
- }
+ onLastCancelMessage(errorMessage);
}
};
@@ -144,6 +153,10 @@
@Override
public void onResume() {
+ final LiveData<Integer> rotationLiveData = mRotationViewModel.getLiveData();
+ mLastRotation = rotationLiveData.getValue();
+ rotationLiveData.observe(this, mRotationObserver);
+
if (mAnimation != null) {
if (DEBUG) {
Log.d(TAG, "onResume(), start animation");
@@ -198,15 +211,39 @@
return;
}
+ if (waitForLastCancelErrMsg) {
+ mProgressViewModel.clearErrorMessageLiveData(); // Prevent got previous error message
+ mProgressViewModel.getErrorMessageLiveData().observe(this,
+ mLastCancelMessageObserver);
+ }
+
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
final boolean cancelResult = mProgressViewModel.cancelEnrollment();
if (!cancelResult) {
Log.e(TAG, "stopLookingForFingerprint(), failed to cancel enrollment");
}
+ }
- if (waitForLastCancelErrMsg) {
- mProgressViewModel.getErrorMessageLiveData().observe(this,
- mLastCancelMessageObserver);
+ private void onRotationChanged(@Surface.Rotation int newRotation) {
+ if (DEBUG) {
+ Log.d(TAG, "onRotationChanged() from " + mLastRotation + " to " + newRotation);
+ }
+ if (newRotation % 2 != mLastRotation % 2) {
+ // Fragment is going to be recreated, just stopLookingForFingerprint() here.
+ stopLookingForFingerprint(true);
+ }
+ }
+
+ private void onLastCancelMessage(@NonNull EnrollmentStatusMessage errorMessage) {
+ if (errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ final EnrollmentProgress progress = mProgressViewModel.getProgressLiveData().getValue();
+ mProgressViewModel.clearProgressLiveData();
+ mProgressViewModel.getErrorMessageLiveData().removeObserver(mLastCancelMessageObserver);
+ if (progress != null && !progress.isInitialStep()) {
+ mViewModel.onStartButtonClick();
+ }
+ } else {
+ Log.e(TAG, "mErrorMessageObserver(" + errorMessage + ")");
}
}
@@ -227,6 +264,7 @@
final ViewModelProvider provider = new ViewModelProvider(activity);
mViewModel = provider.get(FingerprintEnrollFindSensorViewModel.class);
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
+ mRotationViewModel = provider.get(DeviceRotationViewModel.class);
super.onAttach(context);
}
}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.java
index c363f04..75207ca 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.java
@@ -20,6 +20,7 @@
import android.app.Activity;
import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@@ -39,6 +40,7 @@
import com.android.settings.R;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
+import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel;
import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
@@ -75,30 +77,36 @@
private DeviceRotationViewModel mRotationViewModel;
private DeviceFoldedViewModel mFoldedViewModel;
+ private GlifLayout mView;
+ private FooterBarMixin mFooterBarMixin;
+ private final OnClickListener mOnSkipClickListener = (v) -> mViewModel.onSkipButtonClick();
+ private LottieAnimationView mIllustrationLottie;
+ @Surface.Rotation private int mAnimationRotation = -1;
+
private final Observer<Integer> mRotationObserver = rotation -> {
if (DEBUG) {
Log.d(TAG, "rotationObserver " + rotation);
}
- if (rotation == null) {
- return;
+ if (rotation != null) {
+ onRotationChanged(rotation);
}
- onRotationChanged(rotation);
};
- @Surface.Rotation private int mAnimationRotation = -1;
-
- private View mView;
- private GlifLayout mGlifLayout;
- private FooterBarMixin mFooterBarMixin;
- private final OnClickListener mOnSkipClickListener = (v) -> mViewModel.onSkipButtonClick();
- private LottieAnimationView mIllustrationLottie;
-
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
if (DEBUG) {
Log.d(TAG, "mProgressObserver(" + progress + ")");
}
if (progress != null && !progress.isInitialStep()) {
- mViewModel.onStartButtonClick();
+ stopLookingForFingerprint(true);
+ }
+ };
+
+ private final Observer<EnrollmentStatusMessage> mLastCancelMessageObserver = errorMessage -> {
+ if (DEBUG) {
+ Log.d(TAG, "mLastCancelMessageObserver(" + errorMessage + ")");
+ }
+ if (errorMessage != null) {
+ onLastCancelMessage(errorMessage);
}
};
@@ -107,10 +115,10 @@
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
final Context context = inflater.getContext();
- mView = inflater.inflate(R.layout.sfps_enroll_find_sensor_layout, container, false);
- mGlifLayout = mView.findViewById(R.id.setup_wizard_layout);
+ mView = (GlifLayout) inflater.inflate(R.layout.sfps_enroll_find_sensor_layout, container,
+ false);
mIllustrationLottie = mView.findViewById(R.id.illustration_lottie);
- mFooterBarMixin = mGlifLayout.getMixin(FooterBarMixin.class);
+ mFooterBarMixin = mView.getMixin(FooterBarMixin.class);
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(context)
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
@@ -125,7 +133,7 @@
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final Activity activity = getActivity();
- final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, mGlifLayout);
+ final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, mView);
glifLayoutHelper.setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title);
glifLayoutHelper.setDescriptionText(
getText(R.string.security_settings_sfps_enroll_find_sensor_message));
@@ -136,10 +144,13 @@
public void onStart() {
super.onStart();
+ final boolean isEnrolling = mProgressViewModel.isEnrolling();
if (DEBUG) {
- Log.d(TAG, "onStart(), start looking for fingerprint");
+ Log.d(TAG, "onStart(), isEnrolling:" + isEnrolling);
}
- startLookingForFingerprint();
+ if (!isEnrolling) {
+ startLookingForFingerprint();
+ }
}
@Override
@@ -159,10 +170,13 @@
@Override
public void onStop() {
super.onStop();
+ final boolean isEnrolling = mProgressViewModel.isEnrolling();
if (DEBUG) {
- Log.d(TAG, "onStop(), stop looking for fingerprint");
+ Log.d(TAG, "onStop(), isEnrolling:" + isEnrolling);
}
- stopLookingForFingerprint();
+ if (isEnrolling) {
+ stopLookingForFingerprint(false);
+ }
}
private void startLookingForFingerprint() {
@@ -180,13 +194,19 @@
}
}
- private void stopLookingForFingerprint() {
+ private void stopLookingForFingerprint(boolean waitForLastCancelErrMsg) {
if (!mProgressViewModel.isEnrolling()) {
Log.d(TAG, "stopLookingForFingerprint(), failed because isEnrolling is false before"
+ " stopping");
return;
}
+ if (waitForLastCancelErrMsg) {
+ mProgressViewModel.clearErrorMessageLiveData(); // Prevent got previous error message
+ mProgressViewModel.getErrorMessageLiveData().observe(this,
+ mLastCancelMessageObserver);
+ }
+
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
final boolean cancelResult = mProgressViewModel.cancelEnrollment();
if (!cancelResult) {
@@ -199,10 +219,25 @@
Log.d(TAG, "onRotationChanged() from " + mAnimationRotation + " to " + newRotation);
}
if ((newRotation + 2) % 4 == mAnimationRotation) {
+ // Fragment not changed, we just need to play correct rotation animation
playLottieAnimation(newRotation);
+ } else if (newRotation % 2 != mAnimationRotation % 2) {
+ // Fragment is going to be recreated, just stopLookingForFingerprint() here.
+ stopLookingForFingerprint(true);
}
- // Fragment will be re-created if it's changed between landscape and portrait, so no need to
- // handle other cases.
+ }
+
+ private void onLastCancelMessage(@NonNull EnrollmentStatusMessage errorMessage) {
+ if (errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ final EnrollmentProgress progress = mProgressViewModel.getProgressLiveData().getValue();
+ mProgressViewModel.clearProgressLiveData();
+ mProgressViewModel.getErrorMessageLiveData().removeObserver(mLastCancelMessageObserver);
+ if (progress != null && !progress.isInitialStep()) {
+ mViewModel.onStartButtonClick();
+ }
+ } else {
+ Log.e(TAG, "mErrorMessageObserver(" + errorMessage + ")");
+ }
}
private void playLottieAnimation(@Surface.Rotation int rotation) {
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
index bf7b0ac..6a9adb7 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
@@ -23,6 +23,8 @@
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.util.Log;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
@@ -279,6 +281,23 @@
}
/**
+ * Sends an {@link AccessibilityEvent}.
+ *
+ * @param event The event to send.
+ *
+ * @throws IllegalStateException if accessibility is not enabled.
+ *
+ * <strong>Note:</strong> The preferred mechanism for sending custom accessibility
+ * events is through calling
+ * {@link android.view.ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
+ * instead of this method to allow predecessors to augment/filter events sent by
+ * their descendants.
+ */
+ public void sendAccessibilityEvent(@NonNull AccessibilityEvent event) {
+ mAccessibilityRepository.sendAccessibilityEvent(event);
+ }
+
+ /**
* Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
* caller to specify the vibration is owned by someone else and set a reason for vibration.
*/
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
index eebbc42..2a918f5 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
@@ -92,6 +92,9 @@
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
+ if (DEBUG) {
+ Log.d(TAG, "onEnrollmentError(" + errMsgId + ", " + errString + ")");
+ }
mErrorMessageLiveData.postValue(new EnrollmentStatusMessage(errMsgId, errString));
}
@@ -146,6 +149,13 @@
mErrorMessageLiveData.setValue(null);
}
+ /**
+ * clear error message
+ */
+ public void clearErrorMessageLiveData() {
+ mErrorMessageLiveData.setValue(null);
+ }
+
public LiveData<EnrollmentProgress> getProgressLiveData() {
return mProgressLiveData;
}
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index 395d1c7..3047d73 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -27,6 +27,7 @@
import android.net.NetworkPolicy;
import android.net.NetworkTemplate;
import android.os.Bundle;
+import android.provider.Settings;
import android.text.method.NumberKeyListener;
import android.util.Log;
import android.view.LayoutInflater;
@@ -54,6 +55,7 @@
import java.text.NumberFormat;
import java.text.ParseException;
+import java.util.Optional;
import java.util.TimeZone;
@SearchIndexable
@@ -115,6 +117,18 @@
Bundle args = getArguments();
mNetworkTemplate = args.getParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE);
+ if (mNetworkTemplate == null && getIntent() != null) {
+ mNetworkTemplate = getIntent().getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
+ }
+
+ if (mNetworkTemplate == null) {
+ Optional<NetworkTemplate> mobileNetworkTemplateFromSim =
+ DataUsageUtils.getMobileNetworkTemplateFromSubId(context, getIntent());
+ if (mobileNetworkTemplateFromSim.isPresent()) {
+ mNetworkTemplate = mobileNetworkTemplateFromSim.get();
+ }
+ }
+
if (mNetworkTemplate == null) {
mNetworkTemplate = DataUsageUtils.getDefaultTemplate(context,
DataUsageUtils.getDefaultSubscriptionId(context));
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 1499ded..68751e5 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -69,6 +69,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
/**
* Panel showing data usage history across various networks, including options
@@ -266,6 +267,14 @@
mSubId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mTemplate = intent.getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
+
+ if (mTemplate == null) {
+ Optional<NetworkTemplate> mobileNetworkTemplateFromSim =
+ DataUsageUtils.getMobileNetworkTemplateFromSubId(getContext(), getIntent());
+ if (mobileNetworkTemplateFromSim.isPresent()) {
+ mTemplate = mobileNetworkTemplateFromSim.get();
+ }
+ }
}
}
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 9fec27e..cce7ca1 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -22,11 +22,13 @@
import android.app.usage.NetworkStats.Bucket;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -39,6 +41,7 @@
import com.android.settings.network.ProxySubscriptionManager;
import java.util.List;
+import java.util.Optional;
/**
* Utility methods for data usage classes.
@@ -193,4 +196,22 @@
}
}
+ /**
+ * Returns a mobile NetworkTemplate if EXTRA_SUB_ID of the Intent is available and the subId
+ * is valid & hasMobileData. Otherwise, returns empty data.
+ */
+ public static Optional<NetworkTemplate> getMobileNetworkTemplateFromSubId(Context context,
+ Intent intent) {
+ if (intent == null || !intent.hasExtra(Settings.EXTRA_SUB_ID)) {
+ return Optional.empty();
+ }
+
+ int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ if (SubscriptionManager.isValidSubscriptionId(subId) && hasMobileData(context)) {
+ return Optional.of(DataUsageLib.getMobileTemplate(context, subId));
+ }
+
+ return Optional.empty();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 695e86b..16d1483 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -56,9 +56,11 @@
import com.android.internal.content.PackageMonitor;
import com.android.settings.R;
import com.android.settings.testutils.XmlTestUtils;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexableRaw;
@@ -85,6 +87,7 @@
/** Test for {@link AccessibilitySettings}. */
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothUtils.class})
public class AccessibilitySettingsTest {
private static final String PACKAGE_NAME = "com.android.test";
private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service";
@@ -116,6 +119,8 @@
private ShadowAccessibilityManager mShadowAccessibilityManager;
@Mock
private AppOpsManager mAppOpsManager;
+ @Mock
+ private LocalBluetoothManager mLocalBluetoothManager;
private Lifecycle mLifecycle;
@@ -134,6 +139,7 @@
anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ALLOWED);
mLifecycle = new Lifecycle(() -> mLifecycle);
when(mFragment.getSettingsLifecycle()).thenReturn(mLifecycle);
+ ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
}
@Test