blob: 810dc46ad814955e42d7b4cf8b1d62f2c0a052b2 [file] [log] [blame]
/*
* Copyright (C) 2022 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.permission.ui.handheld.v33;
import static android.Manifest.permission_group.CAMERA;
import static android.Manifest.permission_group.LOCATION;
import static android.Manifest.permission_group.MICROPHONE;
import static android.os.Build.VERSION_CODES.TIRAMISU;
import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.permission.PermissionGroupUsage;
import android.permission.PermissionManager;
import android.transition.AutoTransition;
import android.transition.TransitionManager;
import android.util.ArrayMap;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.view.ViewCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.ui.model.v33.SafetyCenterQsViewModel;
import com.android.permissioncontroller.permission.ui.model.v33.SafetyCenterQsViewModelFactory;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.permissioncontroller.safetycenter.ui.Action;
import com.android.permissioncontroller.safetycenter.ui.NavigationSource;
import com.android.permissioncontroller.safetycenter.ui.SafetyCenterDashboardFragment;
import com.android.permissioncontroller.safetycenter.ui.SafetyCenterTouchTarget;
import com.android.permissioncontroller.safetycenter.ui.Sensor;
import com.android.permissioncontroller.safetycenter.ui.model.LiveSafetyCenterViewModelFactory;
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterViewModel;
import com.google.android.material.button.MaterialButton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* The Quick Settings fragment for the safety center. Displays information to the user about the
* current safety and privacy status of their device, including showing mic/camera usage, and having
* mic/camera/location toggles.
*/
@RequiresApi(TIRAMISU)
public class SafetyCenterQsFragment extends Fragment {
private static final ArrayMap<String, Integer> sToggleButtons = new ArrayMap<>();
private Context mContext;
private long mSessionId;
private List<PermissionGroupUsage> mPermGroupUsages;
private SafetyCenterQsViewModel mViewModel;
private View mRootView;
static {
sToggleButtons.put(CAMERA, R.id.camera_toggle);
sToggleButtons.put(MICROPHONE, R.id.mic_toggle);
sToggleButtons.put(LOCATION, R.id.location_toggle);
}
private SafetyCenterViewModel mSafetyCenterViewModel;
/**
* Create instance of SafetyCenterDashboardFragment with the arguments set
*
* @param sessionId The current session Id
* @param usages ArrayList of PermissionGroupUsage
* @return SafetyCenterQsFragment with the arguments set
*/
public static SafetyCenterQsFragment newInstance(
long sessionId, ArrayList<PermissionGroupUsage> usages) {
Bundle args = new Bundle();
args.putLong(EXTRA_SESSION_ID, sessionId);
args.putParcelableArrayList(PermissionManager.EXTRA_PERMISSION_USAGES, usages);
SafetyCenterQsFragment frag = new SafetyCenterQsFragment();
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSessionId = INVALID_SESSION_ID;
if (getArguments() != null) {
mSessionId = getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID);
}
mContext = getContext();
mPermGroupUsages =
getArguments().getParcelableArrayList(PermissionManager.EXTRA_PERMISSION_USAGES);
if (mPermGroupUsages == null) {
mPermGroupUsages = new ArrayList<>();
}
getActivity().setTheme(R.style.Theme_SafetyCenterQs);
SafetyCenterQsViewModelFactory factory =
new SafetyCenterQsViewModelFactory(
getActivity().getApplication(), mSessionId, mPermGroupUsages);
mViewModel =
new ViewModelProvider(requireActivity(), factory)
.get(SafetyCenterQsViewModel.class);
mViewModel
.getSensorPrivacyLiveData()
.observe(this, (v) -> setSensorToggleState(v, getView()));
// LightAppPermGroupLiveDatas are kept track of in the view model,
// we need to start observing them here
if (!mPermGroupUsages.isEmpty()) {
mViewModel.getPermDataLoadedLiveData().observe(this, this::onPermissionGroupsLoaded);
}
}
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.safety_center_qs, container, false);
mRootView = root;
if (mPermGroupUsages.isEmpty()) {
mRootView.setVisibility(View.VISIBLE);
} else {
mRootView.setVisibility(View.GONE);
}
root.setBackgroundColor(android.R.color.background_dark);
View closeButton = root.findViewById(R.id.close_button);
closeButton.setOnClickListener((v) -> requireActivity().finish());
SafetyCenterTouchTarget.configureSize(
closeButton, R.dimen.sc_icon_button_touch_target_size);
mSafetyCenterViewModel =
new ViewModelProvider(
requireActivity(),
new LiveSafetyCenterViewModelFactory(
requireActivity().getApplication()))
.get(SafetyCenterViewModel.class);
View securitySettings = root.findViewById(R.id.security_settings_button);
securitySettings.setOnClickListener(
(v) ->
mSafetyCenterViewModel.navigateToSafetyCenter(
mContext, NavigationSource.QUICK_SETTINGS_TILE));
TextView securitySettingsText = securitySettings.findViewById(R.id.toggle_sensor_name);
securitySettingsText.setText(R.string.settings);
securitySettingsText.setSelected(true);
securitySettings.findViewById(R.id.toggle_sensor_status).setVisibility(View.GONE);
ImageView securitySettingsIcon = securitySettings.findViewById(R.id.toggle_sensor_icon);
securitySettingsIcon.setImageDrawable(
Utils.applyTint(
mContext,
mContext.getDrawable(R.drawable.ic_safety_center_shield),
android.R.attr.textColorPrimaryInverse));
securitySettings.findViewById(R.id.arrow_icon).setVisibility(View.VISIBLE);
((ImageView) securitySettings.findViewById(R.id.arrow_icon))
.setImageDrawable(
Utils.applyTint(
mContext,
mContext.getDrawable(R.drawable.ic_chevron_right),
android.R.attr.textColorSecondaryInverse));
ViewCompat.replaceAccessibilityAction(
securitySettings,
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
mContext.getString(R.string.safety_center_qs_open_action),
null);
getChildFragmentManager()
.beginTransaction()
.add(
R.id.safety_center_prefs,
SafetyCenterDashboardFragment.newInstance(
mSessionId, /* isQuickSettingsFragment= */ true))
.commitNow();
return root;
}
private void onPermissionGroupsLoaded(boolean initialized) {
if (initialized) {
mRootView.setVisibility(View.VISIBLE);
addPermissionUsageInformation(mRootView);
}
}
private void addPermissionUsageInformation(View rootView) {
if (rootView == null) {
return;
}
View permissionSectionTitleView = rootView.findViewById(R.id.permission_section_title);
if (mPermGroupUsages == null || mPermGroupUsages.isEmpty()) {
permissionSectionTitleView.setVisibility(View.GONE);
return;
}
permissionSectionTitleView.setVisibility(View.VISIBLE);
LinearLayout usageLayout = rootView.findViewById(R.id.permission_usage);
Collections.sort(
mPermGroupUsages,
(pguA, pguB) ->
getAppLabel(pguA).toString().compareTo(getAppLabel(pguB).toString()));
for (PermissionGroupUsage usage : mPermGroupUsages) {
View cardView = View.inflate(mContext, R.layout.indicator_card, usageLayout);
cardView.setId(View.generateViewId());
ConstraintLayout parentIndicatorLayout = cardView.findViewById(R.id.indicator_layout);
parentIndicatorLayout.setId(View.generateViewId());
ImageView expandView = parentIndicatorLayout.findViewById(R.id.expand_view);
// Update UI for the parent indicator card
updateIndicatorParentUi(
parentIndicatorLayout,
usage.getPermissionGroupName(),
generateUsageLabel(usage),
usage.isActive());
// If sensor usage is due to an active phone call, don't allow any actions
if (usage.isPhoneCall()) {
expandView.setVisibility(View.GONE);
continue;
}
ConstraintLayout expandedLayout = cardView.findViewById(R.id.expanded_layout);
expandedLayout.setId(View.generateViewId());
// Handle redraw on orientation changes if permission has been revoked
if (mViewModel.getRevokedUsages().contains(usage)) {
disableIndicatorCardUi(parentIndicatorLayout, expandView);
continue;
}
setIndicatorExpansionBehavior(parentIndicatorLayout, expandedLayout, expandView);
ViewCompat.replaceAccessibilityAction(
parentIndicatorLayout,
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
mContext.getString(R.string.safety_center_qs_expand_action),
null);
// Configure the indicator action buttons
configureIndicatorActionButtons(
usage, parentIndicatorLayout, expandedLayout, expandView);
}
}
private void configureIndicatorActionButtons(
PermissionGroupUsage usage,
ConstraintLayout parentIndicatorLayout,
ConstraintLayout expandedLayout,
ImageView expandView) {
configurePrimaryActionButton(usage, parentIndicatorLayout, expandedLayout, expandView);
configureSeeUsageButton(usage, expandedLayout);
}
private void configurePrimaryActionButton(
PermissionGroupUsage usage,
ConstraintLayout parentIndicatorLayout,
ConstraintLayout expandedLayout,
ImageView expandView) {
boolean shouldAllowRevoke = mViewModel.shouldAllowRevoke(usage);
Intent manageServiceIntent = null;
if (isSubAttributionUsage(usage.getAttributionLabel())) {
manageServiceIntent = mViewModel.getStartViewPermissionUsageIntent(mContext, usage);
}
int primaryActionButtonLabel =
getPrimaryActionButtonLabel(
manageServiceIntent != null,
shouldAllowRevoke,
usage.getPermissionGroupName());
MaterialButton primaryActionButton = expandedLayout.findViewById(R.id.primary_button);
primaryActionButton.setText(primaryActionButtonLabel);
primaryActionButton.setStrokeColorResource(
Utils.getColorResId(mContext, android.R.attr.colorAccent));
if (shouldAllowRevoke && manageServiceIntent == null) {
primaryActionButton.setOnClickListener(
l -> {
parentIndicatorLayout.callOnClick();
disableIndicatorCardUi(parentIndicatorLayout, expandView);
revokePermission(usage);
mSafetyCenterViewModel
.getInteractionLogger()
.recordForSensor(
Action.SENSOR_PERMISSION_REVOKE_CLICKED,
Sensor.fromPermissionGroupUsage(usage));
});
} else {
setPrimaryActionClickListener(primaryActionButton, usage, manageServiceIntent);
}
}
private void configureSeeUsageButton(
PermissionGroupUsage usage, ConstraintLayout expandedLayout) {
MaterialButton seeUsageButton = expandedLayout.findViewById(R.id.secondary_button);
seeUsageButton.setText(getSeeUsageText(usage.getPermissionGroupName()));
seeUsageButton.setStrokeColorResource(
Utils.getColorResId(mContext, android.R.attr.colorAccent));
seeUsageButton.setOnClickListener(
l -> {
mViewModel.navigateToSeeUsage(this, usage.getPermissionGroupName());
mSafetyCenterViewModel
.getInteractionLogger()
.recordForSensor(
Action.SENSOR_PERMISSION_SEE_USAGES_CLICKED,
Sensor.fromPermissionGroupUsage(usage));
});
}
private void setPrimaryActionClickListener(
Button primaryActionButton, PermissionGroupUsage usage, Intent manageServiceIntent) {
if (manageServiceIntent != null) {
primaryActionButton.setOnClickListener(
l -> {
mViewModel.navigateToManageService(this, manageServiceIntent);
mSafetyCenterViewModel
.getInteractionLogger()
.recordForSensor(
// Unfortunate name, but this is used for all primary
// CTAs on the permission usage cards.
Action.SENSOR_PERMISSION_REVOKE_CLICKED,
Sensor.fromPermissionGroupUsage(usage));
});
} else {
primaryActionButton.setOnClickListener(
l -> {
mViewModel.navigateToManageAppPermissions(this, usage);
mSafetyCenterViewModel
.getInteractionLogger()
.recordForSensor(
Action.SENSOR_PERMISSION_REVOKE_CLICKED,
Sensor.fromPermissionGroupUsage(usage));
});
}
}
private int getPrimaryActionButtonLabel(
boolean canHandleIntent, boolean shouldAllowRevoke, String permissionGroupName) {
if (canHandleIntent) {
return R.string.manage_service_qs;
}
if (!shouldAllowRevoke) {
return R.string.manage_permissions_qs;
}
return getRemovePermissionText(permissionGroupName);
}
private boolean isSubAttributionUsage(@Nullable CharSequence attributionLabel) {
if (attributionLabel == null || attributionLabel.length() == 0) {
return false;
}
return true;
}
private void revokePermission(PermissionGroupUsage usage) {
mViewModel.revokePermission(usage);
}
private void disableIndicatorCardUi(
ConstraintLayout parentIndicatorLayout, ImageView expandView) {
// Disable the parent indicator and the expand view
parentIndicatorLayout.setEnabled(false);
expandView.setEnabled(false);
expandView.setVisibility(View.GONE);
// Construct new icon for revoked permission
ImageView iconView = parentIndicatorLayout.findViewById(R.id.indicator_icon);
Drawable background = mContext.getDrawable(R.drawable.indicator_background_circle).mutate();
background.setTint(mContext.getColor(R.color.sc_surface_variant_dark));
Drawable icon = mContext.getDrawable(R.drawable.ic_check);
Utils.applyTint(mContext, icon, android.R.attr.textColorPrimary);
int bgSize = (int) getResources().getDimension(R.dimen.ongoing_appops_dialog_circle_size);
int iconSize = (int) getResources().getDimension(R.dimen.ongoing_appops_dialog_icon_size);
iconView.setImageDrawable(constructIcon(icon, background, bgSize, iconSize));
// Set label to show on permission revoke
TextView labelView = parentIndicatorLayout.findViewById(R.id.indicator_label);
labelView.setText(R.string.permissions_removed_qs);
labelView.setContentDescription(mContext.getString(R.string.permissions_removed_qs));
}
private void setIndicatorExpansionBehavior(
ConstraintLayout parentIndicatorLayout,
ConstraintLayout expandedLayout,
ImageView expandView) {
parentIndicatorLayout.setOnClickListener(
createExpansionListener(expandedLayout, expandView));
}
private View.OnClickListener createExpansionListener(
ConstraintLayout expandedLayout, ImageView expandView) {
AutoTransition transition = new AutoTransition();
// Get the entire fragment as a viewgroup in order to animate it nicely in case of
// expand/collapse
ViewGroup indicatorCardViewGroup = (ViewGroup) mRootView;
return v -> {
if (expandedLayout.getVisibility() == View.VISIBLE) {
// Enable -> Press -> Hide the expanded card for a continuous ripple effect
expandedLayout.setEnabled(true);
pressButton(expandedLayout);
expandedLayout.setVisibility(View.GONE);
TransitionManager.beginDelayedTransition(indicatorCardViewGroup, transition);
expandView.setImageDrawable(
mContext.getDrawable(R.drawable.ic_safety_group_expand));
ViewCompat.replaceAccessibilityAction(
v,
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
mContext.getString(R.string.safety_center_qs_expand_action),
null);
} else {
// Show -> Press -> Disable the expanded card for a continuous ripple effect
expandedLayout.setVisibility(View.VISIBLE);
pressButton(expandedLayout);
expandedLayout.setEnabled(false);
TransitionManager.beginDelayedTransition(indicatorCardViewGroup, transition);
expandView.setImageDrawable(
mContext.getDrawable(R.drawable.ic_safety_group_collapse));
ViewCompat.replaceAccessibilityAction(
v,
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
mContext.getString(R.string.safety_center_qs_collapse_action),
null);
}
};
}
/**
* To get the expanded card to ripple at the same time as the parent card we must simulate a
* user press on the expanded card
*/
private void pressButton(View buttonToBePressed) {
buttonToBePressed.setPressed(true);
buttonToBePressed.setPressed(false);
buttonToBePressed.performClick();
}
private String generateUsageLabel(PermissionGroupUsage usage) {
if (usage.isPhoneCall() && usage.isActive()) {
return mContext.getString(R.string.active_call_usage_qs);
} else if (usage.isPhoneCall()) {
return mContext.getString(R.string.recent_call_usage_qs);
}
return generateAttributionUsageLabel(usage);
}
private String generateAttributionUsageLabel(PermissionGroupUsage usage) {
CharSequence appLabel = getAppLabel(usage);
final int usageResId =
usage.isActive() ? R.string.active_app_usage_qs : R.string.recent_app_usage_qs;
final int singleUsageResId =
usage.isActive() ? R.string.active_app_usage_1_qs : R.string.recent_app_usage_1_qs;
final int doubleUsageResId =
usage.isActive() ? R.string.active_app_usage_2_qs : R.string.recent_app_usage_2_qs;
CharSequence attributionLabel = usage.getAttributionLabel();
CharSequence proxyLabel = usage.getProxyLabel();
if (attributionLabel == null && proxyLabel == null) {
return mContext.getString(usageResId, appLabel);
} else if (attributionLabel != null && proxyLabel != null) {
return mContext.getString(doubleUsageResId, appLabel, attributionLabel, proxyLabel);
} else {
return mContext.getString(
singleUsageResId,
appLabel,
attributionLabel == null ? proxyLabel : attributionLabel);
}
}
private CharSequence getAppLabel(PermissionGroupUsage usage) {
return KotlinUtils.INSTANCE.getPackageLabel(
getActivity().getApplication(),
usage.getPackageName(),
UserHandle.getUserHandleForUid(usage.getUid()));
}
private void updateIndicatorParentUi(
ConstraintLayout indicatorParentLayout,
String permGroupName,
String usageText,
boolean isActiveUsage) {
CharSequence permGroupLabel = getPermGroupLabel(permGroupName);
ImageView iconView = indicatorParentLayout.findViewById(R.id.indicator_icon);
Drawable background = mContext.getDrawable(R.drawable.indicator_background_circle);
int indicatorColor =
Utils.getColorResId(
mContext,
isActiveUsage
? android.R.attr.textColorPrimaryInverse
: android.R.attr.textColorPrimary);
Drawable indicatorIcon =
KotlinUtils.INSTANCE.getPermGroupIcon(
mContext, permGroupName, mContext.getColor(indicatorColor));
if (isActiveUsage) {
Utils.applyTint(mContext, background, android.R.attr.colorAccent);
} else {
background.setTint(mContext.getColor(R.color.sc_surface_variant_dark));
}
int bgSize = (int) getResources().getDimension(R.dimen.ongoing_appops_dialog_circle_size);
int iconSize = (int) getResources().getDimension(R.dimen.ongoing_appops_dialog_icon_size);
iconView.setImageDrawable(constructIcon(indicatorIcon, background, bgSize, iconSize));
iconView.setContentDescription(permGroupLabel);
TextView titleText = indicatorParentLayout.findViewById(R.id.indicator_title);
titleText.setText(permGroupLabel);
titleText.setTextColor(
mContext.getColor(Utils.getColorResId(mContext, android.R.attr.textColorPrimary)));
titleText.setContentDescription(permGroupLabel);
TextView labelText = indicatorParentLayout.findViewById(R.id.indicator_label);
labelText.setText(usageText);
labelText.setContentDescription(usageText);
ImageView expandView = indicatorParentLayout.findViewById(R.id.expand_view);
expandView.setImageDrawable(mContext.getDrawable(R.drawable.ic_safety_group_expand));
}
private Drawable constructIcon(Drawable icon, Drawable background, int bgSize, int iconSize) {
LayerDrawable layered = new LayerDrawable(new Drawable[] {background, icon});
final int bgLayerIndex = 0;
final int iconLayerIndex = 1;
layered.setLayerSize(bgLayerIndex, bgSize, bgSize);
layered.setLayerSize(iconLayerIndex, iconSize, iconSize);
layered.setLayerGravity(iconLayerIndex, Gravity.CENTER);
return layered;
}
private void setSensorToggleState(Map<String, Boolean> sensorState, View rootView) {
if (rootView == null) {
if (getView() == null) {
return;
}
rootView = getView();
if (rootView == null) {
return;
}
}
if (sensorState == null) {
sensorState = new ArrayMap<>();
}
for (int i = 0; i < sToggleButtons.size(); i++) {
View toggle = rootView.findViewById(sToggleButtons.valueAt(i));
String groupName = sToggleButtons.keyAt(i);
if (!toggle.hasOnClickListeners()) {
toggle.setOnClickListener(
(v) -> {
mViewModel.toggleSensor(groupName);
mSafetyCenterViewModel
.getInteractionLogger()
.recordForSensor(
Action.PRIVACY_CONTROL_TOGGLE_CLICKED,
Sensor.fromPermissionGroupName(groupName));
});
}
TextView groupLabel = toggle.findViewById(R.id.toggle_sensor_name);
groupLabel.setText(getPermGroupLabel(groupName));
// Set the text as selected to get marquee to work
groupLabel.setSelected(true);
TextView blockedStatus = toggle.findViewById(R.id.toggle_sensor_status);
// Set the text as selected to get marquee to work
blockedStatus.setSelected(true);
ImageView iconView = toggle.findViewById(R.id.toggle_sensor_icon);
boolean sensorEnabled =
!sensorState.containsKey(groupName) || sensorState.get(groupName);
Drawable icon;
int colorPrimary = getTextColor(true, sensorEnabled);
int colorSecondary = getTextColor(false, sensorEnabled);
if (sensorEnabled) {
toggle.setBackgroundResource(R.drawable.safety_center_sensor_toggle_enabled);
icon = KotlinUtils.INSTANCE.getPermGroupIcon(mContext, groupName, colorPrimary);
} else {
toggle.setBackgroundResource(R.drawable.safety_center_sensor_toggle_disabled);
icon = mContext.getDrawable(getBlockedIconResId(groupName));
icon.setTint(colorPrimary);
}
blockedStatus.setText(getSensorStatusTextResId(groupName, sensorEnabled));
blockedStatus.setTextColor(colorSecondary);
groupLabel.setTextColor(colorPrimary);
iconView.setImageDrawable(icon);
int contentDescriptionResId = R.string.safety_center_qs_privacy_control;
toggle.setContentDescription(
mContext.getString(
contentDescriptionResId,
groupLabel.getText(),
blockedStatus.getText()));
ViewCompat.replaceAccessibilityAction(
toggle,
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
mContext.getString(R.string.safety_center_qs_toggle_action),
null);
}
}
@ColorInt
private Integer getTextColor(boolean primary, boolean inverse) {
int primaryAttribute =
inverse ? android.R.attr.textColorPrimaryInverse : android.R.attr.textColorPrimary;
int secondaryAttribute =
inverse
? android.R.attr.textColorSecondaryInverse
: android.R.attr.textColorSecondary;
int attribute = primary ? primaryAttribute : secondaryAttribute;
TypedValue value = new TypedValue();
mContext.getTheme().resolveAttribute(attribute, value, true);
int colorRes = value.resourceId != 0 ? value.resourceId : value.data;
return mContext.getColor(colorRes);
}
private CharSequence getPermGroupLabel(String permissionGroup) {
switch (permissionGroup) {
case MICROPHONE:
return mContext.getString(R.string.microphone_toggle_label_qs);
case CAMERA:
return mContext.getString(R.string.camera_toggle_label_qs);
}
return KotlinUtils.INSTANCE.getPermGroupLabel(mContext, permissionGroup);
}
private static int getRemovePermissionText(String permissionGroup) {
return CAMERA.equals(permissionGroup)
? R.string.remove_camera_qs
: R.string.remove_microphone_qs;
}
private static int getSeeUsageText(String permissionGroup) {
return CAMERA.equals(permissionGroup)
? R.string.camera_usage_qs
: R.string.microphone_usage_qs;
}
private static int getBlockedIconResId(String permissionGroup) {
switch (permissionGroup) {
case MICROPHONE:
return R.drawable.ic_mic_blocked;
case CAMERA:
return R.drawable.ic_camera_blocked;
case LOCATION:
return R.drawable.ic_location_blocked;
}
return -1;
}
private static int getSensorStatusTextResId(String permissionGroup, boolean enabled) {
switch (permissionGroup) {
case LOCATION:
return enabled ? R.string.on : R.string.off;
}
return enabled ? R.string.available : R.string.blocked;
}
}