• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 package com.android.settings.applications.appinfo;
17 
18 import static com.android.settings.widget.EntityHeaderController.ActionType;
19 
20 import android.app.Activity;
21 import android.app.LocaleManager;
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.PackageManager;
26 import android.os.Bundle;
27 import android.os.LocaleList;
28 import android.os.UserHandle;
29 import android.util.FeatureFlagUtils;
30 import android.util.Log;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.widget.TextView;
35 
36 import androidx.annotation.Nullable;
37 import androidx.preference.Preference;
38 
39 import com.android.internal.app.LocaleHelper;
40 import com.android.settings.R;
41 import com.android.settings.SettingsPreferenceFragment;
42 import com.android.settings.Utils;
43 import com.android.settings.applications.AppInfoBase;
44 import com.android.settings.applications.AppLocaleUtil;
45 import com.android.settings.widget.EntityHeaderController;
46 import com.android.settingslib.applications.AppUtils;
47 import com.android.settingslib.widget.LayoutPreference;
48 
49 import java.util.Locale;
50 
51 /**
52  * TODO(b/223503670): Implement the unittest.
53  * A fragment to show the current app locale info.
54  */
55 public class AppLocaleDetails extends SettingsPreferenceFragment {
56     private static final String TAG = "AppLocaleDetails";
57 
58     private static final String KEY_APP_DESCRIPTION = "app_locale_description";
59     private static final String KEY_APP_DISCLAIMER = "app_locale_disclaimer";
60 
61     private boolean mCreated = false;
62     private String mPackageName;
63     private LayoutPreference mPrefOfDescription;
64     private Preference mPrefOfDisclaimer;
65     private ApplicationInfo mApplicationInfo;
66     @Nullable private String mParentLocale;
67 
68     /**
69      * Create a instance of AppLocaleDetails.
70      * @param packageName Indicates which application need to show the locale picker.
71      * @param uid User id.
72      */
newInstance(String packageName, int uid)73     public static AppLocaleDetails newInstance(String packageName, int uid) {
74         AppLocaleDetails appLocaleDetails = new AppLocaleDetails();
75         Bundle bundle = new Bundle();
76         bundle.putString(AppInfoBase.ARG_PACKAGE_NAME, packageName);
77         bundle.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
78         appLocaleDetails.setArguments(bundle);
79         return appLocaleDetails;
80     }
81 
82     @Override
onCreate(Bundle savedInstanceState)83     public void onCreate(Bundle savedInstanceState) {
84         super.onCreate(savedInstanceState);
85         Bundle bundle = getArguments();
86         mPackageName = bundle.getString(AppInfoBase.ARG_PACKAGE_NAME, "");
87         if (mPackageName.isEmpty()) {
88             Log.d(TAG, "There is no package name.");
89             finish();
90         }
91         int uid = bundle.getInt(AppInfoBase.ARG_PACKAGE_UID, getContext().getUserId());
92 
93         addPreferencesFromResource(R.xml.app_locale_details);
94         mPrefOfDescription = getPreferenceScreen().findPreference(KEY_APP_DESCRIPTION);
95         mPrefOfDisclaimer = getPreferenceScreen().findPreference(KEY_APP_DISCLAIMER);
96         mApplicationInfo = getApplicationInfo(mPackageName, uid);
97         setDisclaimerPreference();
98     }
99 
100     // Override here so we don't have an empty screen
101     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)102     public View onCreateView(LayoutInflater inflater,
103             ViewGroup container,
104             Bundle savedInstanceState) {
105         // if we don't have a package, show a page saying this is unsupported
106         if (mPackageName.isEmpty()) {
107             return inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
108         }
109         return super.onCreateView(inflater, container, savedInstanceState);
110     }
111 
112     @Override
onResume()113     public void onResume() {
114         super.onResume();
115         refreshUi();
116         final Activity activity = getActivity();
117         if (mParentLocale != null) {
118             activity.setTitle(mParentLocale);
119         } else {
120             activity.setTitle(R.string.app_locale_picker_title);
121         }
122     }
123 
refreshUi()124     private void refreshUi() {
125         setDescription();
126     }
127 
128     @Override
getMetricsCategory()129     public int getMetricsCategory() {
130         return SettingsEnums.APPS_LOCALE_LIST;
131     }
132 
133     @Override
onActivityCreated(Bundle savedInstanceState)134     public void onActivityCreated(Bundle savedInstanceState) {
135         super.onActivityCreated(savedInstanceState);
136         if (mCreated) {
137             Log.w(TAG, "onActivityCreated: ignoring duplicate call");
138             return;
139         }
140         mCreated = true;
141         if (mPackageName == null) {
142             return;
143         }
144         // Creates a head icon button of app on this page.
145         final Activity activity = getActivity();
146         final Preference pref = EntityHeaderController
147                 .newInstance(activity, this, null /* header */)
148                 .setIcon(Utils.getBadgedIcon(getContext(), mApplicationInfo))
149                 .setLabel(mApplicationInfo.loadLabel(getContext().getPackageManager()))
150                 .setIsInstantApp(AppUtils.isInstant(mApplicationInfo))
151                 .setPackageName(mPackageName)
152                 .setUid(mApplicationInfo.uid)
153                 .setHasAppInfoLink(true)
154                 .setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
155                 .setOrder(10)
156                 .done(getPrefContext());
157         getPreferenceScreen().addPreference(pref);
158     }
159 
setDisclaimerPreference()160     private void setDisclaimerPreference() {
161         if (FeatureFlagUtils.isEnabled(
162                 getContext(), FeatureFlagUtils.SETTINGS_APP_LOCALE_OPT_IN_ENABLED)) {
163             mPrefOfDisclaimer.setVisible(false);
164         }
165     }
166 
setDescription()167     private void setDescription() {
168         int res = getAppDescription();
169         if (res != -1) {
170             mPrefOfDescription.setVisible(true);
171             TextView description = (TextView) mPrefOfDescription.findViewById(R.id.description);
172             description.setText(getContext().getString(res));
173         }
174     }
175 
getApplicationInfo(String packageName, int userId)176     private ApplicationInfo getApplicationInfo(String packageName, int userId) {
177         ApplicationInfo applicationInfo;
178         try {
179             applicationInfo = getContext().getPackageManager()
180                     .getApplicationInfoAsUser(packageName, /* flags= */ 0, userId);
181             return applicationInfo;
182         } catch (PackageManager.NameNotFoundException e) {
183             Log.w(TAG, "Application info not found for: " + packageName);
184             return null;
185         }
186     }
187 
getAppDescription()188     private int getAppDescription() {
189         LocaleList packageLocaleList = AppLocaleUtil.getPackageLocales(getContext(), mPackageName);
190         String[] assetLocaleList = AppLocaleUtil.getAssetLocales(getContext(), mPackageName);
191         // TODO add apended url string, "Learn more", to these both sentenses.
192         if ((packageLocaleList != null && packageLocaleList.isEmpty())
193                 || (packageLocaleList == null && assetLocaleList.length == 0)) {
194             return R.string.desc_no_available_supported_locale;
195         }
196         return -1;
197     }
198 
199     /** Gets per app's default locale */
getAppDefaultLocale(Context context, String packageName)200     public static Locale getAppDefaultLocale(Context context, String packageName) {
201         LocaleManager localeManager = context.getSystemService(LocaleManager.class);
202         try {
203             LocaleList localeList = (localeManager == null)
204                     ? null : localeManager.getApplicationLocales(packageName);
205             return localeList == null ? null : localeList.get(0);
206         } catch (IllegalArgumentException e) {
207             Log.w(TAG, "package name : " + packageName + " is not correct. " + e);
208         }
209         return null;
210     }
211 
212     /**
213      * TODO (b209962418) Do a performance test to low end device.
214      * @return Return the summary to show the current app's language.
215      */
getSummary(Context context, ApplicationInfo app)216     public static CharSequence getSummary(Context context, ApplicationInfo app) {
217         final UserHandle userHandle = UserHandle.getUserHandleForUid(app.uid);
218         final Context contextAsUser = context.createContextAsUser(userHandle, 0);
219         Locale appLocale = getAppDefaultLocale(contextAsUser, app.packageName);
220         if (appLocale == null) {
221             return context.getString(R.string.preference_of_system_locale_summary);
222         } else {
223             return LocaleHelper.getDisplayName(appLocale.stripExtensions(), appLocale, true);
224         }
225     }
226 
setParentLocale(@ullable String localeName)227     public void setParentLocale(@Nullable String localeName) {
228         mParentLocale = localeName;
229     }
230 }
231