Home | History | Annotate | Download | only in system
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.car.settings.system;
     18 
     19 import android.arch.lifecycle.LiveData;
     20 import android.arch.lifecycle.MutableLiveData;
     21 import android.arch.lifecycle.ViewModel;
     22 import android.arch.lifecycle.ViewModelProviders;
     23 import android.content.Context;
     24 import android.content.res.Configuration;
     25 import android.content.res.Resources;
     26 import android.os.AsyncTask;
     27 import android.os.Build;
     28 import android.os.Bundle;
     29 
     30 import androidx.car.widget.ListItemProvider;
     31 
     32 import com.android.car.settings.R;
     33 import com.android.car.settings.common.ListItemSettingsFragment;
     34 import com.android.car.settingslib.language.LanguagePickerUtils;
     35 import com.android.car.settingslib.language.LocaleListItemProvider;
     36 import com.android.car.settingslib.language.LocaleSelectionListener;
     37 import com.android.internal.app.LocalePicker;
     38 import com.android.internal.app.LocaleStore;
     39 
     40 import java.util.HashSet;
     41 import java.util.Locale;
     42 import java.util.Set;
     43 
     44 /**
     45  * Fragment for showing the list of languages.
     46  */
     47 public class LanguagePickerFragment extends ListItemSettingsFragment implements
     48         LocaleSelectionListener {
     49 
     50     private LocaleListItemProvider mLocaleListItemProvider;
     51     private final HashSet<String> mLangTagsToIgnore = new HashSet<>();
     52 
     53     /**
     54      * Factory method for creating LanguagePickerFragment.
     55      */
     56     public static LanguagePickerFragment newInstance() {
     57         LanguagePickerFragment LanguagePickerFragment = new LanguagePickerFragment();
     58         Bundle bundle = ListItemSettingsFragment.getBundle();
     59         bundle.putInt(EXTRA_TITLE_ID, R.string.language_settings);
     60         bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar);
     61         LanguagePickerFragment.setArguments(bundle);
     62         return LanguagePickerFragment;
     63     }
     64 
     65     @Override
     66     public void onActivityCreated(Bundle savedInstanceState) {
     67         super.onActivityCreated(savedInstanceState);
     68 
     69         LocaleViewModel viewModel = getLocaleViewModel();
     70         viewModel.getLocaleInfos(getContext(), mLangTagsToIgnore).observe(this,
     71                 localeInfos -> resetLocaleList(localeInfos));
     72     }
     73 
     74     @Override
     75     public ListItemProvider getItemProvider() {
     76         if (mLocaleListItemProvider == null) {
     77             mLocaleListItemProvider = new LocaleListItemProvider(
     78                     getContext(),
     79                     new HashSet<LocaleStore.LocaleInfo>(),
     80                     /* localeSelectionListener= */ this,
     81                     mLangTagsToIgnore);
     82         }
     83         return mLocaleListItemProvider;
     84     }
     85 
     86     @Override
     87     public void onLocaleSelected(LocaleStore.LocaleInfo localeInfo) {
     88         if (localeInfo == null || localeInfo.getLocale() == null) {
     89             return;
     90         }
     91 
     92         Locale locale = localeInfo.getLocale();
     93 
     94         Resources res = getResources();
     95         Configuration baseConfig = res.getConfiguration();
     96         Configuration config = new Configuration(baseConfig);
     97         config.setLocale(locale);
     98         res.updateConfiguration(config, null);
     99 
    100         // Apply locale to system.
    101         LocalePicker.updateLocale(locale);
    102         getFragmentController().goBack();
    103     }
    104 
    105     @Override
    106     public void onParentWithChildrenLocaleSelected(LocaleStore.LocaleInfo localeInfo) {
    107         if (localeInfo != null) {
    108             setTitle(localeInfo.getFullNameNative());
    109             refreshList();
    110         }
    111     }
    112 
    113     @Override
    114     protected void onBackPressed() {
    115         if (isChildLocaleDisplayed()) {
    116             setTitle(getString(R.string.language_settings));
    117             getLocaleViewModel().reloadLocales(getContext(), mLangTagsToIgnore);
    118         } else {
    119             super.onBackPressed();
    120         }
    121     }
    122 
    123     private LocaleViewModel getLocaleViewModel() {
    124         return ViewModelProviders.of(this).get(LocaleViewModel.class);
    125     }
    126 
    127     private boolean isChildLocaleDisplayed() {
    128         return mLocaleListItemProvider != null && mLocaleListItemProvider.isChildLocale();
    129     }
    130 
    131     /**
    132      * Add a pseudo locale in debug build for testing RTL.
    133      *
    134      * @param localeInfos the set of {@link LocaleStore.LocaleInfo} to which the locale is added.
    135      */
    136     private void maybeAddPseudoLocale(Set<LocaleStore.LocaleInfo> localeInfos) {
    137         if (Build.IS_USERDEBUG) {
    138             // The ar-XB pseudo-locale is RTL.
    139             localeInfos.add(LocaleStore.getLocaleInfo(new Locale("ar", "XB")));
    140         }
    141     }
    142 
    143     private void resetLocaleList(Set<LocaleStore.LocaleInfo> localeInfos) {
    144         if (mLocaleListItemProvider != null) {
    145             maybeAddPseudoLocale(localeInfos);
    146             mLocaleListItemProvider.updateSuggestedLocaleAdapter(
    147                     LanguagePickerUtils.createSuggestedLocaleAdapter(
    148                             getContext(), localeInfos, /* parent= */ null),
    149                     /* isChildLocale= */ false);
    150             refreshList();
    151         }
    152     }
    153 
    154     /**
    155      * ViewModel for holding the LocaleInfos.
    156      */
    157     public static class LocaleViewModel extends ViewModel {
    158 
    159         private MutableLiveData<Set<LocaleStore.LocaleInfo>> mLocaleInfos;
    160 
    161         /**
    162          * Returns LiveData holding a set of LocaleInfo.
    163          */
    164         public LiveData<Set<LocaleStore.LocaleInfo>> getLocaleInfos(Context context,
    165                 Set<String> ignorables) {
    166 
    167             if (mLocaleInfos == null) {
    168                 mLocaleInfos = new MutableLiveData<Set<LocaleStore.LocaleInfo>>();
    169                 reloadLocales(context, ignorables);
    170             }
    171             return mLocaleInfos;
    172         }
    173 
    174         /**
    175          * Reload the locales based on the current context.
    176          */
    177         public void reloadLocales(Context context, Set<String> ignorables) {
    178             new AsyncTask<Context, Void, Set<LocaleStore.LocaleInfo>>() {
    179                 @Override
    180                 protected Set<LocaleStore.LocaleInfo> doInBackground(Context... contexts) {
    181                     return LocaleStore.getLevelLocales(
    182                             contexts[0],
    183                             ignorables,
    184                             /* parent= */ null,
    185                             /* translatedOnly= */ true);
    186                 }
    187 
    188                 @Override
    189                 protected void onPostExecute(Set<LocaleStore.LocaleInfo> localeInfos) {
    190                     LocaleViewModel.this.mLocaleInfos.setValue(localeInfos);
    191                 }
    192             }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, context);
    193         }
    194     }
    195 }
    196