summaryrefslogtreecommitdiff
path: root/PermissionController/src/com/android/permissioncontroller/safetycenter
diff options
context:
space:
mode:
authorTyler Dewey <deweytyl@google.com>2023-03-08 11:33:12 +0000
committerTyler Dewey <deweytyl@google.com>2023-03-13 13:42:35 +0000
commit33daeba42d7fc94e48a585e3afca457466814e84 (patch)
treedd8b4ffc00c38475da934702183e2fec9d8b44ca /PermissionController/src/com/android/permissioncontroller/safetycenter
parent031ed668b811efc948ecd2c1ff2f48ebc543eab4 (diff)
downloadPermission-33daeba42d7fc94e48a585e3afca457466814e84.tar.gz
Extract status card view and clean up button logic.
Bug: 269725572 Test: atest CtsSafetyCenterTestCases SafetyCenterFunctionalTestCases Change-Id: Ia79d13b4ac770e864724ff6fb16f9df6656fda92
Diffstat (limited to 'PermissionController/src/com/android/permissioncontroller/safetycenter')
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java190
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt76
3 files changed, 181 insertions, 112 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
index 6c1c7aa90..61b36fc60 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
@@ -40,8 +40,7 @@ import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterViewModel;
import com.android.permissioncontroller.safetycenter.ui.model.StatusUiData;
-
-import com.google.android.material.button.MaterialButton;
+import com.android.permissioncontroller.safetycenter.ui.view.StatusCardView;
import kotlin.Pair;
@@ -81,68 +80,68 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
}
Context context = getContext();
- ImageView statusImage = (ImageView) holder.findViewById(R.id.status_image);
- MaterialButton rescanButton = (MaterialButton) holder.findViewById(R.id.rescan_button);
- MaterialButton pendingActionsRescanButton =
- (MaterialButton) holder.findViewById(R.id.pending_actions_rescan_button);
- View reviewSettingsButton = holder.findViewById(R.id.review_settings_button);
- if (mStatus.hasPendingActions()) {
- reviewSettingsButton.setOnClickListener(
- l -> {
- requireViewModel()
- .navigateToSafetyCenter(
- context, NavigationSource.QUICK_SETTINGS_TILE);
- requireViewModel()
- .getInteractionLogger()
- .record(Action.REVIEW_SETTINGS_CLICKED);
- });
- reviewSettingsButton.setVisibility(View.VISIBLE);
- } else {
- reviewSettingsButton.setVisibility(View.GONE);
- }
- rescanButton = updateRescanButtonUi(rescanButton, pendingActionsRescanButton);
- setRescanButtonState(rescanButton);
-
- holder.findViewById(R.id.status_title_and_summary)
+ StatusCardView statusCardView = (StatusCardView) holder.itemView;
+ configureButtons(context, statusCardView);
+ statusCardView
+ .getTitleAndSummaryContainerView()
.setContentDescription(mStatus.getContentDescription(context));
- rescanButton.setOnClickListener(
- unused -> {
- SafetyCenterViewModel viewModel = requireViewModel();
- viewModel.rescan();
- viewModel.getInteractionLogger().record(Action.SCAN_INITIATED);
- });
-
- updateStatusIcon(statusImage, rescanButton);
+ updateStatusIcon(statusCardView);
- TextView titleTextView = (TextView) holder.findViewById(R.id.status_title);
- TextView summaryTextView = (TextView) holder.findViewById(R.id.status_summary);
- updateStatusText(titleTextView, summaryTextView);
+ updateStatusText(statusCardView.getTitleView(), statusCardView.getSummaryView());
- configureSafetyProtectionView(holder, context);
+ configureSafetyProtectionView(statusCardView, context);
mFirstBind = false;
}
- private void configureSafetyProtectionView(PreferenceViewHolder holder, Context context) {
- View safetyProtectionSectionView = holder.findViewById(R.id.safety_protection_section_view);
+ private void configureButtons(Context context, StatusCardView statusCardView) {
+ statusCardView
+ .getRescanButton()
+ .setOnClickListener(
+ unused -> {
+ SafetyCenterViewModel viewModel = requireViewModel();
+ viewModel.rescan();
+ viewModel.getInteractionLogger().record(Action.SCAN_INITIATED);
+ });
+ statusCardView
+ .getReviewSettingsButton()
+ .setOnClickListener(
+ unused -> {
+ SafetyCenterViewModel viewModel = requireViewModel();
+ viewModel.navigateToSafetyCenter(
+ context, NavigationSource.QUICK_SETTINGS_TILE);
+ viewModel.getInteractionLogger().record(Action.REVIEW_SETTINGS_CLICKED);
+ });
+
+ updateButtonState(statusCardView);
+ }
+
+ private void updateButtonState(StatusCardView statusCardView) {
+ if (mStatus == null) return; // Shouldn't happen in practice but we do it for null safety.
+ statusCardView.showButtons(mStatus);
+ }
+
+ private void configureSafetyProtectionView(StatusCardView statusCardView, Context context) {
+ View safetyProtectionSectionView =
+ statusCardView.findViewById(R.id.safety_protection_section_view);
if (KotlinUtils.INSTANCE.shouldShowSafetyProtectionResources(context)) {
// Hide the Safety Protection branding if there are any issue cards
safetyProtectionSectionView.setVisibility(
mStatus.hasIssues() ? View.GONE : View.VISIBLE);
}
if (safetyProtectionSectionView.getVisibility() == View.GONE) {
- holder.itemView.setPaddingRelative(
- holder.itemView.getPaddingStart(),
- holder.itemView.getPaddingTop(),
- holder.itemView.getPaddingEnd(),
+ statusCardView.setPaddingRelative(
+ statusCardView.getPaddingStart(),
+ statusCardView.getPaddingTop(),
+ statusCardView.getPaddingEnd(),
/* bottom= */ getContext()
.getResources()
.getDimensionPixelSize(R.dimen.sc_card_margin_bottom));
} else {
- holder.itemView.setPaddingRelative(
- holder.itemView.getPaddingStart(),
- holder.itemView.getPaddingTop(),
- holder.itemView.getPaddingEnd(),
+ statusCardView.setPaddingRelative(
+ statusCardView.getPaddingStart(),
+ statusCardView.getPaddingTop(),
+ statusCardView.getPaddingEnd(),
/* bottom= */ 0);
}
}
@@ -155,14 +154,13 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
runTextAnimationIfNeeded(title, summary);
}
- private void updateStatusIcon(ImageView statusImage, View rescanButton) {
+ private void updateStatusIcon(StatusCardView statusCardView) {
int severityLevel = mStatus.getSeverityLevel();
boolean isRefreshing = mStatus.isRefreshInProgress();
handleAnimationSequencerAction(
mSequencer.onUpdateReceived(isRefreshing, severityLevel),
- statusImage,
- rescanButton,
+ statusCardView,
/* scanningAnimation= */ null);
}
@@ -191,8 +189,9 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
}
}
- private void startScanningAnimation(ImageView statusImage, View rescanButton) {
+ private void startScanningAnimation(StatusCardView statusCardView) {
mSequencer.onStartScanningAnimationStart();
+ ImageView statusImage = statusCardView.getStatusImageView();
statusImage.setImageResource(
StatusAnimationResolver.getScanningStartAnimation(
mSequencer.getCurrentlyVisibleSeverityLevel()));
@@ -203,15 +202,16 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
public void onAnimationEnd(Drawable drawable) {
handleAnimationSequencerAction(
mSequencer.onStartScanningAnimationEnd(),
- statusImage,
- rescanButton,
+ statusCardView,
/* scanningAnimation= */ null);
}
});
animation.start();
}
- private void continueScanningAnimation(ImageView statusImage, View rescanButton) {
+ private void continueScanningAnimation(StatusCardView statusCardView) {
+ ImageView statusImage = statusCardView.getStatusImageView();
+
// clear previous scan animation in case we need to continue with different severity level
Drawable statusDrawable = statusImage.getDrawable();
if (statusDrawable instanceof AnimatedVectorDrawable) {
@@ -229,25 +229,25 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
handleAnimationSequencerAction(
mSequencer.onContinueScanningAnimationEnd(
mStatus.isRefreshInProgress(), mStatus.getSeverityLevel()),
- statusImage,
- rescanButton,
+ statusCardView,
scanningAnim);
}
});
scanningAnim.start();
}
- private void endScanningAnimation(ImageView statusImage, View rescanButton) {
+ private void endScanningAnimation(StatusCardView statusCardView) {
+ ImageView statusImage = statusCardView.getStatusImageView();
Drawable statusDrawable = statusImage.getDrawable();
int finishingSeverityLevel = mStatus.getSeverityLevel();
if (!(statusDrawable instanceof AnimatedVectorDrawable)) {
- finishScanAnimation(statusImage, rescanButton, finishingSeverityLevel);
+ finishScanAnimation(statusCardView, finishingSeverityLevel);
return;
}
AnimatedVectorDrawable animatedStatusDrawable = (AnimatedVectorDrawable) statusDrawable;
if (!animatedStatusDrawable.isRunning()) {
- finishScanAnimation(statusImage, rescanButton, finishingSeverityLevel);
+ finishScanAnimation(statusCardView, finishingSeverityLevel);
return;
}
@@ -267,8 +267,7 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
- finishScanAnimation(
- statusImage, rescanButton, finishingSeverityLevel);
+ finishScanAnimation(statusCardView, finishingSeverityLevel);
}
});
animatedDrawable.start();
@@ -276,18 +275,16 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
});
}
- private void finishScanAnimation(
- ImageView statusImage, View rescanButton, int finishedSeverityLevel) {
- setRescanButtonState(rescanButton);
+ private void finishScanAnimation(StatusCardView statusCardView, int finishedSeverityLevel) {
+ updateButtonState(statusCardView);
handleAnimationSequencerAction(
mSequencer.onFinishScanAnimationEnd(
mStatus.isRefreshInProgress(), finishedSeverityLevel),
- statusImage,
- rescanButton,
+ statusCardView,
/* scanningAnimation= */ null);
}
- private void startIconChangeAnimation(ImageView statusImage, View rescanButton) {
+ private void startIconChangeAnimation(StatusCardView statusCardView) {
int finalSeverityLevel = mStatus.getSeverityLevel();
int changeAnimationResId =
StatusAnimationResolver.getStatusChangeAnimation(
@@ -296,14 +293,14 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
handleAnimationSequencerAction(
mSequencer.onCouldNotStartIconChangeAnimation(
mStatus.isRefreshInProgress(), finalSeverityLevel),
- statusImage,
- rescanButton,
+ statusCardView,
/* scanningAnimation= */ null);
return;
}
mSequencer.onIconChangeAnimationStart();
- statusImage.setImageResource(changeAnimationResId);
- AnimatedVectorDrawable animation = (AnimatedVectorDrawable) statusImage.getDrawable();
+ statusCardView.getStatusImageView().setImageResource(changeAnimationResId);
+ AnimatedVectorDrawable animation =
+ (AnimatedVectorDrawable) statusCardView.getStatusImageView().getDrawable();
animation.clearAnimationCallbacks();
animation.registerAnimationCallback(
new Animatable2.AnimationCallback() {
@@ -312,8 +309,7 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
handleAnimationSequencerAction(
mSequencer.onIconChangeAnimationEnd(
mStatus.isRefreshInProgress(), finalSeverityLevel),
- statusImage,
- rescanButton,
+ statusCardView,
/* scanningAnimation= */ null);
}
});
@@ -322,62 +318,47 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
private void handleAnimationSequencerAction(
@Nullable SafetyStatusAnimationSequencer.Action action,
- ImageView statusImage,
- View rescanButton,
+ StatusCardView statusCardView,
@Nullable AnimatedVectorDrawable scanningAnimation) {
if (action == null) {
return;
}
switch (action) {
case START_SCANNING_ANIMATION:
- startScanningAnimation(statusImage, rescanButton);
+ startScanningAnimation(statusCardView);
break;
case CONTINUE_SCANNING_ANIMATION:
if (scanningAnimation != null) {
scanningAnimation.start();
} else {
- continueScanningAnimation(statusImage, rescanButton);
+ continueScanningAnimation(statusCardView);
}
break;
case RESET_SCANNING_ANIMATION:
- continueScanningAnimation(statusImage, rescanButton);
+ continueScanningAnimation(statusCardView);
break;
case FINISH_SCANNING_ANIMATION:
- endScanningAnimation(statusImage, rescanButton);
+ endScanningAnimation(statusCardView);
break;
case START_ICON_CHANGE_ANIMATION:
- startIconChangeAnimation(statusImage, rescanButton);
+ startIconChangeAnimation(statusCardView);
break;
case CHANGE_ICON_WITHOUT_ANIMATION:
- setSettledStatus(statusImage);
+ setSettledStatus(statusCardView);
break;
}
}
- private void setSettledStatus(ImageView statusImage) {
- Drawable statusDrawable = statusImage.getDrawable();
+ private void setSettledStatus(StatusCardView statusCardView) {
+ Drawable statusDrawable = statusCardView.getStatusImageView().getDrawable();
if (statusDrawable instanceof AnimatedVectorDrawable) {
((AnimatedVectorDrawable) statusDrawable).clearAnimationCallbacks();
}
- statusImage.setImageResource(
- StatusUiData.Companion.getStatusImageResId(
- mSequencer.getCurrentlyVisibleSeverityLevel()));
- }
-
- /**
- * Updates UI for the rescan button depending on the pending actions state and returns the
- * correctly styled rescan button
- */
- private MaterialButton updateRescanButtonUi(
- MaterialButton rescanButton, MaterialButton pendingActionsRescanButton) {
- if (mStatus.hasPendingActions()) {
- rescanButton.setVisibility(View.GONE);
- pendingActionsRescanButton.setVisibility(View.VISIBLE);
- return pendingActionsRescanButton;
- }
- pendingActionsRescanButton.setVisibility(View.GONE);
- rescanButton.setVisibility(View.VISIBLE);
- return rescanButton;
+ statusCardView
+ .getStatusImageView()
+ .setImageResource(
+ StatusUiData.Companion.getStatusImageResId(
+ mSequencer.getCurrentlyVisibleSeverityLevel()));
}
void setData(StatusUiData statusUiData) {
@@ -393,11 +374,6 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
return Objects.requireNonNull(mViewModel);
}
- private void setRescanButtonState(View rescanButton) {
- rescanButton.setVisibility(mStatus.shouldShowRescanButton() ? View.VISIBLE : View.GONE);
- rescanButton.setEnabled(!mStatus.isRefreshInProgress());
- }
-
// Calling notifyChanged while recyclerview is scrolling or computing layout will result in an
// IllegalStateException. Post to handler to wait for UI to settle.
private void safeNotifyChanged() {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt
index d83abbe12..741745c19 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt
@@ -4,6 +4,8 @@ import android.content.Context
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterStatus
+import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK
+import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN
import android.util.Log
import androidx.annotation.RequiresApi
import com.android.permissioncontroller.R
@@ -28,8 +30,8 @@ data class StatusUiData(
private val TAG: String = StatusUiData::class.java.simpleName
fun getStatusImageResId(severityLevel: Int) =
when (severityLevel) {
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN,
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK -> R.drawable.safety_status_info
+ OVERALL_SEVERITY_LEVEL_UNKNOWN,
+ OVERALL_SEVERITY_LEVEL_OK -> R.drawable.safety_status_info
SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION ->
R.drawable.safety_status_recommendation
SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING ->
@@ -61,7 +63,8 @@ data class StatusUiData(
return context.getString(
R.string.safety_status_preference_title_and_summary_content_description,
title,
- getSummary(context))
+ getSummary(context)
+ )
}
val isRefreshInProgress: Boolean
@@ -76,9 +79,23 @@ data class StatusUiData(
return !hasIssues &&
!hasPendingActions &&
when (severityLevel) {
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK,
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN -> true
+ OVERALL_SEVERITY_LEVEL_OK,
+ OVERALL_SEVERITY_LEVEL_UNKNOWN -> true
else -> false
}
}
+
+ enum class ButtonToShow {
+ RESCAN,
+ REVIEW_SETTINGS
+ }
+ val buttonToShow: ButtonToShow?
+ get() =
+ when {
+ hasIssues -> null
+ hasPendingActions -> ButtonToShow.REVIEW_SETTINGS
+ severityLevel == OVERALL_SEVERITY_LEVEL_OK ||
+ severityLevel == OVERALL_SEVERITY_LEVEL_UNKNOWN -> ButtonToShow.RESCAN
+ else -> null
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt
new file mode 100644
index 000000000..eef9a45b6
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 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.permissioncontroller.safetycenter.ui.view
+
+import android.content.Context
+import android.os.Build
+import android.util.AttributeSet
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.RequiresApi
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.widget.SafetyProtectionSectionView
+import com.android.permissioncontroller.safetycenter.ui.model.StatusUiData
+import com.google.android.material.button.MaterialButton
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+internal class StatusCardView
+@JvmOverloads
+constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+ defStyleRes: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) {
+
+ init {
+ inflate(context, R.layout.view_status_card, this)
+ }
+
+ val statusImageView: ImageView by lazy { findViewById(R.id.status_image) }
+ val titleAndSummaryContainerView: LinearLayout by lazy {
+ findViewById(R.id.status_title_and_summary)
+ }
+ val titleView: TextView by lazy { findViewById(R.id.status_title) }
+ val summaryView: TextView by lazy { findViewById(R.id.status_summary) }
+ val reviewSettingsButton: MaterialButton by lazy { findViewById(R.id.review_settings_button) }
+ val rescanButton: MaterialButton by lazy { findViewById(R.id.rescan_button) }
+ val safetyProtectionSectionView: SafetyProtectionSectionView by lazy {
+ findViewById(R.id.safety_protection_section_view)
+ }
+
+ fun showButtons(statusUiData: StatusUiData) {
+ rescanButton.isEnabled = !statusUiData.isRefreshInProgress
+
+ when (statusUiData.buttonToShow) {
+ StatusUiData.ButtonToShow.RESCAN -> {
+ rescanButton.visibility = VISIBLE
+ reviewSettingsButton.visibility = GONE
+ }
+ StatusUiData.ButtonToShow.REVIEW_SETTINGS -> {
+ rescanButton.visibility = GONE
+ reviewSettingsButton.visibility = VISIBLE
+ }
+ null -> {
+ rescanButton.visibility = GONE
+ reviewSettingsButton.visibility = GONE
+ }
+ }
+ }
+}