Merge "Merge Coral/Flame into AOSP master"
This commit is contained in:
@@ -26,6 +26,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
@@ -97,6 +98,7 @@ public class AccessibilitySettingsForSetupWizardActivity extends SettingsActivit
|
||||
super.onCreate(savedState);
|
||||
|
||||
tryLaunchFontSizeSettings();
|
||||
findViewById(R.id.content_parent).setFitsSystemWindows(false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
@@ -31,18 +31,17 @@ import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.internal.widget.SubtitleView;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settings.widget.ToggleSwitch;
|
||||
import com.android.settings.widget.ToggleSwitch.OnBeforeCheckedChangeListener;
|
||||
import com.android.settingslib.accessibility.AccessibilityUtils;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@@ -63,6 +62,7 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
private static final String PREF_TYPEFACE = "captioning_typeface";
|
||||
private static final String PREF_LOCALE = "captioning_locale";
|
||||
private static final String PREF_PRESET = "captioning_preset";
|
||||
private static final String PREF_SWITCH = "captioning_preference_switch";
|
||||
private static final String PREF_CUSTOM = "custom";
|
||||
|
||||
/** WebVtt specifies line height as 5.3% of the viewport height. */
|
||||
@@ -72,10 +72,9 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
private SubtitleView mPreviewText;
|
||||
private View mPreviewWindow;
|
||||
private View mPreviewViewport;
|
||||
private SwitchBar mSwitchBar;
|
||||
private ToggleSwitch mToggleSwitch;
|
||||
|
||||
// Standard options.
|
||||
private SwitchPreference mSwitch;
|
||||
private LocalePreference mLocale;
|
||||
private ListPreference mFontSize;
|
||||
private PresetPreference mPreset;
|
||||
@@ -94,6 +93,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
|
||||
private boolean mShowingCustom;
|
||||
|
||||
private final List<Preference> mPreferenceList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.ACCESSIBILITY_CAPTION_PROPERTIES;
|
||||
@@ -110,31 +111,18 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
updateAllPreferences();
|
||||
refreshShowingCustom();
|
||||
installUpdateListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
final boolean enabled = mCaptioningManager.isEnabled();
|
||||
SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
mSwitchBar = activity.getSwitchBar();
|
||||
mSwitchBar.setSwitchBarText(R.string.accessibility_caption_master_switch_title,
|
||||
R.string.accessibility_caption_master_switch_title);
|
||||
mSwitchBar.setCheckedInternal(enabled);
|
||||
mToggleSwitch = mSwitchBar.getSwitch();
|
||||
|
||||
getPreferenceScreen().setEnabled(enabled);
|
||||
|
||||
refreshPreviewText();
|
||||
|
||||
installSwitchBarToggleSwitch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
removeSwitchBarToggleSwitch();
|
||||
private void setPreferenceViewEnabled(boolean enabled) {
|
||||
for (Preference preference : mPreferenceList) {
|
||||
preference.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPreferenceViewEnabled(boolean enabled) {
|
||||
setPreferenceViewEnabled(enabled);
|
||||
mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
private void refreshPreviewText() {
|
||||
@@ -196,38 +184,10 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
protected void onInstallSwitchBarToggleSwitch() {
|
||||
mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
|
||||
@Override
|
||||
public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
|
||||
mSwitchBar.setCheckedInternal(checked);
|
||||
Settings.Secure.putInt(getActivity().getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, checked ? 1 : 0);
|
||||
getPreferenceScreen().setEnabled(checked);
|
||||
if (mPreviewText != null) {
|
||||
mPreviewText.setVisibility(checked ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void installSwitchBarToggleSwitch() {
|
||||
onInstallSwitchBarToggleSwitch();
|
||||
mSwitchBar.show();
|
||||
}
|
||||
|
||||
private void removeSwitchBarToggleSwitch() {
|
||||
mSwitchBar.hide();
|
||||
mToggleSwitch.setOnBeforeCheckedChangeListener(null);
|
||||
}
|
||||
|
||||
private void initializeAllPreferences() {
|
||||
final LayoutPreference captionPreview = findPreference(PREF_CAPTION_PREVIEW);
|
||||
|
||||
final boolean enabled = mCaptioningManager.isEnabled();
|
||||
mPreviewText = captionPreview.findViewById(R.id.preview_text);
|
||||
mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
|
||||
|
||||
mPreviewWindow = captionPreview.findViewById(R.id.preview_window);
|
||||
|
||||
@@ -236,9 +196,6 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
|
||||
-> refreshPreviewText());
|
||||
|
||||
mLocale = (LocalePreference) findPreference(PREF_LOCALE);
|
||||
mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
|
||||
|
||||
final Resources res = getResources();
|
||||
final int[] presetValues = res.getIntArray(R.array.captioning_preset_selector_values);
|
||||
final String[] presetTitles = res.getStringArray(R.array.captioning_preset_selector_titles);
|
||||
@@ -246,6 +203,17 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
mPreset.setValues(presetValues);
|
||||
mPreset.setTitles(presetTitles);
|
||||
|
||||
mSwitch = (SwitchPreference) findPreference(PREF_SWITCH);
|
||||
mLocale = (LocalePreference) findPreference(PREF_LOCALE);
|
||||
mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
|
||||
|
||||
// Initialize the preference list
|
||||
mPreferenceList.add(mLocale);
|
||||
mPreferenceList.add(mFontSize);
|
||||
mPreferenceList.add(mPreset);
|
||||
|
||||
refreshPreferenceViewEnabled(mCaptioningManager.isEnabled());
|
||||
|
||||
mCustom = (PreferenceCategory) findPreference(PREF_CUSTOM);
|
||||
mShowingCustom = true;
|
||||
|
||||
@@ -304,6 +272,7 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
mWindowOpacity.setOnValueChangedListener(this);
|
||||
mEdgeType.setOnValueChangedListener(this);
|
||||
|
||||
mSwitch.setOnPreferenceChangeListener(this);
|
||||
mTypeface.setOnPreferenceChangeListener(this);
|
||||
mFontSize.setOnPreferenceChangeListener(this);
|
||||
mLocale.setOnPreferenceChangeListener(this);
|
||||
@@ -338,6 +307,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
|
||||
final String rawLocale = mCaptioningManager.getRawLocale();
|
||||
mLocale.setValue(rawLocale == null ? "" : rawLocale);
|
||||
|
||||
mSwitch.setChecked(mCaptioningManager.isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,16 +402,22 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
|
||||
if (mTypeface == preference) {
|
||||
Settings.Secure.putString(
|
||||
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE, (String) value);
|
||||
refreshPreviewText();
|
||||
} else if (mFontSize == preference) {
|
||||
Settings.Secure.putFloat(
|
||||
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
|
||||
Float.parseFloat((String) value));
|
||||
refreshPreviewText();
|
||||
} else if (mLocale == preference) {
|
||||
Settings.Secure.putString(
|
||||
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE, (String) value);
|
||||
refreshPreviewText();
|
||||
} else if (mSwitch == preference) {
|
||||
Settings.Secure.putInt(
|
||||
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, (boolean) value ? 1 : 0);
|
||||
refreshPreferenceViewEnabled((boolean) value);
|
||||
}
|
||||
|
||||
refreshPreviewText();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
@@ -132,9 +134,10 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
|
||||
if (info.getComponentName().equals(assignedComponentName)) {
|
||||
final CharSequence assignedServiceName = info.getResolveInfo().loadLabel(
|
||||
context.getPackageManager());
|
||||
return context.getString(
|
||||
R.string.accessibility_screen_magnification_navbar_configuration_warning,
|
||||
assignedServiceName);
|
||||
final int messageId = isGestureNavigateEnabled(context)
|
||||
? R.string.accessibility_screen_magnification_gesture_navigation_warning
|
||||
: R.string.accessibility_screen_magnification_navbar_configuration_warning;
|
||||
return context.getString(messageId, assignedServiceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,6 +161,12 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
|
||||
return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
|
||||
}
|
||||
|
||||
private static boolean isGestureNavigateEnabled(Context context) {
|
||||
return context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode)
|
||||
== NAV_BAR_MODE_GESTURAL;
|
||||
}
|
||||
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
@@ -173,4 +182,4 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
|
||||
return isApplicable(context.getResources());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@@ -31,6 +31,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.applications.AppStorageSettings;
|
||||
import com.android.settings.applications.FetchPackageStorageAsyncLoader;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
@@ -48,9 +49,12 @@ public class AppStoragePreferenceController extends AppInfoPreferenceControllerB
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
final boolean isExternal =
|
||||
(mParent.getAppEntry().info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
|
||||
preference.setSummary(getStorageSummary(mLastResult, isExternal));
|
||||
final ApplicationsState.AppEntry entry = mParent.getAppEntry();
|
||||
if (entry != null && entry.info != null) {
|
||||
final boolean isExternal =
|
||||
(entry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
|
||||
preference.setSummary(getStorageSummary(mLastResult, isExternal));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -172,11 +172,11 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
|
||||
if (mUserId == UserHandle.USER_NULL) {
|
||||
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(titleResId),
|
||||
null, null, challenge);
|
||||
null, null, challenge, true /* foregroundOnly */);
|
||||
} else {
|
||||
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(titleResId),
|
||||
null, null, challenge, mUserId);
|
||||
null, null, challenge, mUserId, true /* foregroundOnly */);
|
||||
}
|
||||
if (!launchedConfirmationActivity) {
|
||||
// This shouldn't happen, as we should only end up at this step if a lock thingy is
|
||||
|
@@ -47,6 +47,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
private boolean mHasPassword;
|
||||
private boolean mBiometricUnlockDisabledByAdmin;
|
||||
private TextView mErrorText;
|
||||
protected boolean mConfirmingCredentials;
|
||||
protected boolean mNextClicked;
|
||||
|
||||
/**
|
||||
* @return true if the biometric is disabled by a device administrator
|
||||
@@ -149,10 +151,12 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
|
||||
if (!mHasPassword) {
|
||||
// No password registered, launch into enrollment wizard.
|
||||
mConfirmingCredentials = true;
|
||||
launchChooseLock();
|
||||
} else if (mToken == null) {
|
||||
// It's possible to have a token but mLaunchedConfirmLock == false, since
|
||||
// ChooseLockGeneric can pass us a token.
|
||||
mConfirmingCredentials = true;
|
||||
launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
|
||||
}
|
||||
}
|
||||
@@ -182,6 +186,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
|
||||
@Override
|
||||
protected void onNextButtonClick(View view) {
|
||||
mNextClicked = true;
|
||||
if (checkMaxEnrolled() == 0) {
|
||||
// Lock thingy is already set up, launch directly to the next page
|
||||
launchNextEnrollingActivity(mToken);
|
||||
@@ -249,12 +254,14 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
mToken = data.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
|
||||
mConfirmingCredentials = false;
|
||||
return;
|
||||
} else {
|
||||
setResult(resultCode, data);
|
||||
finish();
|
||||
}
|
||||
} else if (requestCode == CONFIRM_REQUEST) {
|
||||
mConfirmingCredentials = false;
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
|
||||
|
@@ -60,6 +60,8 @@ public class FaceEnrollAccessibilityToggle extends LinearLayout {
|
||||
}
|
||||
mSwitch = findViewById(R.id.toggle);
|
||||
mSwitch.setChecked(false);
|
||||
mSwitch.setClickable(false);
|
||||
mSwitch.setFocusable(false);
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
import static android.provider.Settings.Secure.FACE_UNLOCK_EDUCATION_INFO_DISPLAYED;
|
||||
import static android.security.KeyStore.getApplicationContext;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
@@ -50,8 +49,6 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
private static final String TAG = "FaceEducation";
|
||||
private static final int ON = 1;
|
||||
private static final int OFF = 0;
|
||||
// 8 seconds.
|
||||
private static final long FACE_ENROLL_EDUCATION_DELAY = 8000;
|
||||
|
||||
private FaceManager mFaceManager;
|
||||
private FaceEnrollAccessibilityToggle mSwitchDiversity;
|
||||
@@ -61,6 +58,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
private Handler mHandler;
|
||||
private Intent mResultIntent;
|
||||
private TextView mDescriptionText;
|
||||
private boolean mNextClicked;
|
||||
|
||||
private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
@@ -101,14 +99,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
mDescriptionText = findViewById(R.id.sud_layout_description);
|
||||
|
||||
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
|
||||
mFooterBarMixin.setSecondaryButton(
|
||||
new FooterButton.Builder(this)
|
||||
.setText(R.string.security_settings_face_enroll_enrolling_skip)
|
||||
.setListener(this::onSkipButtonClick)
|
||||
.setButtonType(FooterButton.ButtonType.SKIP)
|
||||
.setTheme(R.style.SudGlifButton_Secondary)
|
||||
.build()
|
||||
);
|
||||
|
||||
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
|
||||
mFooterBarMixin.setSecondaryButton(
|
||||
new FooterButton.Builder(this)
|
||||
.setText(R.string.skip_label)
|
||||
.setListener(this::onSkipButtonClick)
|
||||
.setButtonType(FooterButton.ButtonType.SKIP)
|
||||
.setTheme(R.style.SudGlifButton_Secondary)
|
||||
.build()
|
||||
);
|
||||
} else {
|
||||
mFooterBarMixin.setSecondaryButton(
|
||||
new FooterButton.Builder(this)
|
||||
.setText(R.string.security_settings_face_enroll_introduction_cancel)
|
||||
.setListener(this::onSkipButtonClick)
|
||||
.setButtonType(FooterButton.ButtonType.CANCEL)
|
||||
.setTheme(R.style.SudGlifButton_Secondary)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
final FooterButton footerButton = new FooterButton.Builder(this)
|
||||
.setText(R.string.security_settings_face_enroll_education_start)
|
||||
@@ -121,24 +131,15 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
final AccessibilityManager accessibilityManager = getApplicationContext().getSystemService(
|
||||
AccessibilityManager.class);
|
||||
if (accessibilityManager != null) {
|
||||
accessibilityEnabled = accessibilityManager.isEnabled();
|
||||
// Add additional check for touch exploration. This prevents other accessibility
|
||||
// features such as Live Transcribe from defaulting to the accessibility setup.
|
||||
accessibilityEnabled = accessibilityManager.isEnabled()
|
||||
&& accessibilityManager.isTouchExplorationEnabled();
|
||||
}
|
||||
mFooterBarMixin.setPrimaryButton(footerButton);
|
||||
final Context context = getApplicationContext();
|
||||
final boolean didDisplayEdu = Settings.Secure.getIntForUser(context.getContentResolver(),
|
||||
FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, OFF, mUserId) == ON;
|
||||
if (!didDisplayEdu && !accessibilityEnabled) {
|
||||
Settings.Secure.putIntForUser(context.getContentResolver(),
|
||||
FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, ON, mUserId);
|
||||
footerButton.setEnabled(false);
|
||||
mHandler.postDelayed(() -> {
|
||||
footerButton.setEnabled(true);
|
||||
}, FACE_ENROLL_EDUCATION_DELAY);
|
||||
}
|
||||
|
||||
final Button accessibilityButton = findViewById(R.id.accessibility_button);
|
||||
accessibilityButton.setOnClickListener(view -> {
|
||||
footerButton.setEnabled(true);
|
||||
mSwitchDiversity.setChecked(true);
|
||||
accessibilityButton.setVisibility(View.GONE);
|
||||
mSwitchDiversity.setVisibility(View.VISIBLE);
|
||||
@@ -146,6 +147,9 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
|
||||
mSwitchDiversity = findViewById(R.id.toggle_diversity);
|
||||
mSwitchDiversity.setListener(mSwitchDiversityListener);
|
||||
mSwitchDiversity.setOnClickListener(v -> {
|
||||
mSwitchDiversity.getSwitch().toggle();
|
||||
});
|
||||
|
||||
if (accessibilityEnabled) {
|
||||
accessibilityButton.callOnClick();
|
||||
@@ -157,6 +161,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
super.onResume();
|
||||
mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
|
||||
mSwitchDiversity.isChecked());
|
||||
|
||||
// If the user goes back after enrollment, we should send them back to the intro page
|
||||
// if they've met the max limit.
|
||||
final int max = getResources().getInteger(
|
||||
com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
|
||||
final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
|
||||
if (numEnrolledFaces >= max) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (!isChangingConfigurations() && !WizardManagerHelper.isAnySetupWizard(getIntent())
|
||||
&& !mNextClicked) {
|
||||
setResult(RESULT_SKIP);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,6 +192,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
}
|
||||
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
|
||||
final String flattenedString = getString(R.string.config_face_enroll);
|
||||
if (!TextUtils.isEmpty(flattenedString)) {
|
||||
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
|
||||
@@ -175,11 +200,12 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
||||
} else {
|
||||
intent.setClass(this, FaceEnrollEnrolling.class);
|
||||
}
|
||||
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
|
||||
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
|
||||
if (mResultIntent != null) {
|
||||
intent.putExtras(mResultIntent);
|
||||
}
|
||||
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
|
||||
mNextClicked = true;
|
||||
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
|
||||
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
|
||||
}
|
||||
|
||||
|
@@ -32,6 +32,7 @@ import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar;
|
||||
import com.android.settings.biometrics.BiometricErrorDialog;
|
||||
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
|
||||
import com.google.android.setupcompat.template.FooterBarMixin;
|
||||
import com.google.android.setupcompat.template.FooterButton;
|
||||
@@ -184,6 +185,10 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
|
||||
// TODO: Have this match any animations that UX comes up with
|
||||
if (remaining == 0) {
|
||||
// Force the reload of the FaceEnroll slice in case a user has enrolled,
|
||||
// this will cause the slice to no longer appear.
|
||||
getApplicationContext().getContentResolver().notifyChange(
|
||||
CustomSliceRegistry.FACE_ENROLL_SLICE_URI, null);
|
||||
launchFinish(mToken);
|
||||
}
|
||||
}
|
||||
|
@@ -77,6 +77,16 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (!isChangingConfigurations() && !mConfirmingCredentials && !mNextClicked
|
||||
&& !WizardManagerHelper.isAnySetupWizard(getIntent())) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabledByAdmin() {
|
||||
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
|
||||
|
@@ -52,7 +52,7 @@ public class FaceEnrollSidecar extends BiometricEnrollSidecar {
|
||||
mFaceManager.setActiveUser(mUserId);
|
||||
}
|
||||
|
||||
mFaceManager.enroll(mToken, mEnrollmentCancel,
|
||||
mFaceManager.enroll(mUserId, mToken, mEnrollmentCancel,
|
||||
mEnrollmentCallback, mDisabledFeatures);
|
||||
}
|
||||
|
||||
|
@@ -19,14 +19,30 @@ package com.android.settings.biometrics.face;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceController {
|
||||
|
||||
public static final String KEY_FACE_SETTINGS = "face_settings_profile";
|
||||
private static final String KEY_FACE_SETTINGS = "face_settings_profile";
|
||||
|
||||
public FaceProfileStatusPreferenceController(Context context) {
|
||||
super(context, KEY_FACE_SETTINGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
// Check if Face for Profile is available.
|
||||
final int isAvailable = super.getAvailabilityStatus();
|
||||
if (isAvailable != AVAILABLE) {
|
||||
return isAvailable;
|
||||
}
|
||||
// Make the profile unsearchable so the user preference controller gets highlighted
|
||||
// when searched for.
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isUserSupported() {
|
||||
return mProfileChallengeUserId != UserHandle.USER_NULL
|
||||
@@ -37,4 +53,11 @@ public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceC
|
||||
protected int getUserId() {
|
||||
return mProfileChallengeUserId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
preference.setTitle(mContext.getResources().getString(
|
||||
R.string.security_settings_face_profile_preference_title));
|
||||
}
|
||||
}
|
||||
|
@@ -60,7 +60,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
private FaceManager mFaceManager;
|
||||
private int mUserId;
|
||||
private byte[] mToken;
|
||||
private FaceSettingsAttentionPreferenceController mAttentionController;
|
||||
private FaceSettingsRemoveButtonPreferenceController mRemoveController;
|
||||
private FaceSettingsEnrollButtonPreferenceController mEnrollController;
|
||||
private List<AbstractPreferenceController> mControllers;
|
||||
@@ -69,6 +68,8 @@ public class FaceSettings extends DashboardFragment {
|
||||
private Preference mRemoveButton;
|
||||
private Preference mEnrollButton;
|
||||
|
||||
private boolean mConfirmingPassword;
|
||||
|
||||
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
|
||||
|
||||
// Disable the toggles until the user re-enrolls
|
||||
@@ -117,12 +118,18 @@ public class FaceSettings extends DashboardFragment {
|
||||
mUserId = getActivity().getIntent().getIntExtra(
|
||||
Intent.EXTRA_USER_ID, UserHandle.myUserId());
|
||||
|
||||
if (mUserManager.getUserInfo(mUserId).isManagedProfile()) {
|
||||
getActivity().setTitle(getActivity().getResources().getString(
|
||||
R.string.security_settings_face_profile_preference_title));
|
||||
}
|
||||
|
||||
Preference keyguardPref = findPreference(FaceSettingsKeyguardPreferenceController.KEY);
|
||||
Preference appPref = findPreference(FaceSettingsAppPreferenceController.KEY);
|
||||
Preference attentionPref = findPreference(FaceSettingsAttentionPreferenceController.KEY);
|
||||
Preference confirmPref = findPreference(FaceSettingsConfirmPreferenceController.KEY);
|
||||
Preference bypassPref =
|
||||
findPreference(FaceSettingsLockscreenBypassPreferenceController.KEY);
|
||||
mTogglePreferences = new ArrayList<>(
|
||||
Arrays.asList(keyguardPref, appPref, attentionPref, confirmPref));
|
||||
Arrays.asList(keyguardPref, appPref, confirmPref, bypassPref));
|
||||
|
||||
mRemoveButton = findPreference(FaceSettingsRemoveButtonPreferenceController.KEY);
|
||||
mEnrollButton = findPreference(FaceSettingsEnrollButtonPreferenceController.KEY);
|
||||
@@ -145,24 +152,27 @@ public class FaceSettings extends DashboardFragment {
|
||||
if (savedInstanceState != null) {
|
||||
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
|
||||
}
|
||||
|
||||
if (mToken == null) {
|
||||
final long challenge = mFaceManager.generateChallenge();
|
||||
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
|
||||
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(R.string.security_settings_face_preference_title),
|
||||
null, null, challenge, mUserId)) {
|
||||
Log.e(TAG, "Password not set");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mToken != null) {
|
||||
mAttentionController.setToken(mToken);
|
||||
|
||||
if (mToken == null && !mConfirmingPassword) {
|
||||
// Generate challenge in onResume instead of onCreate, since FaceSettings can be
|
||||
// created while Keyguard is showing, in which case the resetLockout revokeChallenge
|
||||
// will invalidate the too-early created challenge here.
|
||||
final long challenge = mFaceManager.generateChallenge();
|
||||
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
|
||||
|
||||
mConfirmingPassword = true;
|
||||
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(R.string.security_settings_face_preference_title),
|
||||
null, null, challenge, mUserId, true /* foregroundOnly */)) {
|
||||
Log.e(TAG, "Password not set");
|
||||
finish();
|
||||
}
|
||||
} else {
|
||||
mEnrollController.setToken(mToken);
|
||||
}
|
||||
|
||||
@@ -175,6 +185,7 @@ public class FaceSettings extends DashboardFragment {
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == CONFIRM_REQUEST) {
|
||||
mConfirmingPassword = false;
|
||||
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
|
||||
mFaceManager.setActiveUser(mUserId);
|
||||
// The pin/pattern/password was set.
|
||||
@@ -182,7 +193,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
mToken = data.getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
if (mToken != null) {
|
||||
mAttentionController.setToken(mToken);
|
||||
mEnrollController.setToken(mToken);
|
||||
}
|
||||
}
|
||||
@@ -196,16 +206,28 @@ public class FaceSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (getActivity().isFinishing()) {
|
||||
final int result = mFaceManager.revokeChallenge();
|
||||
if (result < 0) {
|
||||
Log.w(TAG, "revokeChallenge failed, result: " + result);
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (!mEnrollController.isClicked() && !getActivity().isChangingConfigurations()
|
||||
&& !mConfirmingPassword) {
|
||||
// Revoke challenge and finish
|
||||
if (mToken != null) {
|
||||
final int result = mFaceManager.revokeChallenge();
|
||||
if (result < 0) {
|
||||
Log.w(TAG, "revokeChallenge failed, result: " + result);
|
||||
}
|
||||
mToken = null;
|
||||
}
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHelpResource() {
|
||||
return R.string.help_url_face;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
if (!isAvailable(context)) {
|
||||
@@ -214,9 +236,7 @@ public class FaceSettings extends DashboardFragment {
|
||||
mControllers = buildPreferenceControllers(context, getSettingsLifecycle());
|
||||
// There's no great way of doing this right now :/
|
||||
for (AbstractPreferenceController controller : mControllers) {
|
||||
if (controller instanceof FaceSettingsAttentionPreferenceController) {
|
||||
mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
|
||||
} else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
|
||||
if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
|
||||
mRemoveController = (FaceSettingsRemoveButtonPreferenceController) controller;
|
||||
mRemoveController.setListener(mRemovalListener);
|
||||
mRemoveController.setActivity((SettingsActivity) getActivity());
|
||||
@@ -235,7 +255,6 @@ public class FaceSettings extends DashboardFragment {
|
||||
controllers.add(new FaceSettingsVideoPreferenceController(context));
|
||||
controllers.add(new FaceSettingsKeyguardPreferenceController(context));
|
||||
controllers.add(new FaceSettingsAppPreferenceController(context));
|
||||
controllers.add(new FaceSettingsAttentionPreferenceController(context));
|
||||
controllers.add(new FaceSettingsRemoveButtonPreferenceController(context));
|
||||
controllers.add(new FaceSettingsFooterPreferenceController(context));
|
||||
controllers.add(new FaceSettingsConfirmPreferenceController(context));
|
||||
|
@@ -78,6 +78,19 @@ public class FaceSettingsAppPreferenceController extends FaceSettingsPreferenceC
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
if(mFaceManager == null){
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
// By only allowing this preference controller to be searchable when the feature is turned
|
||||
// off, it will give preference to the face setup controller.
|
||||
final boolean hasEnrolledUser = mFaceManager.hasEnrolledTemplates(getUserId());
|
||||
final boolean appUnlockEnabled = Settings.Secure.getIntForUser(
|
||||
mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED, OFF, getUserId()) == ON;
|
||||
if (hasEnrolledUser && !appUnlockEnabled) {
|
||||
return AVAILABLE;
|
||||
} else {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -99,7 +99,8 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
|
||||
}
|
||||
// Set to disabled until we know the true value.
|
||||
mPreference.setEnabled(false);
|
||||
mFaceManager.getFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, mGetFeatureCallback);
|
||||
mFaceManager.getFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION,
|
||||
mGetFeatureCallback);
|
||||
|
||||
// Ideally returns a cached value.
|
||||
return true;
|
||||
@@ -111,8 +112,8 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
|
||||
mPreference.setEnabled(false);
|
||||
mPreference.setChecked(isChecked);
|
||||
|
||||
mFaceManager.setFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked, mToken,
|
||||
mSetFeatureCallback);
|
||||
mFaceManager.setFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked,
|
||||
mToken, mSetFeatureCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
|
||||
private byte[] mToken;
|
||||
private SettingsActivity mActivity;
|
||||
private Button mButton;
|
||||
private boolean mIsClicked;
|
||||
|
||||
public FaceSettingsEnrollButtonPreferenceController(Context context) {
|
||||
this(context, KEY);
|
||||
@@ -63,6 +64,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mIsClicked = true;
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName());
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
@@ -83,6 +85,13 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
// Return the click state, then clear its state.
|
||||
public boolean isClicked() {
|
||||
final boolean wasClicked = mIsClicked;
|
||||
mIsClicked = false;
|
||||
return wasClicked;
|
||||
}
|
||||
|
||||
public void setActivity(SettingsActivity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
@@ -18,16 +18,13 @@ package com.android.settings.biometrics.face;
|
||||
|
||||
import static android.provider.Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
|
||||
/**
|
||||
* Preference controller for Face settings page controlling the ability to unlock the phone
|
||||
@@ -87,13 +84,4 @@ public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
|
||||
preference.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean adminDisabled() {
|
||||
DevicePolicyManager dpm =
|
||||
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
return dpm != null &&
|
||||
(dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
|
||||
& DevicePolicyManager.KEYGUARD_DISABLE_FACE)
|
||||
!= 0;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.biometrics.face;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
public class FaceSettingsLockscreenBypassPreferenceController
|
||||
extends FaceSettingsPreferenceController {
|
||||
|
||||
static final String KEY = "security_lockscreen_bypass";
|
||||
|
||||
@VisibleForTesting
|
||||
protected FaceManager mFaceManager;
|
||||
private UserManager mUserManager;
|
||||
|
||||
public FaceSettingsLockscreenBypassPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
||||
mFaceManager = context.getSystemService(FaceManager.class);
|
||||
}
|
||||
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
boolean defaultValue = mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_faceAuthDismissesKeyguard);
|
||||
return Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, defaultValue ? 1 : 0) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, isChecked ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
if (!FaceSettings.isAvailable(mContext)) {
|
||||
preference.setEnabled(false);
|
||||
} else if (adminDisabled()) {
|
||||
preference.setEnabled(false);
|
||||
} else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
|
||||
preference.setEnabled(false);
|
||||
} else {
|
||||
preference.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (mUserManager.isManagedProfile(UserHandle.myUserId())) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
|
||||
return mFaceManager.hasEnrolledTemplates() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
|
||||
} else {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
|
||||
@@ -38,4 +40,13 @@ public abstract class FaceSettingsPreferenceController extends TogglePreferenceC
|
||||
protected int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
protected boolean adminDisabled() {
|
||||
DevicePolicyManager dpm =
|
||||
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
return dpm != null &&
|
||||
(dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
|
||||
& DevicePolicyManager.KEYGUARD_DISABLE_FACE)
|
||||
!= 0;
|
||||
}
|
||||
}
|
||||
|
@@ -64,7 +64,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
|
||||
|
||||
builder.setTitle(R.string.security_settings_face_settings_remove_dialog_title)
|
||||
.setMessage(R.string.security_settings_face_settings_remove_dialog_details)
|
||||
.setPositiveButton(R.string.okay, mOnClickListener)
|
||||
.setPositiveButton(R.string.delete, mOnClickListener)
|
||||
.setNegativeButton(R.string.cancel, mOnClickListener);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
|
@@ -26,7 +26,7 @@ import com.android.settings.biometrics.BiometricStatusPreferenceController;
|
||||
|
||||
public class FaceStatusPreferenceController extends BiometricStatusPreferenceController {
|
||||
|
||||
private static final String KEY_FACE_SETTINGS = "face_settings";
|
||||
public static final String KEY_FACE_SETTINGS = "face_settings";
|
||||
|
||||
protected final FaceManager mFaceManager;
|
||||
|
||||
|
@@ -617,7 +617,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
|
||||
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(R.string.security_settings_fingerprint_preference_title),
|
||||
null, null, challenge, mUserId)) {
|
||||
null, null, challenge, mUserId, true /* foregroundOnly */)) {
|
||||
intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName());
|
||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||
|
@@ -494,12 +494,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
|
||||
controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle));
|
||||
controllers.add(new AutofillResetOptionsPreferenceController(context));
|
||||
controllers.add(new OverlayCategoryPreferenceController(context,
|
||||
"android.theme.customization.accent_color"));
|
||||
controllers.add(new OverlayCategoryPreferenceController(context,
|
||||
"android.theme.customization.font"));
|
||||
controllers.add(new OverlayCategoryPreferenceController(context,
|
||||
"android.theme.customization.adaptive_icon_shape"));
|
||||
controllers.add(new TrustAgentsExtendUnlockPreferenceController(context));
|
||||
controllers.add(new TrustLostLocksScreenPreferenceController(context));
|
||||
return controllers;
|
||||
|
@@ -21,6 +21,7 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -28,9 +29,20 @@ import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class MainlineModuleVersionPreferenceController extends BasePreferenceController {
|
||||
|
||||
private static final String TAG = "MainlineModuleControl";
|
||||
private static final List<String> VERSION_NAME_DATE_PATTERNS = Arrays.asList("yyyy-MM-dd",
|
||||
"yyyy-MM");
|
||||
|
||||
@VisibleForTesting
|
||||
static final Intent MODULE_UPDATE_INTENT =
|
||||
@@ -81,6 +93,30 @@ public class MainlineModuleVersionPreferenceController extends BasePreferenceCon
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return mModuleVersion;
|
||||
if (TextUtils.isEmpty(mModuleVersion)) {
|
||||
return mModuleVersion;
|
||||
}
|
||||
|
||||
final Optional<Date> parsedDate = parseDateFromVersionName(mModuleVersion);
|
||||
if (!parsedDate.isPresent()) {
|
||||
Log.w("Could not parse mainline versionName (%s) as date.", mModuleVersion);
|
||||
return mModuleVersion;
|
||||
}
|
||||
|
||||
return DateFormat.getLongDateFormat(mContext).format(parsedDate.get());
|
||||
}
|
||||
|
||||
private Optional<Date> parseDateFromVersionName(String text) {
|
||||
for (String pattern : VERSION_NAME_DATE_PATTERNS) {
|
||||
try {
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern,
|
||||
Locale.getDefault());
|
||||
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
return Optional.of(simpleDateFormat.parse(text));
|
||||
} catch (ParseException e) {
|
||||
// ignore and try next pattern
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import android.content.Context;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPreferenceController {
|
||||
|
||||
public AdaptiveSleepDetailPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
}
|
||||
@@ -42,6 +43,6 @@ public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPrefer
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
preference.setEnabled(super.hasSufficientPermissions);
|
||||
preference.setEnabled(hasSufficientPermission(mContext.getPackageManager()));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.display;
|
||||
|
||||
import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class AdaptiveSleepPermissionPreferenceController extends BasePreferenceController {
|
||||
final static String PREF_NAME = "adaptive_sleep_permission";
|
||||
private final Intent mIntent;
|
||||
|
||||
public AdaptiveSleepPermissionPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
final String packageName = context.getPackageManager().getAttentionServicePackageName();
|
||||
mIntent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
mIntent.setData(Uri.parse("package:" + packageName));
|
||||
}
|
||||
|
||||
@Override
|
||||
@AvailabilityStatus
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
|
||||
mContext.startActivity(mIntent);
|
||||
return true;
|
||||
}
|
||||
return super.handlePreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
|
||||
preference.setVisible(!hasSufficientPermission(mContext.getPackageManager()));
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,28 +25,20 @@ import com.android.settings.core.TogglePreferenceController;
|
||||
|
||||
|
||||
public class AdaptiveSleepPreferenceController extends TogglePreferenceController {
|
||||
|
||||
private final String SYSTEM_KEY = ADAPTIVE_SLEEP;
|
||||
private final int DEFAULT_VALUE = 0;
|
||||
|
||||
final boolean hasSufficientPermissions;
|
||||
public static final String PREF_NAME = "adaptive_sleep";
|
||||
private static final String SYSTEM_KEY = ADAPTIVE_SLEEP;
|
||||
private static final int DEFAULT_VALUE = 0;
|
||||
|
||||
public AdaptiveSleepPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
|
||||
final PackageManager packageManager = mContext.getPackageManager();
|
||||
final String attentionPackage = packageManager.getAttentionServicePackageName();
|
||||
hasSufficientPermissions = attentionPackage != null && packageManager.checkPermission(
|
||||
Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return hasSufficientPermissions && Settings.System.getInt(mContext.getContentResolver(),
|
||||
SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
|
||||
return hasSufficientPermission(mContext.getPackageManager()) && Settings.System.getInt(
|
||||
mContext.getContentResolver(), SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY,
|
||||
@@ -57,10 +49,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
|
||||
@Override
|
||||
@AvailabilityStatus
|
||||
public int getAvailabilityStatus() {
|
||||
return mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_adaptive_sleep_available)
|
||||
? AVAILABLE_UNSEARCHABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
return isControllerAvailable(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,4 +58,17 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
|
||||
? R.string.adaptive_sleep_summary_on
|
||||
: R.string.adaptive_sleep_summary_off);
|
||||
}
|
||||
|
||||
public static int isControllerAvailable(Context context) {
|
||||
return context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_adaptive_sleep_available)
|
||||
? AVAILABLE_UNSEARCHABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
static boolean hasSufficientPermission(PackageManager packageManager) {
|
||||
final String attentionPackage = packageManager.getAttentionServicePackageName();
|
||||
return attentionPackage != null && packageManager.checkPermission(
|
||||
Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
||||
|
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.android.settings.display;
|
||||
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
@@ -34,14 +39,28 @@ import java.util.List;
|
||||
public class AdaptiveSleepSettings extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "AdaptiveSleepSettings";
|
||||
private Context mContext;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
final FooterPreference footerPreference =
|
||||
mFooterPreferenceMixin.createFooterPreference();
|
||||
mContext = getContext();
|
||||
|
||||
footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
|
||||
footerPreference.setTitle(R.string.adaptive_sleep_privacy);
|
||||
|
||||
Preference permissionPreference = findPreference(
|
||||
AdaptiveSleepPermissionPreferenceController.PREF_NAME);
|
||||
if (permissionPreference != null) {
|
||||
permissionPreference.setVisible(false);
|
||||
}
|
||||
|
||||
mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putBoolean(PREF_KEY_INTERACTED, true)
|
||||
.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -213,5 +213,13 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
|
||||
sir.xmlResId = R.xml.color_mode_settings;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
final int[] availableColorModes = context.getResources().getIntArray(
|
||||
com.android.internal.R.array.config_availableColorModes);
|
||||
return availableColorModes != null && availableColorModes.length > 0
|
||||
&& !ColorDisplayManager.areAccessibilityTransformsEnabled(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -1,62 +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.gestures;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
/**
|
||||
* Dialog to notify user that gesture navigation is not available because of unsupported launcher.
|
||||
*/
|
||||
public class GestureNavigationNotAvailableDialog extends InstrumentedDialogFragment {
|
||||
private static final String TAG = "GestureNavigationNotAvailableDialog";
|
||||
|
||||
public static void show(SystemNavigationGestureSettings parent) {
|
||||
if (!parent.isAdded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final GestureNavigationNotAvailableDialog dialog =
|
||||
new GestureNavigationNotAvailableDialog();
|
||||
dialog.setTargetFragment(parent, 0);
|
||||
dialog.show(parent.getFragmentManager(), TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.SETTINGS_GESTURE_NAV_NOT_AVAILABLE_DLG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Context context = getActivity();
|
||||
final String defaultHomeAppName = SystemNavigationPreferenceController
|
||||
.getDefaultHomeAppName(context);
|
||||
final String message = getString(R.string.gesture_not_supported_dialog_message,
|
||||
defaultHomeAppName);
|
||||
return new AlertDialog.Builder(context)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.okay, null)
|
||||
.create();
|
||||
}
|
||||
}
|
@@ -22,7 +22,6 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVE
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
|
||||
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE;
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO;
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_SETTING;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
@@ -160,17 +159,9 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
|
||||
|
||||
RadioButtonPreferenceWithExtraWidget p = (RadioButtonPreferenceWithExtraWidget) pref;
|
||||
if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL) {
|
||||
if (SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(
|
||||
getContext())) {
|
||||
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
|
||||
p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog
|
||||
.show(this, getBackSensitivity(getContext(), mOverlayManager)));
|
||||
} else {
|
||||
p.setEnabled(false);
|
||||
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO);
|
||||
p.setExtraWidgetOnClickListener((v) ->
|
||||
GestureNavigationNotAvailableDialog.show(this));
|
||||
}
|
||||
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
|
||||
p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog
|
||||
.show(this, getBackSensitivity(getContext(), mOverlayManager)));
|
||||
} else {
|
||||
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE);
|
||||
}
|
||||
@@ -219,12 +210,6 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
|
||||
@Override
|
||||
protected boolean setDefaultKey(String key) {
|
||||
final Context c = getContext();
|
||||
if (key == KEY_SYSTEM_NAV_GESTURAL &&
|
||||
!SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(c)) {
|
||||
// This should not happen since the preference is disabled. Return to be safe.
|
||||
return false;
|
||||
}
|
||||
|
||||
setCurrentSystemNavigationMode(c, mOverlayManager, key);
|
||||
setIllustrationVideo(mVideoPreference, key);
|
||||
if (TextUtils.equals(KEY_SYSTEM_NAV_GESTURAL, key) && (
|
||||
|
@@ -22,14 +22,11 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SystemNavigationPreferenceController extends BasePreferenceController {
|
||||
|
||||
static final String PREF_KEY_SYSTEM_NAVIGATION = "gesture_system_navigation";
|
||||
@@ -101,31 +98,4 @@ public class SystemNavigationPreferenceController extends BasePreferenceControll
|
||||
return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode);
|
||||
}
|
||||
|
||||
static boolean isGestureNavSupportedByDefaultLauncher(Context context) {
|
||||
final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
|
||||
if (cn == null) {
|
||||
// There is no default home app set for the current user, don't make any changes yet.
|
||||
return true;
|
||||
}
|
||||
ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
|
||||
com.android.internal.R.string.config_recentsComponentName));
|
||||
return recentsComponentName.getPackageName().equals(cn.getPackageName());
|
||||
}
|
||||
|
||||
static String getDefaultHomeAppName(Context context) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
final ComponentName cn = pm.getHomeActivities(new ArrayList<>());
|
||||
if (cn != null) {
|
||||
try {
|
||||
ApplicationInfo ai = pm.getApplicationInfo(cn.getPackageName(), 0);
|
||||
if (ai != null) {
|
||||
return pm.getApplicationLabel(ai).toString();
|
||||
}
|
||||
} catch (final PackageManager.NameNotFoundException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@@ -64,12 +64,28 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
|
||||
.setCardName(contextualNotificationChannelSliceUri)
|
||||
.setCardCategory(ContextualCard.Category.POSSIBLE)
|
||||
.build();
|
||||
final String contextualAdaptiveSleepSliceUri =
|
||||
CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI.toString();
|
||||
final ContextualCard contextualAdaptiveSleepCard =
|
||||
ContextualCard.newBuilder()
|
||||
.setSliceUri(contextualAdaptiveSleepSliceUri)
|
||||
.setCardName(contextualAdaptiveSleepSliceUri)
|
||||
.setCardCategory(ContextualCard.Category.DEFAULT)
|
||||
.build();
|
||||
final ContextualCard contextualFaceSettingsCard =
|
||||
ContextualCard.newBuilder()
|
||||
.setSliceUri(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
|
||||
.setCardName(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
|
||||
.setCardCategory(ContextualCard.Category.DEFAULT)
|
||||
.build();
|
||||
final ContextualCardList cards = ContextualCardList.newBuilder()
|
||||
.addCard(wifiCard)
|
||||
.addCard(connectedDeviceCard)
|
||||
.addCard(lowStorageCard)
|
||||
.addCard(batteryFixCard)
|
||||
.addCard(notificationChannelCard)
|
||||
.addCard(contextualAdaptiveSleepCard)
|
||||
.addCard(contextualFaceSettingsCard)
|
||||
.build();
|
||||
|
||||
return cards;
|
||||
|
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.homepage.contextualcards.slices;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.display.AdaptiveSleepPreferenceController.PREF_NAME;
|
||||
import static com.android.settings.display.AdaptiveSleepPreferenceController.isControllerAvailable;
|
||||
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.display.AdaptiveSleepSettings;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBuilderUtils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ContextualAdaptiveSleepSlice implements CustomSliceable {
|
||||
private static final String TAG = "ContextualAdaptiveSleepSlice";
|
||||
private static final long DEFAULT_SETUP_TIME = 0;
|
||||
private Context mContext;
|
||||
|
||||
@VisibleForTesting
|
||||
static final long DEFERRED_TIME_DAYS = TimeUnit.DAYS.toMillis(14);
|
||||
@VisibleForTesting
|
||||
static final String PREF_KEY_SETUP_TIME = "adaptive_sleep_setup_time";
|
||||
|
||||
public static final String PREF_KEY_INTERACTED = "adaptive_sleep_interacted";
|
||||
public static final String PREF = "adaptive_sleep_slice";
|
||||
|
||||
public ContextualAdaptiveSleepSlice(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
final long setupTime = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getLong(
|
||||
PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
|
||||
if (setupTime == DEFAULT_SETUP_TIME) {
|
||||
// Set the first setup time.
|
||||
mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putLong(PREF_KEY_SETUP_TIME, System.currentTimeMillis())
|
||||
.apply();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Display the contextual card only if all the following 3 conditions hold:
|
||||
// 1. The Screen Attention is enabled in Settings.
|
||||
// 2. The device is not recently set up.
|
||||
// 3. Current user hasn't opened Screen Attention's settings page before.
|
||||
if (isSettingsAvailable() && !isUserInteracted() && !isRecentlySetup()) {
|
||||
final IconCompat icon = IconCompat.createWithResource(mContext,
|
||||
R.drawable.ic_settings_adaptive_sleep);
|
||||
final CharSequence title = mContext.getText(R.string.adaptive_sleep_title);
|
||||
final CharSequence subtitle = mContext.getText(
|
||||
R.string.adaptive_sleep_contextual_slice_summary);
|
||||
|
||||
final SliceAction pAction = SliceAction.createDeeplink(getPrimaryAction(),
|
||||
icon,
|
||||
ListBuilder.ICON_IMAGE,
|
||||
title);
|
||||
final ListBuilder listBuilder = new ListBuilder(mContext,
|
||||
CONTEXTUAL_ADAPTIVE_SLEEP_URI,
|
||||
ListBuilder.INFINITY)
|
||||
.setAccentColor(COLOR_NOT_TINTED)
|
||||
.addRow(new ListBuilder.RowBuilder()
|
||||
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
||||
.setTitle(title)
|
||||
.setSubtitle(subtitle)
|
||||
.setPrimaryAction(pAction));
|
||||
return listBuilder.build();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return CONTEXTUAL_ADAPTIVE_SLEEP_URI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
final CharSequence screenTitle = mContext.getText(R.string.adaptive_sleep_title);
|
||||
final Uri contentUri = new Uri.Builder().appendPath(PREF_NAME).build();
|
||||
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
|
||||
AdaptiveSleepSettings.class.getName(), PREF_NAME, screenTitle.toString(),
|
||||
SettingsEnums.SLICE).setClassName(mContext.getPackageName(),
|
||||
SubSettings.class.getName()).setData(contentUri);
|
||||
}
|
||||
|
||||
private PendingIntent getPrimaryAction() {
|
||||
final Intent intent = getIntent();
|
||||
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the current user has opened the Screen Attention settings page
|
||||
* before, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isUserInteracted() {
|
||||
return mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getBoolean(
|
||||
PREF_KEY_INTERACTED, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The device is recently set up means its first settings-open time is within 2 weeks ago.
|
||||
*
|
||||
* @return {@code true} if the device is recently set up, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isRecentlySetup() {
|
||||
final long endTime = System.currentTimeMillis() - DEFERRED_TIME_DAYS;
|
||||
final long firstSetupTime = mContext.getSharedPreferences(PREF,
|
||||
Context.MODE_PRIVATE).getLong(PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
|
||||
return firstSetupTime > endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the screen attention settings is enabled. Contextual card will only appear
|
||||
* when the screen attention settings is available.
|
||||
*
|
||||
* @return {@code true} if screen attention settings is enabled, otherwise {@code false}
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isSettingsAvailable() {
|
||||
return isControllerAvailable(mContext) == AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.homepage.contextualcards.slices;
|
||||
|
||||
|
||||
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.net.Uri;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.face.FaceStatusPreferenceController;
|
||||
import com.android.settings.security.SecuritySettings;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBuilderUtils;
|
||||
|
||||
public class FaceSetupSlice implements CustomSliceable {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public FaceSetupSlice(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
final FaceManager faceManager = Utils.getFaceManagerOrNull(mContext);
|
||||
if (faceManager == null || faceManager.hasEnrolledTemplates(UserHandle.myUserId())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CharSequence title = mContext.getText(
|
||||
R.string.security_settings_face_settings_enroll);
|
||||
final ListBuilder listBuilder = new ListBuilder(mContext,
|
||||
CustomSliceRegistry.FACE_ENROLL_SLICE_URI, ListBuilder.INFINITY)
|
||||
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
|
||||
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_face_24dp);
|
||||
return listBuilder
|
||||
.addRow(buildRowBuilder(title,
|
||||
mContext.getText(R.string.security_settings_face_settings_context_subtitle),
|
||||
icon, mContext, getIntent()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return CustomSliceRegistry.FACE_ENROLL_SLICE_URI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
|
||||
SecuritySettings.class.getName(),
|
||||
FaceStatusPreferenceController.KEY_FACE_SETTINGS,
|
||||
mContext.getText(R.string.security_settings_face_settings_enroll).toString(),
|
||||
SettingsEnums.SLICE)
|
||||
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
|
||||
}
|
||||
|
||||
private static RowBuilder buildRowBuilder(CharSequence title, CharSequence subTitle,
|
||||
IconCompat icon, Context context, Intent intent) {
|
||||
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
||||
PendingIntent.getActivity(context, 0, intent, 0), icon, ListBuilder.ICON_IMAGE,
|
||||
title);
|
||||
return new RowBuilder()
|
||||
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
||||
.setTitle(title)
|
||||
.setSubtitle(subTitle)
|
||||
.setPrimaryAction(primarySliceAction);
|
||||
}
|
||||
}
|
@@ -130,7 +130,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (mPreference == null) {
|
||||
if (mPreference == null || mPreference.isDisabledByAdmin()) {
|
||||
return;
|
||||
}
|
||||
refreshSummary(mPreference);
|
||||
|
@@ -55,7 +55,7 @@ public class TetherProvisioningActivity extends Activity {
|
||||
|
||||
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
final int subId = SubscriptionManager.getActiveDataSubscriptionId();
|
||||
if (tetherSubId != subId) {
|
||||
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
|
||||
return;
|
||||
@@ -67,6 +67,7 @@ public class TetherProvisioningActivity extends Activity {
|
||||
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setClassName(provisionApp[0], provisionApp[1]);
|
||||
intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
|
||||
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.view.Menu;
|
||||
@@ -76,6 +77,13 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
updateSubscriptions(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -86,13 +94,18 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
|
||||
setContentView(R.layout.mobile_network_settings_container);
|
||||
}
|
||||
setActionBar(findViewById(R.id.mobile_action_bar));
|
||||
mPhoneChangeReceiver = new PhoneChangeReceiver(this, () -> {
|
||||
if (mCurSubscriptionId != SUB_ID_NULL) {
|
||||
// When the radio changes (ex: CDMA->GSM), refresh the fragment.
|
||||
// This is very rare.
|
||||
mPhoneChangeReceiver = new PhoneChangeReceiver(this, new PhoneChangeReceiver.Client() {
|
||||
@Override
|
||||
public void onPhoneChange() {
|
||||
// When the radio or carrier config changes (ex: CDMA->GSM), refresh the fragment.
|
||||
switchFragment(new MobileNetworkSettings(), mCurSubscriptionId,
|
||||
true /* forceUpdate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSubscriptionId() {
|
||||
return mCurSubscriptionId;
|
||||
}
|
||||
});
|
||||
mSubscriptionManager = getSystemService(SubscriptionManager.class);
|
||||
mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(true);
|
||||
@@ -243,14 +256,12 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
|
||||
|
||||
@VisibleForTesting
|
||||
static class PhoneChangeReceiver extends BroadcastReceiver {
|
||||
private static final IntentFilter RADIO_TECHNOLOGY_CHANGED_FILTER = new IntentFilter(
|
||||
TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
|
||||
|
||||
private Context mContext;
|
||||
private Client mClient;
|
||||
|
||||
interface Client {
|
||||
void onPhoneChange();
|
||||
int getSubscriptionId();
|
||||
}
|
||||
|
||||
public PhoneChangeReceiver(Context context, Client client) {
|
||||
@@ -259,7 +270,10 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
|
||||
}
|
||||
|
||||
public void register() {
|
||||
mContext.registerReceiver(this, RADIO_TECHNOLOGY_CHANGED_FILTER);
|
||||
final IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
|
||||
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
|
||||
mContext.registerReceiver(this, intentFilter);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
@@ -268,9 +282,17 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!isInitialStickyBroadcast()) {
|
||||
mClient.onPhoneChange();
|
||||
if (isInitialStickyBroadcast()) {
|
||||
return;
|
||||
}
|
||||
if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
|
||||
if (!intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX) ||
|
||||
intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1)
|
||||
!= mClient.getSubscriptionId()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mClient.onPhoneChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -61,16 +61,12 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
|
||||
PhoneAccountHandle mSimCallManager;
|
||||
private PhoneCallStateListener mPhoneStateListener;
|
||||
private Preference mPreference;
|
||||
private boolean mEditableWfcRoamingMode;
|
||||
private boolean mUseWfcHomeModeForRoaming;
|
||||
|
||||
public WifiCallingPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
|
||||
mTelephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
|
||||
mEditableWfcRoamingMode = true;
|
||||
mUseWfcHomeModeForRoaming = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,9 +125,18 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
|
||||
preference.setTitle(title);
|
||||
int resId = com.android.internal.R.string.wifi_calling_off_summary;
|
||||
if (mImsManager.isWfcEnabledByUser()) {
|
||||
boolean wfcRoamingEnabled = mEditableWfcRoamingMode && !mUseWfcHomeModeForRoaming;
|
||||
boolean useWfcHomeModeForRoaming = false;
|
||||
if (mCarrierConfigManager != null) {
|
||||
final PersistableBundle carrierConfig =
|
||||
mCarrierConfigManager.getConfigForSubId(mSubId);
|
||||
if (carrierConfig != null) {
|
||||
useWfcHomeModeForRoaming = carrierConfig.getBoolean(
|
||||
CarrierConfigManager
|
||||
.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
|
||||
}
|
||||
}
|
||||
final boolean isRoaming = mTelephonyManager.isNetworkRoaming();
|
||||
int wfcMode = mImsManager.getWfcMode(isRoaming && wfcRoamingEnabled);
|
||||
int wfcMode = mImsManager.getWfcMode(isRoaming && !useWfcHomeModeForRoaming);
|
||||
switch (wfcMode) {
|
||||
case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
|
||||
resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
|
||||
@@ -159,16 +164,6 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
|
||||
mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
|
||||
mSimCallManager = mContext.getSystemService(TelecomManager.class)
|
||||
.getSimCallManagerForSubscription(mSubId);
|
||||
if (mCarrierConfigManager != null) {
|
||||
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
|
||||
if (carrierConfig != null) {
|
||||
mEditableWfcRoamingMode = carrierConfig.getBoolean(
|
||||
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
||||
mUseWfcHomeModeForRoaming = carrierConfig.getBoolean(
|
||||
CarrierConfigManager
|
||||
.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PhoneCallStateListener extends PhoneStateListener {
|
||||
|
@@ -55,7 +55,7 @@ public abstract class RingtonePreferenceControllerBase extends AbstractPreferenc
|
||||
|
||||
final CharSequence summary;
|
||||
if (ringtoneUri == null) {
|
||||
summary = null;
|
||||
summary = mContext.getString(com.android.internal.R.string.ringtone_silent);
|
||||
} else {
|
||||
summary = Ringtone.getTitle(
|
||||
mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
|
||||
|
@@ -47,6 +47,7 @@ public final class ChooseLockSettingsHelper {
|
||||
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
|
||||
public static final String EXTRA_KEY_FOR_FACE = "for_face";
|
||||
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
|
||||
public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
|
||||
|
||||
/**
|
||||
* Intent extra for passing the requested min password complexity to later steps in the set new
|
||||
@@ -105,7 +106,8 @@ public final class ChooseLockSettingsHelper {
|
||||
null /* header */,
|
||||
null /* description */,
|
||||
false /* returnCredentials */,
|
||||
false /* external */);
|
||||
false /* external */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +126,8 @@ public final class ChooseLockSettingsHelper {
|
||||
null /* header */,
|
||||
null /* description */,
|
||||
returnCredentials /* returnCredentials */,
|
||||
false /* external */);
|
||||
false /* external */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +151,8 @@ public final class ChooseLockSettingsHelper {
|
||||
false /* external */,
|
||||
false /* hasChallenge */,
|
||||
0 /* challenge */,
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */);
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,12 +166,13 @@ public final class ChooseLockSettingsHelper {
|
||||
* @param external specifies whether this activity is launched externally, meaning that it will
|
||||
* get a dark theme, allow fingerprint authentication and it will forward
|
||||
* activity result.
|
||||
* @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
|
||||
* @return true if one exists and we launched an activity to confirm it
|
||||
* @see Activity#onActivityResult(int, int, android.content.Intent)
|
||||
*/
|
||||
boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
boolean returnCredentials, boolean external) {
|
||||
boolean returnCredentials, boolean external, boolean foregroundOnly) {
|
||||
return launchConfirmationActivity(
|
||||
request /* request */,
|
||||
title /* title */,
|
||||
@@ -177,7 +182,8 @@ public final class ChooseLockSettingsHelper {
|
||||
external /* external */,
|
||||
false /* hasChallenge */,
|
||||
0 /* challenge */,
|
||||
Utils.getCredentialOwnerUserId(mActivity) /* userId */);
|
||||
Utils.getCredentialOwnerUserId(mActivity) /* userId */,
|
||||
foregroundOnly /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +213,8 @@ public final class ChooseLockSettingsHelper {
|
||||
external /* external */,
|
||||
false /* hasChallenge */,
|
||||
0 /* challenge */,
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */);
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,12 +224,13 @@ public final class ChooseLockSettingsHelper {
|
||||
* @param header header of the confirmation screen; shown as large text
|
||||
* @param description description of the confirmation screen
|
||||
* @param challenge a challenge to be verified against the device credential.
|
||||
* @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
|
||||
* @return true if one exists and we launched an activity to confirm it
|
||||
* @see Activity#onActivityResult(int, int, android.content.Intent)
|
||||
*/
|
||||
public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
long challenge) {
|
||||
long challenge, boolean foregroundOnly) {
|
||||
return launchConfirmationActivity(
|
||||
request /* request */,
|
||||
title /* title */,
|
||||
@@ -232,7 +240,8 @@ public final class ChooseLockSettingsHelper {
|
||||
false /* external */,
|
||||
true /* hasChallenge */,
|
||||
challenge /* challenge */,
|
||||
Utils.getCredentialOwnerUserId(mActivity) /* userId */);
|
||||
Utils.getCredentialOwnerUserId(mActivity) /* userId */,
|
||||
foregroundOnly /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,12 +252,13 @@ public final class ChooseLockSettingsHelper {
|
||||
* @param description description of the confirmation screen
|
||||
* @param challenge a challenge to be verified against the device credential.
|
||||
* @param userId The userId for whom the lock should be confirmed.
|
||||
* @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
|
||||
* @return true if one exists and we launched an activity to confirm it
|
||||
* @see Activity#onActivityResult(int, int, android.content.Intent)
|
||||
*/
|
||||
public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
long challenge, int userId) {
|
||||
long challenge, int userId, boolean foregroundOnly) {
|
||||
return launchConfirmationActivity(
|
||||
request /* request */,
|
||||
title /* title */,
|
||||
@@ -258,7 +268,8 @@ public final class ChooseLockSettingsHelper {
|
||||
false /* external */,
|
||||
true /* hasChallenge */,
|
||||
challenge /* challenge */,
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */);
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */,
|
||||
foregroundOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +298,8 @@ public final class ChooseLockSettingsHelper {
|
||||
external /* external */,
|
||||
true /* hasChallenge */,
|
||||
challenge /* challenge */,
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */);
|
||||
Utils.enforceSameOwner(mActivity, userId) /* userId */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,7 +328,7 @@ public final class ChooseLockSettingsHelper {
|
||||
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
boolean returnCredentials, boolean external, boolean hasChallenge,
|
||||
long challenge, int userId) {
|
||||
long challenge, int userId, boolean foregroundOnly) {
|
||||
return launchConfirmationActivity(
|
||||
request /* request */,
|
||||
title /* title */,
|
||||
@@ -328,7 +340,8 @@ public final class ChooseLockSettingsHelper {
|
||||
challenge /* challenge */,
|
||||
userId /* userId */,
|
||||
null /* alternateButton */,
|
||||
null /* extras */);
|
||||
null /* extras */,
|
||||
foregroundOnly /* foregroundOnly */);
|
||||
}
|
||||
|
||||
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@@ -346,7 +359,8 @@ public final class ChooseLockSettingsHelper {
|
||||
challenge /* challenge */,
|
||||
userId /* userId */,
|
||||
null /* alternateButton */,
|
||||
extras /* extras */);
|
||||
extras /* extras */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
public boolean launchFrpConfirmationActivity(int request, @Nullable CharSequence header,
|
||||
@@ -362,13 +376,15 @@ public final class ChooseLockSettingsHelper {
|
||||
0 /* challenge */,
|
||||
LockPatternUtils.USER_FRP /* userId */,
|
||||
alternateButton /* alternateButton */,
|
||||
null /* extras */);
|
||||
null /* extras */,
|
||||
false /* foregroundOnly */);
|
||||
}
|
||||
|
||||
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
boolean returnCredentials, boolean external, boolean hasChallenge,
|
||||
long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras) {
|
||||
long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras,
|
||||
boolean foregroundOnly) {
|
||||
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
|
||||
boolean launched = false;
|
||||
|
||||
@@ -378,7 +394,8 @@ public final class ChooseLockSettingsHelper {
|
||||
returnCredentials || hasChallenge
|
||||
? ConfirmLockPattern.InternalActivity.class
|
||||
: ConfirmLockPattern.class, returnCredentials, external,
|
||||
hasChallenge, challenge, userId, alternateButton, extras);
|
||||
hasChallenge, challenge, userId, alternateButton, extras,
|
||||
foregroundOnly);
|
||||
break;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
@@ -390,7 +407,8 @@ public final class ChooseLockSettingsHelper {
|
||||
returnCredentials || hasChallenge
|
||||
? ConfirmLockPassword.InternalActivity.class
|
||||
: ConfirmLockPassword.class, returnCredentials, external,
|
||||
hasChallenge, challenge, userId, alternateButton, extras);
|
||||
hasChallenge, challenge, userId, alternateButton, extras,
|
||||
foregroundOnly);
|
||||
break;
|
||||
}
|
||||
return launched;
|
||||
@@ -399,7 +417,8 @@ public final class ChooseLockSettingsHelper {
|
||||
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
|
||||
CharSequence message, Class<?> activityClass, boolean returnCredentials,
|
||||
boolean external, boolean hasChallenge, long challenge,
|
||||
int userId, @Nullable CharSequence alternateButton, Bundle extras) {
|
||||
int userId, @Nullable CharSequence alternateButton, Bundle extras,
|
||||
boolean foregroundOnly) {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
|
||||
@@ -414,6 +433,7 @@ public final class ChooseLockSettingsHelper {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, userId);
|
||||
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
|
||||
if (extras != null) {
|
||||
intent.putExtras(extras);
|
||||
}
|
||||
|
@@ -172,6 +172,10 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
|
||||
mBiometricManager.onConfirmDeviceCredentialError(
|
||||
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
|
||||
getString(com.android.internal.R.string.biometric_error_user_canceled));
|
||||
if (getIntent().getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, false)) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -111,7 +111,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
|
||||
layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
|
||||
|
||||
int titleResource = mForFingerprint ?
|
||||
int titleResource = isForBiometric() ?
|
||||
R.string.lock_settings_picker_title : R.string.setup_lock_settings_picker_title;
|
||||
if (getActivity() != null) {
|
||||
getActivity().setTitle(titleResource);
|
||||
@@ -125,7 +125,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
|
||||
@Override
|
||||
protected void addHeaderView() {
|
||||
if (mForFingerprint || mForFace) {
|
||||
if (isForBiometric()) {
|
||||
setHeaderView(R.layout.setup_choose_lock_generic_biometrics_header);
|
||||
} else {
|
||||
setHeaderView(R.layout.setup_choose_lock_generic_header);
|
||||
@@ -183,7 +183,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
|
||||
@Override
|
||||
protected void addPreferences() {
|
||||
if (mForFingerprint) {
|
||||
if (isForBiometric()) {
|
||||
super.addPreferences();
|
||||
} else {
|
||||
addPreferencesFromResource(R.xml.setup_security_settings_picker);
|
||||
@@ -240,6 +240,10 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private boolean isForBiometric() {
|
||||
return mForFingerprint || mForFace;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InternalActivity extends ChooseLockGeneric.InternalActivity {
|
||||
@@ -261,5 +265,4 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -96,18 +96,23 @@ public final class EnableContentCaptureWithServiceSettingsPreferenceController
|
||||
for (UserInfo info: userInfos) {
|
||||
userHandles.add(info.getUserHandle());
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context, userHandles);
|
||||
builder.setTitle(com.android.settingslib.R.string.choose_profile)
|
||||
.setAdapter(adapter, (DialogInterface dialog, int which) -> {
|
||||
final UserHandle user = userHandles.get(which);
|
||||
// Show menu on top level items.
|
||||
final Intent intent = pref.getIntent();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivityAsUser(intent, user);
|
||||
})
|
||||
.show();
|
||||
if (userHandles.size() == 1) {
|
||||
final Intent intent = pref.getIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivityAsUser(intent, userHandles.get(0));
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context,
|
||||
userHandles);
|
||||
builder.setTitle(com.android.settingslib.R.string.choose_profile)
|
||||
.setAdapter(adapter, (DialogInterface dialog, int which) -> {
|
||||
final UserHandle user = userHandles.get(which);
|
||||
// Show menu on top level items.
|
||||
final Intent intent = pref.getIntent()
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivityAsUser(intent, user);
|
||||
})
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@ import android.util.ArrayMap;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.display.AdaptiveSleepPreferenceController;
|
||||
import com.android.settings.flashlight.FlashlightSlice;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
|
||||
@@ -34,7 +35,9 @@ import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSli
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.FaceSetupSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
|
||||
import com.android.settings.location.LocationSlice;
|
||||
@@ -64,6 +67,16 @@ public class CustomSliceRegistry {
|
||||
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Uri for Contextual Adaptive Sleep Slice
|
||||
*/
|
||||
public static final Uri CONTEXTUAL_ADAPTIVE_SLEEP_URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
|
||||
.appendPath(AdaptiveSleepPreferenceController.PREF_NAME)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Uri for Battery Fix Slice.
|
||||
*/
|
||||
@@ -150,6 +163,15 @@ public class CustomSliceRegistry {
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath("enhanced_4g_lte")
|
||||
.build();
|
||||
/**
|
||||
* Slice Uri for Face Enrollment
|
||||
*/
|
||||
public static final Uri FACE_ENROLL_SLICE_URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath("face_unlock_greeting_card")
|
||||
.build();
|
||||
/**
|
||||
* Backing Uri for the Flashlight Slice.
|
||||
*/
|
||||
@@ -328,21 +350,23 @@ public class CustomSliceRegistry {
|
||||
|
||||
sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
|
||||
sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
|
||||
sUriToSlice.put(CONTEXTUAL_ADAPTIVE_SLEEP_URI, ContextualAdaptiveSleepSlice.class);
|
||||
sUriToSlice.put(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI,
|
||||
ContextualNotificationChannelSlice.class);
|
||||
sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
|
||||
sUriToSlice.put(DATA_USAGE_SLICE_URI, DataUsageSlice.class);
|
||||
sUriToSlice.put(DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
|
||||
sUriToSlice.put(EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
|
||||
sUriToSlice.put(FACE_ENROLL_SLICE_URI, FaceSetupSlice.class);
|
||||
sUriToSlice.put(FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
|
||||
sUriToSlice.put(LOCATION_SLICE_URI, LocationSlice.class);
|
||||
sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
|
||||
sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
|
||||
sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
|
||||
sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
|
||||
sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
|
||||
}
|
||||
|
||||
public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
|
||||
|
@@ -17,8 +17,11 @@
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.SubscriptionManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
|
||||
/**
|
||||
@@ -33,7 +36,7 @@ public class CellularFallbackPreferenceController extends TogglePreferenceContro
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return !avoidBadWifiConfig() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
return avoidBadWifiConfig() ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,12 +52,28 @@ public class CellularFallbackPreferenceController extends TogglePreferenceContro
|
||||
}
|
||||
|
||||
private boolean avoidBadWifiConfig() {
|
||||
return mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
|
||||
final int activeDataSubscriptionId = getActiveDataSubscriptionId();
|
||||
if (activeDataSubscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Resources resources = getResourcesForSubId(activeDataSubscriptionId);
|
||||
return resources.getInteger(com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
int getActiveDataSubscriptionId() {
|
||||
return SubscriptionManager.getActiveDataSubscriptionId();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Resources getResourcesForSubId(int subscriptionId) {
|
||||
return SubscriptionManager.getResourcesForSubId(mContext, subscriptionId,
|
||||
false /* useRootLocale */);
|
||||
}
|
||||
|
||||
private boolean avoidBadWifiCurrentSettings() {
|
||||
return "1".equals(Settings.Global.getString(mContext.getContentResolver(),
|
||||
Settings.Global.NETWORK_AVOID_BAD_WIFI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -696,7 +696,11 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
}
|
||||
|
||||
mMacAddressPref.setVisible(true);
|
||||
mMacAddressPref.setSummary(macAddress);
|
||||
if (macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) {
|
||||
mMacAddressPref.setSummary(R.string.device_info_not_available);
|
||||
} else {
|
||||
mMacAddressPref.setSummary(macAddress);
|
||||
}
|
||||
}
|
||||
|
||||
private String getMacAddress() {
|
||||
|
@@ -85,7 +85,7 @@ public class TetherService extends Service {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (DEBUG) Log.d(TAG, "Creating TetherService");
|
||||
String provisionResponse = getResourceForDefaultDataSubId().getString(
|
||||
String provisionResponse = getResourceForActiveDataSubId().getString(
|
||||
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
||||
registerReceiver(mReceiver, new IntentFilter(provisionResponse),
|
||||
android.Manifest.permission.TETHER_PRIVILEGED, null);
|
||||
@@ -105,7 +105,7 @@ public class TetherService extends Service {
|
||||
if (intent.hasExtra(EXTRA_SUBID)) {
|
||||
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
|
||||
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
|
||||
if (tetherSubId != subId) {
|
||||
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
|
||||
if (!mInProvisionCheck) {
|
||||
@@ -273,11 +273,13 @@ public class TetherService extends Service {
|
||||
}
|
||||
|
||||
private Intent getProvisionBroadcastIntent(int index) {
|
||||
String provisionAction = getResourceForDefaultDataSubId().getString(
|
||||
String provisionAction = getResourceForActiveDataSubId().getString(
|
||||
com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
|
||||
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
|
||||
Intent intent = new Intent(provisionAction);
|
||||
int type = mCurrentTethers.get(index);
|
||||
intent.putExtra(TETHER_CHOICE, type);
|
||||
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
|
||||
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
|
||||
|
||||
@@ -309,7 +311,7 @@ public class TetherService extends Service {
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
|
||||
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||
int period = getResourceForDefaultDataSubId().getInteger(
|
||||
int period = getResourceForActiveDataSubId().getInteger(
|
||||
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
|
||||
long periodMs = period * MS_PER_HOUR;
|
||||
long firstTime = SystemClock.elapsedRealtime() + periodMs;
|
||||
@@ -362,7 +364,7 @@ public class TetherService extends Service {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
|
||||
String provisionResponse = getResourceForDefaultDataSubId().getString(
|
||||
String provisionResponse = getResourceForActiveDataSubId().getString(
|
||||
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
||||
|
||||
if (provisionResponse.equals(intent.getAction())) {
|
||||
@@ -429,14 +431,14 @@ public class TetherService extends Service {
|
||||
mUsageStatsManager.setAppInactive(packageName, isInactive);
|
||||
}
|
||||
|
||||
int getDefaultDataSubscriptionId() {
|
||||
return SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
int getActiveDataSubscriptionId() {
|
||||
return SubscriptionManager.getActiveDataSubscriptionId();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Resources getResourceForDefaultDataSubId() {
|
||||
final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
|
||||
Resources getResourceForActiveDataSubId() {
|
||||
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
|
||||
return Utils.getResourcesForSubId(this, subId);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user