permittedServices, boolean serviceEnabled) {
- // permittedServices null means all accessibility services are allowed.
- boolean serviceAllowed = permittedServices == null || permittedServices.contains(
- preference.getPackageName());
- boolean appOpsAllowed;
- if (serviceAllowed) {
- try {
- final int mode = mAppOps.noteOpNoThrow(
- AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
- preference.getUid(), preference.getPackageName());
- appOpsAllowed = mode == AppOpsManager.MODE_ALLOWED;
- serviceAllowed = appOpsAllowed;
- } catch (Exception e) {
- // Allow service in case if app ops is not available in testing.
- appOpsAllowed = true;
- }
- } else {
- appOpsAllowed = false;
- }
- if (serviceAllowed || serviceEnabled) {
- preference.setEnabled(true);
- } else {
- // Disable accessibility service that are not permitted.
- final EnforcedAdmin admin =
- RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
- mContext, preference.getPackageName(), UserHandle.myUserId());
-
- if (admin != null) {
- preference.setDisabledByAdmin(admin);
- } else if (!appOpsAllowed) {
- preference.setDisabledByAppOps(true);
- } else {
- preference.setEnabled(false);
- }
- }
- }
-
- /** Puts the basic extras into {@link RestrictedPreference}'s getExtras(). */
- private void putBasicExtras(RestrictedPreference preference, String prefKey,
- CharSequence title, CharSequence intro, CharSequence summary, int imageRes,
- String htmlDescription, ComponentName componentName) {
- final Bundle extras = preference.getExtras();
- extras.putString(EXTRA_PREFERENCE_KEY, prefKey);
- extras.putCharSequence(EXTRA_TITLE, title);
- extras.putCharSequence(EXTRA_INTRO, intro);
- extras.putCharSequence(EXTRA_SUMMARY, summary);
- extras.putParcelable(EXTRA_COMPONENT_NAME, componentName);
- extras.putInt(EXTRA_ANIMATED_IMAGE_RES, imageRes);
- extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
- }
-
- /**
- * Puts the service extras into {@link RestrictedPreference}'s getExtras().
- *
- * Note: Called by {@link AccessibilityServiceInfo}.
- *
- * @param preference The preference we are configuring.
- * @param resolveInfo The service resolve info.
- * @param serviceEnabled Whether the accessibility service is enabled.
- */
- private void putServiceExtras(RestrictedPreference preference, ResolveInfo resolveInfo,
- Boolean serviceEnabled) {
- final Bundle extras = preference.getExtras();
-
- extras.putParcelable(EXTRA_RESOLVE_INFO, resolveInfo);
- extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
- }
-
- /**
- * Puts the settings extras into {@link RestrictedPreference}'s getExtras().
- *
- * Note: Called when settings UI is needed.
- *
- * @param preference The preference we are configuring.
- * @param packageName Package of accessibility feature.
- * @param settingsClassName The component name of an activity that allows the user to modify
- * the settings for this accessibility feature.
- */
- private void putSettingsExtras(RestrictedPreference preference, String packageName,
- String settingsClassName) {
- final Bundle extras = preference.getExtras();
-
- if (!TextUtils.isEmpty(settingsClassName)) {
- extras.putString(EXTRA_SETTINGS_TITLE,
- mContext.getText(R.string.accessibility_menu_item_settings).toString());
- extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
- new ComponentName(packageName, settingsClassName).flattenToString());
- }
- }
-
- /**
- * Puts the information about a particular application
- * {@link android.service.quicksettings.TileService} into {@link RestrictedPreference}'s
- * getExtras().
- *
- * Note: Called when a tooltip of
- * {@link android.service.quicksettings.TileService} is needed.
- *
- * @param preference The preference we are configuring.
- * @param packageName Package of accessibility feature.
- * @param tileServiceClassName The component name of tileService is associated with this
- * accessibility feature.
- */
- private void putTileServiceExtras(RestrictedPreference preference, String packageName,
- String tileServiceClassName) {
- final Bundle extras = preference.getExtras();
- if (!TextUtils.isEmpty(tileServiceClassName)) {
- extras.putString(EXTRA_TILE_SERVICE_COMPONENT_NAME,
- new ComponentName(packageName, tileServiceClassName).flattenToString());
- }
- }
- }
}
diff --git a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
new file mode 100644
index 00000000000..3e42e21c932
--- /dev/null
+++ b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.android.settingslib.widget.TwoTargetPreference.ICON_SIZE_MEDIUM;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityShortcutInfo;
+import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.TextUtils;
+
+import androidx.core.content.ContextCompat;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class helps setup RestrictedPreference for accessibility.
+ */
+public class RestrictedPreferenceHelper {
+ // Index of the first preference in a preference category.
+ private static final int FIRST_PREFERENCE_IN_CATEGORY_INDEX = -1;
+
+ private final Context mContext;
+ private final DevicePolicyManager mDpm;
+ private final PackageManager mPm;
+ private final AppOpsManager mAppOps;
+
+ public RestrictedPreferenceHelper(Context context) {
+ mContext = context;
+ mDpm = context.getSystemService(DevicePolicyManager.class);
+ mPm = context.getPackageManager();
+ mAppOps = context.getSystemService(AppOpsManager.class);
+ }
+
+ /**
+ * Creates the list of {@link RestrictedPreference} with the installedServices arguments.
+ *
+ * @param installedServices The list of {@link AccessibilityServiceInfo}s of the
+ * installed accessibility services
+ * @return The list of {@link RestrictedPreference}
+ */
+ public List createAccessibilityServicePreferenceList(
+ List installedServices) {
+
+ final Set enabledServices =
+ AccessibilityUtils.getEnabledServicesFromSettings(mContext);
+ final List permittedServices = mDpm.getPermittedAccessibilityServices(
+ UserHandle.myUserId());
+ final int installedServicesSize = installedServices.size();
+
+ final List preferenceList = new ArrayList<>(
+ installedServicesSize);
+
+ for (int i = 0; i < installedServicesSize; ++i) {
+ final AccessibilityServiceInfo info = installedServices.get(i);
+ final ResolveInfo resolveInfo = info.getResolveInfo();
+ final String packageName = resolveInfo.serviceInfo.packageName;
+ final ComponentName componentName = new ComponentName(packageName,
+ resolveInfo.serviceInfo.name);
+
+ final String key = componentName.flattenToString();
+ final CharSequence title = resolveInfo.loadLabel(mPm);
+ final boolean serviceEnabled = enabledServices.contains(componentName);
+ final CharSequence summary = AccessibilitySettings.getServiceSummary(
+ mContext, info, serviceEnabled);
+ final String fragment = getAccessibilityServiceFragmentTypeName(info);
+
+ Drawable icon = resolveInfo.loadIcon(mPm);
+ if (resolveInfo.getIconResource() == 0) {
+ icon = ContextCompat.getDrawable(mContext,
+ R.drawable.ic_accessibility_generic);
+ }
+
+ final RestrictedPreference preference = createRestrictedPreference(key, title,
+ summary, icon, fragment, packageName,
+ resolveInfo.serviceInfo.applicationInfo.uid);
+
+ setRestrictedPreferenceEnabled(preference, permittedServices, serviceEnabled);
+
+ final String prefKey = preference.getKey();
+ final int imageRes = info.getAnimatedImageRes();
+ final CharSequence intro = info.loadIntro(mPm);
+ final CharSequence description = AccessibilitySettings.getServiceDescription(
+ mContext, info, serviceEnabled);
+ final String htmlDescription = info.loadHtmlDescription(mPm);
+ final String settingsClassName = info.getSettingsActivityName();
+ final String tileServiceClassName = info.getTileServiceName();
+
+ putBasicExtras(preference, prefKey, title, intro, description, imageRes,
+ htmlDescription, componentName);
+ putServiceExtras(preference, resolveInfo, serviceEnabled);
+ putSettingsExtras(preference, packageName, settingsClassName);
+ putTileServiceExtras(preference, packageName, tileServiceClassName);
+
+ preferenceList.add(preference);
+ }
+ return preferenceList;
+ }
+
+ /**
+ * Creates the list of {@link RestrictedPreference} with the installedShortcuts arguments.
+ *
+ * @param installedShortcuts The list of {@link AccessibilityShortcutInfo}s of the
+ * installed accessibility shortcuts
+ * @return The list of {@link RestrictedPreference}
+ */
+ public List createAccessibilityActivityPreferenceList(
+ List installedShortcuts) {
+ final Set enabledServices =
+ AccessibilityUtils.getEnabledServicesFromSettings(mContext);
+ final List permittedServices = mDpm.getPermittedAccessibilityServices(
+ UserHandle.myUserId());
+
+ final int installedShortcutsSize = installedShortcuts.size();
+ final List preferenceList = new ArrayList<>(
+ installedShortcutsSize);
+
+ for (int i = 0; i < installedShortcutsSize; ++i) {
+ final AccessibilityShortcutInfo info = installedShortcuts.get(i);
+ final ActivityInfo activityInfo = info.getActivityInfo();
+ final ComponentName componentName = info.getComponentName();
+
+ final String key = componentName.flattenToString();
+ final CharSequence title = activityInfo.loadLabel(mPm);
+ final String summary = info.loadSummary(mPm);
+ final String fragment =
+ LaunchAccessibilityActivityPreferenceFragment.class.getName();
+
+ Drawable icon = activityInfo.loadIcon(mPm);
+ if (activityInfo.getIconResource() == 0) {
+ icon = ContextCompat.getDrawable(mContext, R.drawable.ic_accessibility_generic);
+ }
+
+ final RestrictedPreference preference = createRestrictedPreference(key, title,
+ summary, icon, fragment, componentName.getPackageName(),
+ activityInfo.applicationInfo.uid);
+ final boolean serviceEnabled = enabledServices.contains(componentName);
+
+ setRestrictedPreferenceEnabled(preference, permittedServices, serviceEnabled);
+
+ final String prefKey = preference.getKey();
+ final CharSequence intro = info.loadIntro(mPm);
+ final String description = info.loadDescription(mPm);
+ final int imageRes = info.getAnimatedImageRes();
+ final String htmlDescription = info.loadHtmlDescription(mPm);
+ final String settingsClassName = info.getSettingsActivityName();
+ final String tileServiceClassName = info.getTileServiceName();
+
+ putBasicExtras(preference, prefKey, title, intro, description, imageRes,
+ htmlDescription, componentName);
+ putSettingsExtras(preference, componentName.getPackageName(), settingsClassName);
+ putTileServiceExtras(preference, componentName.getPackageName(),
+ tileServiceClassName);
+
+ preferenceList.add(preference);
+ }
+ return preferenceList;
+ }
+
+ private String getAccessibilityServiceFragmentTypeName(AccessibilityServiceInfo info) {
+ final int type = AccessibilityUtil.getAccessibilityServiceFragmentType(info);
+ switch (type) {
+ case AccessibilityUtil.AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE:
+ return VolumeShortcutToggleAccessibilityServicePreferenceFragment.class.getName();
+ case AccessibilityUtil.AccessibilityServiceFragmentType.INVISIBLE_TOGGLE:
+ return InvisibleToggleAccessibilityServicePreferenceFragment.class.getName();
+ case AccessibilityUtil.AccessibilityServiceFragmentType.TOGGLE:
+ return ToggleAccessibilityServicePreferenceFragment.class.getName();
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported accessibility fragment type " + type);
+ }
+ }
+
+ private RestrictedPreference createRestrictedPreference(String key, CharSequence title,
+ CharSequence summary, Drawable icon, String fragment, String packageName, int uid) {
+ final RestrictedPreference preference = new RestrictedPreference(mContext, packageName,
+ uid);
+
+ preference.setKey(key);
+ preference.setTitle(title);
+ preference.setSummary(summary);
+ preference.setIcon(Utils.getAdaptiveIcon(mContext, icon, Color.WHITE));
+ preference.setFragment(fragment);
+ preference.setIconSize(ICON_SIZE_MEDIUM);
+ preference.setPersistent(false); // Disable SharedPreferences.
+ preference.setOrder(FIRST_PREFERENCE_IN_CATEGORY_INDEX);
+
+ return preference;
+ }
+
+ private void setRestrictedPreferenceEnabled(RestrictedPreference preference,
+ final List permittedServices, boolean serviceEnabled) {
+ // permittedServices null means all accessibility services are allowed.
+ boolean serviceAllowed = permittedServices == null || permittedServices.contains(
+ preference.getPackageName());
+ boolean appOpsAllowed;
+ if (serviceAllowed) {
+ try {
+ final int mode = mAppOps.noteOpNoThrow(
+ AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+ preference.getUid(), preference.getPackageName());
+ appOpsAllowed = mode == AppOpsManager.MODE_ALLOWED;
+ serviceAllowed = appOpsAllowed;
+ } catch (Exception e) {
+ // Allow service in case if app ops is not available in testing.
+ appOpsAllowed = true;
+ }
+ } else {
+ appOpsAllowed = false;
+ }
+ if (serviceAllowed || serviceEnabled) {
+ preference.setEnabled(true);
+ } else {
+ // Disable accessibility service that are not permitted.
+ final RestrictedLockUtils.EnforcedAdmin admin =
+ RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
+ mContext, preference.getPackageName(), UserHandle.myUserId());
+
+ if (admin != null) {
+ preference.setDisabledByAdmin(admin);
+ } else if (!appOpsAllowed) {
+ preference.setDisabledByAppOps(true);
+ } else {
+ preference.setEnabled(false);
+ }
+ }
+ }
+
+ /** Puts the basic extras into {@link RestrictedPreference}'s getExtras(). */
+ private void putBasicExtras(RestrictedPreference preference, String prefKey,
+ CharSequence title, CharSequence intro, CharSequence summary, int imageRes,
+ String htmlDescription, ComponentName componentName) {
+ final Bundle extras = preference.getExtras();
+ extras.putString(AccessibilitySettings.EXTRA_PREFERENCE_KEY, prefKey);
+ extras.putCharSequence(AccessibilitySettings.EXTRA_TITLE, title);
+ extras.putCharSequence(AccessibilitySettings.EXTRA_INTRO, intro);
+ extras.putCharSequence(AccessibilitySettings.EXTRA_SUMMARY, summary);
+ extras.putParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME, componentName);
+ extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, imageRes);
+ extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
+ }
+
+ /**
+ * Puts the service extras into {@link RestrictedPreference}'s getExtras().
+ *
+ * Note: Called by {@link AccessibilityServiceInfo}.
+ *
+ * @param preference The preference we are configuring.
+ * @param resolveInfo The service resolve info.
+ * @param serviceEnabled Whether the accessibility service is enabled.
+ */
+ private void putServiceExtras(RestrictedPreference preference, ResolveInfo resolveInfo,
+ Boolean serviceEnabled) {
+ final Bundle extras = preference.getExtras();
+
+ extras.putParcelable(AccessibilitySettings.EXTRA_RESOLVE_INFO, resolveInfo);
+ extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED, serviceEnabled);
+ }
+
+ /**
+ * Puts the settings extras into {@link RestrictedPreference}'s getExtras().
+ *
+ * Note: Called when settings UI is needed.
+ *
+ * @param preference The preference we are configuring.
+ * @param packageName Package of accessibility feature.
+ * @param settingsClassName The component name of an activity that allows the user to modify
+ * the settings for this accessibility feature.
+ */
+ private void putSettingsExtras(RestrictedPreference preference, String packageName,
+ String settingsClassName) {
+ final Bundle extras = preference.getExtras();
+
+ if (!TextUtils.isEmpty(settingsClassName)) {
+ extras.putString(AccessibilitySettings.EXTRA_SETTINGS_TITLE,
+ mContext.getText(R.string.accessibility_menu_item_settings).toString());
+ extras.putString(AccessibilitySettings.EXTRA_SETTINGS_COMPONENT_NAME,
+ new ComponentName(packageName, settingsClassName).flattenToString());
+ }
+ }
+
+ /**
+ * Puts the information about a particular application
+ * {@link android.service.quicksettings.TileService} into {@link RestrictedPreference}'s
+ * getExtras().
+ *
+ * Note: Called when a tooltip of
+ * {@link android.service.quicksettings.TileService} is needed.
+ *
+ * @param preference The preference we are configuring.
+ * @param packageName Package of accessibility feature.
+ * @param tileServiceClassName The component name of tileService is associated with this
+ * accessibility feature.
+ */
+ private void putTileServiceExtras(RestrictedPreference preference, String packageName,
+ String tileServiceClassName) {
+ final Bundle extras = preference.getExtras();
+ if (!TextUtils.isEmpty(tileServiceClassName)) {
+ extras.putString(AccessibilitySettings.EXTRA_TILE_SERVICE_COMPONENT_NAME,
+ new ComponentName(packageName, tileServiceClassName).flattenToString());
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 91eeace0fd3..c3dc3062bba 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -491,7 +491,8 @@ public class AppStorageSettings extends AppInfoWithHeader
return new AlertDialog.Builder(getActivity())
.setTitle(getActivity().getText(R.string.clear_data_dlg_title))
.setMessage(getActivity().getText(R.string.clear_data_dlg_text))
- .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
+ .setPositiveButton(R.string.dlg_delete,
+ new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Clear user data here
initiateClearUserData();
diff --git a/src/com/android/settings/applications/appinfo/AppLocaleDetails.java b/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
index d50a67b8305..5f75b6b3a6d 100644
--- a/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
+++ b/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
@@ -22,73 +22,64 @@ import android.app.LocaleConfig;
import android.app.LocaleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.Bundle;
import android.os.LocaleList;
-import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.RadioButtonPreference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.Locale;
/**
- * A fragment to show the current app locale info and help the user to select the expected locale.
+ * TODO(b/223503670): Implement the unittest.
+ * A fragment to show the current app locale info.
*/
-public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreference.OnClickListener {
+public class AppLocaleDetails extends SettingsPreferenceFragment {
private static final String TAG = "AppLocaleDetails";
- private static final String CATEGORY_KEY_SUGGESTED_LANGUAGES =
- "category_key_suggested_languages";
- private static final String CATEGORY_KEY_ALL_LANGUAGES =
- "category_key_all_languages";
private static final String KEY_APP_DESCRIPTION = "app_locale_description";
- @VisibleForTesting
- static final String KEY_SYSTEM_DEFAULT_LOCALE = "system_default_locale";
private boolean mCreated = false;
- @VisibleForTesting
- AppLocaleDetailsHelper mAppLocaleDetailsHelper;
-
- private PreferenceGroup mGroupOfSuggestedLocales;
- private PreferenceGroup mGroupOfSupportedLocales;
+ private String mPackageName;
private LayoutPreference mPrefOfDescription;
- private RadioButtonPreference mDefaultPreference;
+
+ /**
+ * Create a instance of AppLocaleDetails.
+ * @param packageName Indicates which application need to show the locale picker.
+ */
+ public static AppLocaleDetails newInstance(String packageName) {
+ AppLocaleDetails appLocaleDetails = new AppLocaleDetails();
+ Bundle bundle = new Bundle();
+ bundle.putString(AppInfoBase.ARG_PACKAGE_NAME, packageName);
+ appLocaleDetails.setArguments(bundle);
+ return appLocaleDetails;
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.app_locale_details);
- mAppLocaleDetailsHelper = new AppLocaleDetailsHelper(getContext(), mPackageName);
+ Bundle bundle = getArguments();
+ mPackageName = bundle.getString(AppInfoBase.ARG_PACKAGE_NAME, "");
- mGroupOfSuggestedLocales =
- getPreferenceScreen().findPreference(CATEGORY_KEY_SUGGESTED_LANGUAGES);
- mGroupOfSupportedLocales =
- getPreferenceScreen().findPreference(CATEGORY_KEY_ALL_LANGUAGES);
- mPrefOfDescription = getPreferenceScreen().findPreference(KEY_APP_DESCRIPTION);
-
- mDefaultPreference = (RadioButtonPreference) getPreferenceScreen()
- .findPreference(KEY_SYSTEM_DEFAULT_LOCALE);
- mDefaultPreference.setOnClickListener(this);
+ if (mPackageName.isEmpty()) {
+ Log.d(TAG, "No package name.");
+ finish();
+ }
}
// Override here so we don't have an empty screen
@@ -96,8 +87,8 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
- // if we don't have a package info, show a page saying this is unsupported
- if (mPackageInfo == null) {
+ // if we don't have a package, show a page saying this is unsupported
+ if (mPackageName.isEmpty()) {
return inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
}
return super.onCreateView(inflater, container, savedInstanceState);
@@ -105,46 +96,19 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen
@Override
public void onResume() {
- // Update Locales first, before refresh ui.
- mAppLocaleDetailsHelper.handleAllLocalesData();
- super.onResume();
- mDefaultPreference.setSummary(Locale.getDefault().getDisplayName(Locale.getDefault()));
- }
-
- @Override
- protected boolean refreshUi() {
refreshUiInternal();
- return true;
+ super.onResume();
}
- @VisibleForTesting
- void refreshUiInternal() {
- if (mAppLocaleDetailsHelper.getSupportedLocales().isEmpty()) {
+ private void refreshUiInternal() {
+ if (!hasAppSupportedLocales()) {
Log.d(TAG, "No supported language.");
- mGroupOfSuggestedLocales.setVisible(false);
- mGroupOfSupportedLocales.setVisible(false);
mPrefOfDescription.setVisible(true);
TextView description = (TextView) mPrefOfDescription.findViewById(R.id.description);
description.setText(getContext().getString(R.string.no_multiple_language_supported,
Locale.getDefault().getDisplayName(Locale.getDefault())));
return;
}
- resetLocalePreferences();
- Locale appLocale = AppLocaleDetailsHelper.getAppDefaultLocale(getContext(), mPackageName);
- // Sets up default locale preference.
- mGroupOfSuggestedLocales.addPreference(mDefaultPreference);
- mDefaultPreference.setChecked(appLocale == null);
- // Sets up suggested locales of per app.
- setLanguagesPreference(mGroupOfSuggestedLocales,
- mAppLocaleDetailsHelper.getSuggestedLocales(), appLocale);
- // Sets up supported locales of per app.
- setLanguagesPreference(mGroupOfSupportedLocales,
- mAppLocaleDetailsHelper.getSupportedLocales(), appLocale);
- }
-
- private void resetLocalePreferences() {
- mGroupOfSuggestedLocales.removeAll();
- mGroupOfSupportedLocales.removeAll();
}
@Override
@@ -152,22 +116,6 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen
return SettingsEnums.APPS_LOCALE_LIST;
}
- @Override
- protected AlertDialog createDialog(int id, int errorCode) {
- return null;
- }
-
- @Override
- public void onRadioButtonClicked(RadioButtonPreference pref) {
- String key = pref.getKey();
- if (KEY_SYSTEM_DEFAULT_LOCALE.equals(key)) {
- mAppLocaleDetailsHelper.setAppDefaultLocale(LocaleList.forLanguageTags(""));
- } else {
- mAppLocaleDetailsHelper.setAppDefaultLocale(key);
- }
- refreshUi();
- }
-
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -176,32 +124,98 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen
return;
}
mCreated = true;
- if (mPackageInfo == null) {
+ if (mPackageName == null) {
return;
}
// Creates a head icon button of app on this page.
final Activity activity = getActivity();
+ ApplicationInfo applicationInfo =
+ getApplicationInfo(mPackageName, getContext().getUserId());
final Preference pref = EntityHeaderController
.newInstance(activity, this, null /* header */)
.setRecyclerView(getListView(), getSettingsLifecycle())
- .setIcon(Utils.getBadgedIcon(getContext(), mPackageInfo.applicationInfo))
- .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
- .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
+ .setIcon(Utils.getBadgedIcon(getContext(), applicationInfo))
+ .setLabel(applicationInfo.loadLabel(getContext().getPackageManager()))
+ .setIsInstantApp(AppUtils.isInstant(applicationInfo))
.setPackageName(mPackageName)
- .setUid(mPackageInfo.applicationInfo.uid)
+ .setUid(applicationInfo.uid)
.setHasAppInfoLink(true)
.setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
.done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref);
}
+ private ApplicationInfo getApplicationInfo(String packageName, int userId) {
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = getContext().getPackageManager()
+ .getApplicationInfoAsUser(packageName, /* flags= */ 0, userId);
+ return applicationInfo;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Application info not found for: " + packageName);
+ return null;
+ }
+ }
+
+ private boolean hasAppSupportedLocales() {
+ LocaleList localeList = getPackageLocales();
+ return (localeList != null && localeList.size() > 0) || getAssetLocales().length > 0;
+ }
+
+ private String[] getAssetLocales() {
+ try {
+ PackageManager packageManager = getContext().getPackageManager();
+ String[] locales = packageManager.getResourcesForApplication(
+ packageManager.getPackageInfo(mPackageName, PackageManager.MATCH_ALL)
+ .applicationInfo).getAssets().getNonSystemLocales();
+ if (locales == null) {
+ Log.i(TAG, "[" + mPackageName + "] locales are null.");
+ }
+ if (locales.length <= 0) {
+ Log.i(TAG, "[" + mPackageName + "] locales length is 0.");
+ return new String[0];
+ }
+ String locale = locales[0];
+ Log.i(TAG, "First asset locale - [" + mPackageName + "] " + locale);
+ return locales;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
+ }
+ return new String[0];
+ }
+
+ private LocaleList getPackageLocales() {
+ try {
+ LocaleConfig localeConfig =
+ new LocaleConfig(getContext().createPackageContext(mPackageName, 0));
+ if (localeConfig.getStatus() == LocaleConfig.STATUS_SUCCESS) {
+ return localeConfig.getSupportedLocales();
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
+ }
+ return null;
+ }
+
+ /** Gets per app's default locale */
+ public static Locale getAppDefaultLocale(Context context, String packageName) {
+ LocaleManager localeManager = context.getSystemService(LocaleManager.class);
+ try {
+ LocaleList localeList = (localeManager == null)
+ ? null : localeManager.getApplicationLocales(packageName);
+ return localeList == null ? null : localeList.get(0);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "package name : " + packageName + " is not correct. " + e);
+ }
+ return null;
+ }
+
/**
* TODO (b209962418) Do a performance test to low end device.
* @return Return the summary to show the current app's language.
*/
public static CharSequence getSummary(Context context, String packageName) {
- Locale appLocale =
- AppLocaleDetailsHelper.getAppDefaultLocale(context, packageName);
+ Locale appLocale = getAppDefaultLocale(context, packageName);
if (appLocale == null) {
Locale systemLocale = Locale.getDefault();
return context.getString(R.string.preference_of_system_locale_summary,
@@ -210,217 +224,4 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen
return appLocale.getDisplayName(appLocale);
}
}
-
- private void setLanguagesPreference(PreferenceGroup group,
- Collection locales, Locale appLocale) {
- if (locales == null) {
- return;
- }
-
- for (Locale locale : locales) {
- if (locale == null) {
- continue;
- }
-
- RadioButtonPreference pref = new RadioButtonPreference(getContext());
- pref.setTitle(locale.getDisplayName(locale));
- pref.setKey(locale.toLanguageTag());
- // Will never be checked if appLocale is null
- // aka if there is no per-app locale
- pref.setChecked(locale.equals(appLocale));
- pref.setOnClickListener(this);
- group.addPreference(pref);
- }
- }
-
- @VisibleForTesting
- static class AppLocaleDetailsHelper {
- private String mPackageName;
- private Context mContext;
- private TelephonyManager mTelephonyManager;
- private LocaleManager mLocaleManager;
-
- private Collection mProcessedSuggestedLocales = new ArrayList<>();
- private Collection mProcessedSupportedLocales = new ArrayList<>();
-
- private Collection mAppSupportedLocales = new ArrayList<>();
-
- AppLocaleDetailsHelper(Context context, String packageName) {
- mContext = context;
- mPackageName = packageName;
- mTelephonyManager = context.getSystemService(TelephonyManager.class);
- mLocaleManager = context.getSystemService(LocaleManager.class);
- mAppSupportedLocales = getAppSupportedLocales();
- }
-
- /** Handle suggested and supported locales for UI display. */
- public void handleAllLocalesData() {
- clearLocalesData();
- handleSuggestedLocales();
- handleSupportedLocales();
- }
-
- /** Gets suggested locales in the app. */
- public Collection getSuggestedLocales() {
- return mProcessedSuggestedLocales;
- }
-
- /** Gets supported locales in the app. */
- public Collection getSupportedLocales() {
- return mProcessedSupportedLocales;
- }
-
- @VisibleForTesting
- void handleSuggestedLocales() {
- Locale appLocale = getAppDefaultLocale(mContext, mPackageName);
- // 1st locale in suggested languages group.
- for (Locale supportedlocale : mAppSupportedLocales) {
- if (compareLocale(supportedlocale, appLocale)) {
- mProcessedSuggestedLocales.add(appLocale);
- break;
- }
- }
-
- // 2nd and 3rd locale in suggested languages group.
- String simCountry = mTelephonyManager.getSimCountryIso().toUpperCase(Locale.US);
- String networkCountry = mTelephonyManager.getNetworkCountryIso().toUpperCase(Locale.US);
- mAppSupportedLocales.forEach(supportedlocale -> {
- String localeCountry = supportedlocale.getCountry().toUpperCase(Locale.US);
- if (!compareLocale(supportedlocale, appLocale)
- && isCountrySuggestedLocale(localeCountry, simCountry, networkCountry)) {
- mProcessedSuggestedLocales.add(supportedlocale);
- }
- });
-
- // Other locales in suggested languages group.
- Collection supportedSystemLocales = new HashSet<>();
- getCurrentSystemLocales().forEach(systemLocale -> {
- mAppSupportedLocales.forEach(supportedLocale -> {
- if (compareLocale(systemLocale, supportedLocale)) {
- supportedSystemLocales.add(supportedLocale);
- }
- });
- });
- supportedSystemLocales.removeAll(mProcessedSuggestedLocales);
- mProcessedSuggestedLocales.addAll(supportedSystemLocales);
- }
-
- @VisibleForTesting
- static boolean compareLocale(Locale source, Locale target) {
- if (source == null && target == null) {
- return true;
- } else if (source != null && target != null) {
- return LocaleList.matchesLanguageAndScript(source, target);
- } else {
- return false;
- }
- }
-
- private static boolean isCountrySuggestedLocale(String localeCountry,
- String simCountry,
- String networkCountry) {
- return ((!simCountry.isEmpty() && simCountry.equals(localeCountry))
- || (!networkCountry.isEmpty() && networkCountry.equals(localeCountry)));
- }
-
- @VisibleForTesting
- void handleSupportedLocales() {
- mProcessedSupportedLocales.addAll(mAppSupportedLocales);
-
- if (mProcessedSuggestedLocales != null || !mProcessedSuggestedLocales.isEmpty()) {
- mProcessedSuggestedLocales.retainAll(mProcessedSupportedLocales);
- mProcessedSupportedLocales.removeAll(mProcessedSuggestedLocales);
- }
- }
-
- private void clearLocalesData() {
- mProcessedSuggestedLocales.clear();
- mProcessedSupportedLocales.clear();
- }
-
- private Collection getAppSupportedLocales() {
- Collection appSupportedLocales = new ArrayList<>();
- LocaleList localeList = getPackageLocales();
-
- if (localeList != null && localeList.size() > 0) {
- for (int i = 0; i < localeList.size(); i++) {
- appSupportedLocales.add(localeList.get(i));
- }
- } else {
- String[] languages = getAssetLocales();
- for (String language : languages) {
- appSupportedLocales.add(Locale.forLanguageTag(language));
- }
- }
- return appSupportedLocales;
- }
-
- /** Gets per app's default locale */
- public static Locale getAppDefaultLocale(Context context, String packageName) {
- LocaleManager localeManager = context.getSystemService(LocaleManager.class);
- try {
- LocaleList localeList = (localeManager == null)
- ? null : localeManager.getApplicationLocales(packageName);
- return localeList == null ? null : localeList.get(0);
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "package name : " + packageName + " is not correct. " + e);
- }
- return null;
- }
-
- /** Sets per app's default language to system. */
- public void setAppDefaultLocale(String languageTag) {
- if (languageTag.isEmpty()) {
- Log.w(TAG, "[setAppDefaultLocale] No language tag.");
- return;
- }
- setAppDefaultLocale(LocaleList.forLanguageTags(languageTag));
- }
-
- /** Sets per app's default language to system. */
- public void setAppDefaultLocale(LocaleList localeList) {
- if (mLocaleManager == null) {
- Log.w(TAG, "LocaleManager is null, and cannot set the app locale up.");
- return;
- }
- mLocaleManager.setApplicationLocales(mPackageName, localeList);
- }
-
- @VisibleForTesting
- Collection getCurrentSystemLocales() {
- LocaleList localeList = Resources.getSystem().getConfiguration().getLocales();
- Collection systemLocales = new ArrayList<>();
- for (int i = 0; i < localeList.size(); i++) {
- systemLocales.add(localeList.get(i));
- }
- return systemLocales;
- }
-
- @VisibleForTesting
- String[] getAssetLocales() {
- try {
- PackageManager packageManager = mContext.getPackageManager();
- return packageManager.getResourcesForApplication(
- packageManager.getPackageInfo(mPackageName, PackageManager.MATCH_ALL)
- .applicationInfo).getAssets().getNonSystemLocales();
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
- }
- return new String[0];
- }
-
- @VisibleForTesting
- LocaleList getPackageLocales() {
- try {
- LocaleConfig localeConfig =
- new LocaleConfig(mContext.createPackageContext(mPackageName, 0));
- if (localeConfig.getStatus() == LocaleConfig.STATUS_SUCCESS) {
- return localeConfig.getSupportedLocales();
- }
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
- }
- return null;
- }
- }
}
diff --git a/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java
index eaa2ec00d76..38e655c7fc6 100644
--- a/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java
@@ -17,14 +17,20 @@
package com.android.settings.applications.appinfo;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.text.TextUtils;
import android.util.FeatureFlagUtils;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppLocaleUtil;
+import com.android.settings.localepicker.AppLocalePickerActivity;
import java.util.List;
@@ -59,6 +65,23 @@ public class AppLocalePreferenceController extends AppInfoPreferenceControllerBa
return AppLocaleDetails.getSummary(mContext, mParent.getAppEntry().info.packageName);
}
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), mPreferenceKey)) {
+ return false;
+ }
+
+ if (mParent != null) {
+ Intent intent = new Intent(mContext, AppLocalePickerActivity.class);
+ intent.setData(Uri.parse("package:" + mParent.getAppEntry().info.packageName));
+ mContext.startActivity(intent);
+ return true;
+ } else {
+ Log.d(TAG, "mParent is null");
+ return false;
+ }
+ }
+
@VisibleForTesting
boolean canDisplayLocaleUi() {
return AppLocaleUtil
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 4d598396420..22a4ea74606 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -120,6 +120,7 @@ import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.fuelgauge.HighPowerDetail;
+import com.android.settings.localepicker.AppLocalePickerActivity;
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.app.AppNotificationSettings;
@@ -635,8 +636,9 @@ public class ManageApplications extends InstrumentedFragment
R.string.media_management_apps_title);
break;
case LIST_TYPE_APPS_LOCALE:
- startAppInfoFragment(AppLocaleDetails.class,
- R.string.app_locale_picker_title);
+ Intent intent = new Intent(getContext(), AppLocalePickerActivity.class);
+ intent.setData(Uri.parse("package:" + mCurrentPkgName));
+ startActivity(intent);
break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index dfb4a347ec0..67e4a63b30e 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -380,7 +380,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
break;
case STAGE_LEFT_EDGE:
- setHeaderText(R.string.security_settings_udfps_enroll_edge_title);
+ setHeaderText(R.string.security_settings_udfps_enroll_left_edge_title);
if (!mHaveShownUdfpsLeftEdgeLottie && mIllustrationLottie != null) {
mHaveShownUdfpsLeftEdgeLottie = true;
setDescriptionText("");
@@ -399,7 +399,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
break;
case STAGE_RIGHT_EDGE:
- setHeaderText(R.string.security_settings_udfps_enroll_edge_title);
+ setHeaderText(R.string.security_settings_udfps_enroll_right_edge_title);
if (!mHaveShownUdfpsRightEdgeLottie && mIllustrationLottie != null) {
mHaveShownUdfpsRightEdgeLottie = true;
setDescriptionText("");
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 82b76c3e33d..6fe14e6a9cd 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -91,10 +91,12 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
final TextView footerMessage3 = findViewById(R.id.footer_message_3);
final TextView footerMessage4 = findViewById(R.id.footer_message_4);
final TextView footerMessage5 = findViewById(R.id.footer_message_5);
+ final TextView footerMessage6 = findViewById(R.id.footer_message_6);
footerMessage2.setText(getFooterMessage2());
footerMessage3.setText(getFooterMessage3());
footerMessage4.setText(getFooterMessage4());
footerMessage5.setText(getFooterMessage5());
+ footerMessage6.setText(getFooterMessage6());
final TextView footerTitle1 = findViewById(R.id.footer_title_1);
final TextView footerTitle2 = findViewById(R.id.footer_title_2);
@@ -163,6 +165,11 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
return R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_5;
}
+ @StringRes
+ protected int getFooterMessage6() {
+ return R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_6;
+ }
+
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java
index 22212f27d83..c33ae175a09 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java
@@ -44,7 +44,8 @@ public class FingerprintEnrollParentalConsent extends FingerprintEnrollIntroduct
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_2,
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_3,
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_4,
- R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_5
+ R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_5,
+ R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_6
};
@Override
@@ -116,6 +117,11 @@ public class FingerprintEnrollParentalConsent extends FingerprintEnrollIntroduct
return R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_5;
}
+ @StringRes
+ protected int getFooterMessage6() {
+ return R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_6;
+ }
+
@Override
protected int getHeaderResDefault() {
return R.string.security_settings_fingerprint_enroll_consent_introduction_title;
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index bff8226910e..256a6201cb7 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -27,6 +27,7 @@ import android.util.Log;
import androidx.annotation.CallSuper;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LifecycleObserver;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
@@ -43,7 +44,6 @@ import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.ProviderTile;
import com.android.settingslib.drawer.Tile;
diff --git a/src/com/android/settings/localepicker/AppLocalePickerActivity.java b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
new file mode 100644
index 00000000000..b3c56eacddc
--- /dev/null
+++ b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.localepicker;
+
+import android.app.FragmentTransaction;
+import android.app.LocaleManager;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.MenuItem;
+
+import com.android.internal.app.LocalePickerWithRegion;
+import com.android.internal.app.LocaleStore;
+import com.android.settings.R;
+import com.android.settings.applications.appinfo.AppLocaleDetails;
+import com.android.settings.core.SettingsBaseActivity;
+
+/**
+ * TODO(b/223503670): Add unit test for AppLocalePickerActivity.
+ * A activity to show the locale picker and information page.
+ */
+public class AppLocalePickerActivity extends SettingsBaseActivity
+ implements LocalePickerWithRegion.LocaleSelectedListener {
+ private static final String TAG = AppLocalePickerActivity.class.getSimpleName();
+
+ private String mPackageName;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mPackageName = getIntent().getData().getSchemeSpecificPart();
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.d(TAG, "There is no package name.");
+ finish();
+ return;
+ }
+
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ setContentView(R.layout.app_locale_picker);
+
+ // Create App locale info detail part.
+ AppLocaleDetails appLocaleDetails = AppLocaleDetails.newInstance(mPackageName);
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.app_locale_detail, appLocaleDetails)
+ .commit();
+
+ // Create Locale picker part.
+ final LocalePickerWithRegion selector = LocalePickerWithRegion.createLanguagePicker(
+ this, AppLocalePickerActivity.this, false /* translate only */);
+ // LocalePickerWithRegion use android.app.ListFragment. Thus, it can not user
+ // getSupportFragmentManager() to add this into container.
+ getFragmentManager()
+ .beginTransaction()
+ .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+ .replace(R.id.app_locale_picker_with_region, selector)
+ .commit();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ handleBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onBackPressed() {
+ handleBackPressed();
+ }
+
+ private void handleBackPressed() {
+ if (getFragmentManager().getBackStackEntryCount() > 1) {
+ super.onBackPressed();
+ } else {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ @Override
+ public void onLocaleSelected(LocaleStore.LocaleInfo localeInfo) {
+ if (localeInfo == null || localeInfo.getLocale() == null || localeInfo.isSystemLocale()) {
+ setAppDefaultLocale("");
+ } else {
+ setAppDefaultLocale(localeInfo.getLocale().getLanguage());
+ }
+ finish();
+ }
+
+ /** Sets the app's locale to the supplied language tag */
+ private void setAppDefaultLocale(String languageTag) {
+ LocaleManager localeManager = getSystemService(LocaleManager.class);
+ if (localeManager == null) {
+ Log.w(TAG, "LocaleManager is null, cannot set default app locale");
+ return;
+ }
+ localeManager.setApplicationLocales(mPackageName, LocaleList.forLanguageTags(languageTag));
+ }
+}
+
diff --git a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
index bcc55e3a2db..70f738395be 100644
--- a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
+++ b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
@@ -17,8 +17,11 @@
package com.android.settings.localepicker;
import android.app.FragmentTransaction;
+import android.app.LocaleManager;
import android.content.Intent;
import android.os.Bundle;
+import android.os.LocaleList;
+import android.util.Log;
import android.view.MenuItem;
import com.android.internal.app.LocalePickerWithRegion;
@@ -31,6 +34,7 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
implements LocalePickerWithRegion.LocaleSelectedListener {
private static final String PARENT_FRAGMENT_NAME = "localeListEditor";
+ private static final String TAG = "Calvin";
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -47,6 +51,25 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
.commit();
}
+ public void setAppDefaultLocale(String languageTag) {
+ if (languageTag.isEmpty()) {
+ Log.w(TAG, "[setAppDefaultLocale] No language tag.");
+ return;
+ }
+ setAppDefaultLocale(LocaleList.forLanguageTags(languageTag));
+ }
+
+ /** Sets per app's default language to system. */
+ public void setAppDefaultLocale(LocaleList localeList) {
+ LocaleManager mLocaleManager = getSystemService(LocaleManager.class);
+ if (mLocaleManager == null) {
+ Log.w(TAG, "LocaleManager is null, and cannot set the app locale up.");
+ return;
+ }
+ mLocaleManager.setApplicationLocales("com.android.vending", localeList);
+ }
+
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
@@ -58,9 +81,16 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
@Override
public void onLocaleSelected(LocaleStore.LocaleInfo locale) {
- final Intent intent = new Intent();
+ /*final Intent intent = new Intent();
intent.putExtra(LocaleListEditor.INTENT_LOCALE_KEY, locale);
- setResult(RESULT_OK, intent);
+ setResult(RESULT_OK, intent);*/
+ if(locale != null) {
+ Log.d("Calvin", "onLocaleSelected " + locale.getLocale().toLanguageTag());
+ setAppDefaultLocale(locale.getLocale().toLanguageTag());
+ } else {
+ Log.d("Calvin", "onLocaleSelected null");
+ setAppDefaultLocale("");
+ }
finish();
}
diff --git a/src/com/android/settings/network/telephony/ProgressDialogFragment.java b/src/com/android/settings/network/telephony/ProgressDialogFragment.java
index 0d1b65716db..29f269b8566 100644
--- a/src/com/android/settings/network/telephony/ProgressDialogFragment.java
+++ b/src/com/android/settings/network/telephony/ProgressDialogFragment.java
@@ -26,6 +26,8 @@ import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
+import com.android.settings.R;
+
/** Fragment to show a progress dialog. */
public class ProgressDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
@@ -83,6 +85,7 @@ public class ProgressDialogFragment extends DialogFragment {
@SuppressWarnings("deprecation") // ProgressDialog is deprecated but is intended UX for now
public Dialog onCreateDialog(Bundle savedInstanceState) {
ProgressDialog dialog = new ProgressDialog(getActivity());
+ dialog.getWindow().setBackgroundDrawableResource(R.drawable.sim_progress_dialog_rounded_bg);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.setMessage(getArguments().getString(ARG_TITLE));
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index cc2986d5344..2616a69ba1d 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -217,19 +217,17 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
}
case DIALOG_TAG_ENABLE_SIM_CONFIRMATION:
Log.i(TAG, "User confirmed to enable the subscription.");
+ showProgressDialog(
+ getString(
+ R.string.sim_action_switch_sub_dialog_progress,
+ SubscriptionUtil.getUniqueSubscriptionDisplayName(
+ mSubInfo, this)));
if (mIsEsimOperation) {
- showProgressDialog(
- getString(
- R.string.sim_action_switch_sub_dialog_progress,
- SubscriptionUtil.getUniqueSubscriptionDisplayName(
- mSubInfo, this)));
mSwitchToEuiccSubscriptionSidecar.run(mSubInfo.getSubscriptionId(),
UiccSlotUtil.INVALID_PORT_ID,
removedSubInfo);
return;
}
- showProgressDialog(
- getString(R.string.sim_action_enabling_sim_without_carrier_name));
mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID,
removedSubInfo);
break;
diff --git a/src/com/android/settings/nfc/DefaultPaymentSettings.java b/src/com/android/settings/nfc/DefaultPaymentSettings.java
index 08b843d48f5..5224d92fb4e 100644
--- a/src/com/android/settings/nfc/DefaultPaymentSettings.java
+++ b/src/com/android/settings/nfc/DefaultPaymentSettings.java
@@ -29,13 +29,9 @@ import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AlignmentSpan;
import android.text.style.BulletSpan;
-import android.text.style.ClickableSpan;
import android.text.style.RelativeSizeSpan;
-import android.view.View;
-import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
@@ -58,7 +54,7 @@ public class DefaultPaymentSettings extends DefaultAppPickerFragment {
private PaymentBackend mPaymentBackend;
private List mAppInfos;
- private Preference mFooterPreference;
+ private FooterPreference mFooterPreference;
@Override
public int getMetricsCategory() {
@@ -249,31 +245,12 @@ public class DefaultPaymentSettings extends DefaultAppPickerFragment {
}
private void setupFooterPreference() {
- final String textNfcDefaultPaymentFooter = getResources().getString(
- R.string.nfc_default_payment_footer);
- final String textMoreDetails = getResources().getString(R.string.nfc_more_details);
-
- final SpannableString spannableString = new SpannableString(
- textNfcDefaultPaymentFooter + System.lineSeparator()
- + System.lineSeparator() + textMoreDetails);
- final ClickableSpan clickableSpan = new ClickableSpan() {
- @Override
- public void onClick(@NonNull View widget) {
- Intent howItWorksIntent = new Intent(getActivity(), HowItWorks.class);
- startActivity(howItWorksIntent);
- }
- };
-
- if (textNfcDefaultPaymentFooter != null && textMoreDetails != null) {
- spannableString.setSpan(clickableSpan, textNfcDefaultPaymentFooter.length() + 1,
- textNfcDefaultPaymentFooter.length() + textMoreDetails.length() + 2,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
mFooterPreference = new FooterPreference(getContext());
- mFooterPreference.setLayoutResource(R.layout.preference_footer);
- mFooterPreference.setTitle(spannableString);
- mFooterPreference.setSelectable(false);
+ mFooterPreference.setTitle(getResources().getString(R.string.nfc_default_payment_footer));
mFooterPreference.setIcon(R.drawable.ic_info_outline_24dp);
+ mFooterPreference.setLearnMoreAction(v -> {
+ final Intent howItWorksIntent = new Intent(getActivity(), HowItWorks.class);
+ getContext().startActivity(howItWorksIntent);
+ });
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index c1950be2506..7c52754765f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -87,8 +87,6 @@ public class AccessibilitySettingsTest {
private static final String PACKAGE_NAME = "com.android.test";
private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service";
private static final ComponentName COMPONENT_NAME = new ComponentName(PACKAGE_NAME, CLASS_NAME);
- private static final int ON = 1;
- private static final int OFF = 0;
private static final String EMPTY_STRING = "";
private static final String DEFAULT_SUMMARY = "default summary";
private static final String DEFAULT_DESCRIPTION = "default description";
@@ -246,37 +244,6 @@ public class AccessibilitySettingsTest {
assertThat(description).isEqualTo(DEFAULT_DESCRIPTION);
}
- @Test
- public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
- final String key = COMPONENT_NAME.flattenToString();
- final AccessibilitySettings.RestrictedPreferenceHelper helper =
- new AccessibilitySettings.RestrictedPreferenceHelper(mContext);
- final List infoList = new ArrayList<>(
- singletonList(mServiceInfo));
-
- final List preferenceList =
- helper.createAccessibilityServicePreferenceList(infoList);
- RestrictedPreference preference = preferenceList.get(0);
-
- assertThat(preference.getKey()).isEqualTo(key);
- }
-
- @Test
- public void createAccessibilityActivityPreferenceList_hasOneInfo_containsSameKey() {
- final String key = COMPONENT_NAME.flattenToString();
- final AccessibilitySettings.RestrictedPreferenceHelper helper =
- new AccessibilitySettings.RestrictedPreferenceHelper(mContext);
- setMockAccessibilityShortcutInfo(mShortcutInfo);
- final List infoList = new ArrayList<>(
- singletonList(mShortcutInfo));
-
- final List preferenceList =
- helper.createAccessibilityActivityPreferenceList(infoList);
- RestrictedPreference preference = preferenceList.get(0);
-
- assertThat(preference.getKey()).isEqualTo(key);
- }
-
@Test
@Config(shadows = {ShadowFragment.class, ShadowUserManager.class})
public void onCreate_haveRegisterToSpecificUrisAndActions() {
diff --git a/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java b/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java
new file mode 100644
index 00000000000..99a78cfc408
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import static java.util.Collections.singletonList;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityShortcutInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.RestrictedPreference;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Test for {@link RestrictedPreferenceHelper}. */
+@RunWith(RobolectricTestRunner.class)
+public class RestrictedPreferenceHelperTest {
+
+ private static final String PACKAGE_NAME = "com.android.test";
+ private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service";
+ private static final ComponentName COMPONENT_NAME = new ComponentName(PACKAGE_NAME, CLASS_NAME);
+ private static final String DEFAULT_SUMMARY = "default summary";
+ private static final String DEFAULT_DESCRIPTION = "default description";
+ private static final String DEFAULT_LABEL = "default label";
+
+ @Rule
+ public final MockitoRule mocks = MockitoJUnit.rule();
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ @Spy
+ private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
+ PACKAGE_NAME, CLASS_NAME);
+ @Mock
+ private AccessibilityShortcutInfo mShortcutInfo;
+ private final RestrictedPreferenceHelper mHelper = new RestrictedPreferenceHelper(mContext);
+
+ @Test
+ public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
+ final String key = COMPONENT_NAME.flattenToString();
+ final List infoList = new ArrayList<>(
+ singletonList(mServiceInfo));
+
+ final List preferenceList =
+ mHelper.createAccessibilityServicePreferenceList(infoList);
+ final RestrictedPreference preference = preferenceList.get(0);
+
+ assertThat(preference.getKey()).isEqualTo(key);
+ }
+
+ @Test
+ public void createAccessibilityActivityPreferenceList_hasOneInfo_containsSameKey() {
+ final String key = COMPONENT_NAME.flattenToString();
+ setMockAccessibilityShortcutInfo(mShortcutInfo);
+ final List infoList = new ArrayList<>(
+ singletonList(mShortcutInfo));
+
+ final List preferenceList =
+ mHelper.createAccessibilityActivityPreferenceList(infoList);
+ final RestrictedPreference preference = preferenceList.get(0);
+
+ assertThat(preference.getKey()).isEqualTo(key);
+ }
+
+ private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName,
+ String className) {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ final ServiceInfo serviceInfo = new ServiceInfo();
+ applicationInfo.packageName = packageName;
+ serviceInfo.packageName = packageName;
+ serviceInfo.name = className;
+ serviceInfo.applicationInfo = applicationInfo;
+
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.serviceInfo = serviceInfo;
+ try {
+ final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
+ mContext);
+ info.setComponentName(new ComponentName(packageName, className));
+ return info;
+ } catch (XmlPullParserException | IOException e) {
+ // Do nothing
+ }
+ return null;
+ }
+
+ private void setMockAccessibilityShortcutInfo(AccessibilityShortcutInfo mockInfo) {
+ final ActivityInfo activityInfo = Mockito.mock(ActivityInfo.class);
+ activityInfo.applicationInfo = new ApplicationInfo();
+ when(mockInfo.getActivityInfo()).thenReturn(activityInfo);
+ when(activityInfo.loadLabel(any())).thenReturn(DEFAULT_LABEL);
+ when(mockInfo.loadSummary(any())).thenReturn(DEFAULT_SUMMARY);
+ when(mockInfo.loadDescription(any())).thenReturn(DEFAULT_DESCRIPTION);
+ when(mockInfo.getComponentName()).thenReturn(COMPONENT_NAME);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java b/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
deleted file mode 100644
index aa0daad44ff..00000000000
--- a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2021 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.applications.appinfo;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.LocaleManager;
-import android.content.Context;
-import android.os.LocaleList;
-import android.os.Looper;
-import android.telephony.TelephonyManager;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settingslib.widget.RadioButtonPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Unittest for ApplocaleDetails
- * TODO Need to add a unittest for the UI preference component.
- */
-@RunWith(AndroidJUnit4.class)
-public class AppLocaleDetailsTest {
- private static final String APP_PACKAGE_NAME = "app_package_name";
-
- @Mock
- private TelephonyManager mTelephonyManager;
- @Mock
- private LocaleManager mLocaleManager;
-
- private Context mContext;
- private Collection mSystemLocales;
- private LocaleList mAppLocale;
- private String[] mAssetLocales;
- private LocaleList mPackageLocales;
-
- @Before
- @UiThreadTest
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- mContext = spy(ApplicationProvider.getApplicationContext());
- when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
- when(mContext.getSystemService(LocaleManager.class)).thenReturn(mLocaleManager);
-
- setupInitialLocales(
- /* appLocale= */ "en-gb",
- /* simCountry= */ "tw",
- /* networkCountry= */ "jp",
- /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw",
- /* packageLocales= */ "pa, cn, zh-tw, en-gb, ja-jp",
- /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "zh-tw", "ja-jp"});
- }
-
- @Test
- @UiThreadTest
- public void onRadioButtonClicked_setCurrentLocaleToSystem() {
- AppLocaleDetails appLocaleDetails = new AppLocaleDetails() {
- @Override
- void refreshUiInternal() {}
- };
- DummyAppLocaleDetailsHelper helper =
- spy(new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME));
- appLocaleDetails.mAppLocaleDetailsHelper = helper;
- RadioButtonPreference pref = new RadioButtonPreference(mContext);
- pref.setKey(AppLocaleDetails.KEY_SYSTEM_DEFAULT_LOCALE);
-
- appLocaleDetails.onRadioButtonClicked(pref);
-
- verify(helper).setAppDefaultLocale(LocaleList.forLanguageTags(""));
- }
-
- @Test
- @UiThreadTest
- public void onRadioButtonClicked_setCurrentLocaleForUserSelected() {
- AppLocaleDetails appLocaleDetails = new AppLocaleDetails() {
- @Override
- void refreshUiInternal() {}
- };
- DummyAppLocaleDetailsHelper helper =
- spy(new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME));
- appLocaleDetails.mAppLocaleDetailsHelper = helper;
- RadioButtonPreference pref = new RadioButtonPreference(mContext);
- pref.setKey("en");
-
- appLocaleDetails.onRadioButtonClicked(pref);
-
- verify(helper).setAppDefaultLocale("en");
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_localeManagerIsNull_noCrash() {
- when(mContext.getSystemService(LocaleManager.class)).thenReturn(null);
-
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_1stLocaleIsAppLocaleAndHasSimAndNetwork() {
- Locale simCountryLocale = new Locale("zh", "TW");
- Locale networkCountryLocale = new Locale("ja", "JP");
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- Locale locale = suggestedLocales.iterator().next();
- assertTrue(locale.equals(mAppLocale.get(0)));
- assertTrue(suggestedLocales.contains(simCountryLocale));
- assertTrue(suggestedLocales.contains(networkCountryLocale));
- }
-
- @Test
- @UiThreadTest
- public void
- handleAllLocalesData_noAppAndNoSupportedSimLocale_suggestedLocaleIsSupported() {
- Locale testEnAssetLocale = new Locale("en", "GB");
- Locale testJaAssetLocale = new Locale("ja", "JP");
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "tw",
- /* networkCountry= */ "",
- /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw",
- /* packageLocales= */ "",
- /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "ja-jp"});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- assertTrue(suggestedLocales.contains(testEnAssetLocale));
- assertTrue(suggestedLocales.contains(testJaAssetLocale));
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_noAppButHasSupportedSimLocale_1stSuggestedLocaleIsSim() {
- Locale simLocale = new Locale("zh", "tw");
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "tw",
- /* networkCountry= */ "",
- /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw",
- /* packageLocales= */ "",
- /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "ja-jp", "zh-tw"});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- Locale locale = suggestedLocales.iterator().next();
- assertTrue(locale.equals(simLocale));
- }
-
- @Test
- @UiThreadTest
- public void
- handleAllLocalesData_noAppButHasSupportedNetworkLocale_1stSuggestedLocaleIsNetwork() {
- Locale networkLocale = new Locale("ja", "JP");
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "",
- /* networkCountry= */ "jp",
- /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw",
- /* packageLocales= */ "",
- /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "ja-jp"});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- Locale locale = suggestedLocales.iterator().next();
- assertTrue(locale.equals(networkLocale));
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_noAppSimOrNetworkLocale_suggestedLocalesHasSystemLocale() {
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "",
- /* networkCountry= */ "",
- /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw",
- /* packageLocales= */ "",
- /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "zh-tw", "ja-jp"});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- assertTrue(suggestedLocales.contains(Locale.forLanguageTag("ne")));
- // ru language is not present in the asset locales
- assertFalse(suggestedLocales.contains(Locale.forLanguageTag("ru")));
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_noAppButHasSimAndNetworkLocale_1stLocaleIsSimLocale() {
- Locale simCountryLocale = new Locale("zh", "TW");
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "tw",
- /* networkCountry= */ "jp",
- /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw",
- /* packageLocales= */ "",
- /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "zh-tw", "ja-jp"});
-
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- Locale locale = suggestedLocales.iterator().next();
- assertTrue(locale.equals(simCountryLocale));
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_noSupportedLocale_noSuggestedLocales() {
- Locale networkCountryLocale = new Locale("en", "GB");
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "",
- /* networkCountry= */ "gb",
- /* systemLocales= */ "en, uk, jp, ne",
- /* packageLocales= */ "",
- /* assetLocales= */ new String[]{});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- assertTrue(suggestedLocales.size() == 0);
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_hasPackageAndSystemLocales_1stLocaleIs1stOneInSystemLocales() {
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "",
- /* networkCountry= */ "",
- /* systemLocales= */ "en, uk, jp, ne",
- /* packageLocales= */ "pa, cn, tw, en",
- /* assetLocales= */ new String[]{});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- Locale locale = suggestedLocales.iterator().next();
- Locale systemLocale = mSystemLocales.iterator().next();
- assertTrue(locale.equals(systemLocale));
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_sameLocaleButDifferentRegion_notShowDuplicatedLocale() {
- setupInitialLocales(
- /* appLocale= */ "",
- /* simCountry= */ "",
- /* networkCountry= */ "",
- /* systemLocales= */ "en-us, en-gb, jp, ne",
- /* packageLocales= */ "pa, cn, tw, en-us, en-gb",
- /* assetLocales= */ new String[]{});
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- Collection suggestedLocales = helper.getSuggestedLocales();
- assertFalse(hasDuplicatedResult(suggestedLocales));
- }
-
- private boolean hasDuplicatedResult(Collection locales) {
- Set tempSet = new HashSet<>();
- for (Locale locale : locales) {
- if (!tempSet.add(locale)) {
- return true;
- }
- }
- return false;
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_supportLocaleListIsNotEmpty() {
- DummyAppLocaleDetailsHelper helper =
- new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
-
- helper.handleAllLocalesData();
-
- assertFalse(helper.getSupportedLocales().isEmpty());
- }
-
- @Test
- @UiThreadTest
- public void handleAllLocalesData_compareLocale() {
- //Use LocaleList.matchScore() to compare two locales.
- assertTrue(DummyAppLocaleDetailsHelper.compareLocale(Locale.forLanguageTag("en-US"),
- Locale.forLanguageTag("en-CA")));
- assertTrue(DummyAppLocaleDetailsHelper.compareLocale(Locale.forLanguageTag("zh-CN"),
- Locale.forLanguageTag("zh")));
- assertTrue(DummyAppLocaleDetailsHelper.compareLocale(Locale.forLanguageTag("zh-CN"),
- Locale.forLanguageTag("zh-Hans")));
- assertTrue(DummyAppLocaleDetailsHelper.compareLocale(Locale.forLanguageTag("zh-TW"),
- Locale.forLanguageTag("zh-Hant")));
-
- //Use Locale.equals() to compare two locales.
- assertFalse(Locale.forLanguageTag("en-US").equals(Locale.forLanguageTag("en-CA")));
- assertFalse(Locale.forLanguageTag("zh-CN").equals(Locale.forLanguageTag("zh")));
- assertFalse(Locale.forLanguageTag("zh-CN").equals(Locale.forLanguageTag("zh-Hans")));
- assertFalse(Locale.forLanguageTag("zh-TW").equals(Locale.forLanguageTag("zh-Hant")));
- }
-
- /**
- * Sets the initial Locale data
- *
- * @param appLocale Application locale, it shall be a language tag.
- * example: "en"
- *
- * @param simCountry The ISO-3166-1 alpha-2 country code equivalent for the SIM
- * provider's country code.
- * example: "us"
- *
- * @param networkCountry The ISO-3166-1 alpha-2 country code equivalent of the MCC
- * (Mobile Country Code) of the current registered operato
- * or the cell nearby.
- * example: "us"
- *
- * @param systemLocales System locales, a locale list by a multiple language tags with comma.
- * example: "en, uk, jp"
- *
- * @param packageLocales PackageManager locales, a locale list by a multiple language tags with
- * comma.
- * example: "en, uk, jp"
- *
- * @param assetLocales Asset locales, a locale list by a multiple language tags with String
- * array.
- * example: new String[] {"en", "ne", "ms", "pa"}
- */
- private void setupInitialLocales(String appLocale,
- String simCountry,
- String networkCountry,
- String systemLocales,
- String packageLocales,
- String[] assetLocales) {
- mAppLocale = LocaleList.forLanguageTags(appLocale);
- // forLanguageTags does not filter space to the input string. If there is any space included
- // in string, this will make locale fail to generate.
- systemLocales = systemLocales.replaceAll("\\s+", "");
- LocaleList listOfSystemLocales = LocaleList.forLanguageTags(systemLocales);
- mSystemLocales = new ArrayList<>();
- for (int i = 0; i < listOfSystemLocales.size(); i++) {
- mSystemLocales.add(listOfSystemLocales.get(i));
- }
- mAssetLocales = assetLocales;
- packageLocales = packageLocales.replaceAll("\\s+", "");
- mPackageLocales = LocaleList.forLanguageTags(packageLocales);
- when(mTelephonyManager.getSimCountryIso()).thenReturn(simCountry);
- when(mTelephonyManager.getNetworkCountryIso()).thenReturn(networkCountry);
- when(mLocaleManager.getApplicationLocales(anyString())).thenReturn(mAppLocale);
- }
-
- public class DummyAppLocaleDetailsHelper
- extends AppLocaleDetails.AppLocaleDetailsHelper {
-
- DummyAppLocaleDetailsHelper(Context context, String packageName) {
- super(context, packageName);
- }
-
- @Override
- String[] getAssetLocales() {
- return mAssetLocales;
- }
-
- @Override
- Collection getCurrentSystemLocales() {
- return mSystemLocales;
- }
-
- @Override
- LocaleList getPackageLocales() {
- return mPackageLocales;
- }
- }
-}