1a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa/*
2a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * Copyright (C) 2010 The Android Open Source Project
3a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa *
4a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
5a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * you may not use this file except in compliance with the License.
6a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * You may obtain a copy of the License at
7a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa *
8a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
9a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa *
10a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
11a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
12a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * See the License for the specific language governing permissions and
14a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa * limitations under the License.
15a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa */
16a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
17a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawapackage com.android.internal.app;
18a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
1988b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawaimport com.android.internal.R;
2088b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa
21a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.app.ActivityManagerNative;
22a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.app.IActivityManager;
23a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.app.ListFragment;
24a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.app.backup.BackupManager;
2553daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawaimport android.content.Context;
26a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.content.res.Configuration;
27a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.content.res.Resources;
28a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.os.Bundle;
29a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.os.RemoteException;
30a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.util.Log;
31a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.view.View;
32a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.widget.ArrayAdapter;
33a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport android.widget.ListView;
34a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
35a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport java.text.Collator;
36a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport java.util.Arrays;
37a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawaimport java.util.Locale;
38a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
39a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawapublic class LocalePicker extends ListFragment {
40a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    private static final String TAG = "LocalePicker";
41a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    private static final boolean DEBUG = false;
42a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
43a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    public static interface LocaleSelectionListener {
44a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        // You can add any argument if you really need it...
4588b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa        public void onLocaleSelected(Locale locale);
46a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
47a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
48a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    LocaleSelectionListener mListener;  // default to null
49a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
5053daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    public static class LocaleInfo implements Comparable<LocaleInfo> {
5153daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        static final Collator sCollator = Collator.getInstance();
52a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
53a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        String label;
54a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        Locale locale;
55a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
5653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        public LocaleInfo(String label, Locale locale) {
57a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            this.label = label;
58a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            this.locale = locale;
59a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
60a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
6153daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        public String getLabel() {
6253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            return label;
6353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        }
6453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa
6553daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        public Locale getLocale() {
6653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            return locale;
6753daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        }
6853daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa
69a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        @Override
70a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        public String toString() {
71a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            return this.label;
72a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
73a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
74a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        @Override
7553daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        public int compareTo(LocaleInfo another) {
76a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            return sCollator.compare(this.label, another.label);
77a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
78a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
79a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
8053daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    /**
8153daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa     * Constructs an Adapter object containing Locale information. Content is sorted by
8253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa     * {@link LocaleInfo#label}.
8353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa     */
8453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
852b133574bbfd076ff7f8bfac27a0f1226e47abebDaisuke Miyakawa        return constructAdapter(context, R.layout.locale_picker_item, R.id.locale);
862b133574bbfd076ff7f8bfac27a0f1226e47abebDaisuke Miyakawa    }
872b133574bbfd076ff7f8bfac27a0f1226e47abebDaisuke Miyakawa
882b133574bbfd076ff7f8bfac27a0f1226e47abebDaisuke Miyakawa    public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
892b133574bbfd076ff7f8bfac27a0f1226e47abebDaisuke Miyakawa            int layoutId, int fieldId) {
9053daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        final Resources resources = context.getResources();
91e16a1bfa9cd9a9a0430e2fe890586ae451f0faafDaisuke Miyakawa        final String[] locales = Resources.getSystem().getAssets().getLocales();
9253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
9353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        final String[] specialLocaleNames = resources.getStringArray(R.array.special_locale_names);
94a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        Arrays.sort(locales);
95a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        final int origSize = locales.length;
9653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        final LocaleInfo[] preprocess = new LocaleInfo[origSize];
97a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        int finalSize = 0;
98a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        for (int i = 0 ; i < origSize; i++ ) {
9953daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            final String s = locales[i];
10053daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            final int len = s.length();
101a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            if (len == 5) {
102a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                String language = s.substring(0, 2);
103a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                String country = s.substring(3, 5);
10453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                final Locale l = new Locale(language, country);
105a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
106a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                if (finalSize == 0) {
107a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    if (DEBUG) {
108a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
109a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    }
110a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    preprocess[finalSize++] =
11153daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                            new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l);
112a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                } else {
113a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    // check previous entry:
114a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    //  same lang and a country -> upgrade to full name and
115a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    //    insert ours with full name
116a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    //  diff lang -> insert ours with lang-only name
117a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    if (preprocess[finalSize-1].locale.getLanguage().equals(
118a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                            language)) {
119a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        if (DEBUG) {
120a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                            Log.v(TAG, "backing up and fixing "+
121a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                                    preprocess[finalSize-1].label+" to "+
12253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                    getDisplayName(preprocess[finalSize-1].locale,
12353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                            specialLocaleCodes, specialLocaleNames));
124a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        }
125a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        preprocess[finalSize-1].label = toTitleCase(
12653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                getDisplayName(preprocess[finalSize-1].locale,
12753daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                        specialLocaleCodes, specialLocaleNames));
128a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        if (DEBUG) {
12953daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                            Log.v(TAG, "  and adding "+ toTitleCase(
13053daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                    getDisplayName(l, specialLocaleCodes, specialLocaleNames)));
131a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        }
132a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        preprocess[finalSize++] =
13353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                new LocaleInfo(toTitleCase(
13453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                        getDisplayName(
13553daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                                                l, specialLocaleCodes, specialLocaleNames)), l);
136a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    } else {
137a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        String displayName;
138a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        if (s.equals("zz_ZZ")) {
139a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                            displayName = "Pseudo...";
140a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        } else {
141a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                            displayName = toTitleCase(l.getDisplayLanguage(l));
142a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        }
143a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        if (DEBUG) {
144a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                            Log.v(TAG, "adding "+displayName);
145a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                        }
14653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                        preprocess[finalSize++] = new LocaleInfo(displayName, l);
147a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                    }
148a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa                }
149a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            }
150a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
15153daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa
15253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        final LocaleInfo[] localeInfos = new LocaleInfo[finalSize];
15353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        for (int i = 0; i < finalSize; i++) {
15453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            localeInfos[i] = preprocess[i];
155a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
15653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        Arrays.sort(localeInfos);
15753daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos);
158a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
159a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
160a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    private static String toTitleCase(String s) {
161a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        if (s.length() == 0) {
162a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            return s;
163a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
164a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
165a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
166a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
167a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
16853daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    private static String getDisplayName(
16953daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            Locale l, String[] specialLocaleCodes, String[] specialLocaleNames) {
170a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        String code = l.toString();
171a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
17253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        for (int i = 0; i < specialLocaleCodes.length; i++) {
17353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            if (specialLocaleCodes[i].equals(code)) {
17453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa                return specialLocaleNames[i];
175a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            }
176a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
177a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
178a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        return l.getDisplayName(l);
179a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
180a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
181a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    @Override
18253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    public void onActivityCreated(final Bundle savedInstanceState) {
18353daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        super.onActivityCreated(savedInstanceState);
18453daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity());
18553daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        setListAdapter(adapter);
18653daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    }
18753daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa
18853daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    public void setLocaleSelectionListener(LocaleSelectionListener listener) {
18953daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa        mListener = listener;
19053daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    }
19153daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa
19253daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa    @Override
193a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    public void onResume() {
194a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        super.onResume();
195a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        getListView().requestFocus();
196a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
197a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
19888b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa    /**
19988b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     * Each listener needs to call {@link #updateLocale(Locale)} to actually change the locale.
20088b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     *
20188b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     * We don't call {@link #updateLocale(Locale)} automatically, as it halt the system for
20288b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     * a moment and some callers won't want it.
20388b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     */
204a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    @Override
205a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    public void onListItemClick(ListView l, View v, int position, long id) {
20688b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa        if (mListener != null) {
20753daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            final Locale locale = ((LocaleInfo)getListAdapter().getItem(position)).locale;
20853daead5718a95953fc009782299bd5e544bf4e5Daisuke Miyakawa            mListener.onLocaleSelected(locale);
20988b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa        }
21088b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa    }
21188b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa
21288b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa    /**
21388b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     * Requests the system to update the system locale. Note that the system looks halted
21488b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     * for a while during the Locale migration, so the caller need to take care of it.
21588b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa     */
21688b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa    public static void updateLocale(Locale locale) {
217a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        try {
218a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            IActivityManager am = ActivityManagerNative.getDefault();
219a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            Configuration config = am.getConfiguration();
220a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
22188b7349125d26200c5b4ef3c143e2e1cceda5703Daisuke Miyakawa            config.locale = locale;
222a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
223a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            // indicate this isn't some passing default - the user wants this remembered
224a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            config.userSetLocale = true;
225a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa
226a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            am.updateConfiguration(config);
227a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            // Trigger the dirty bit for the Settings Provider.
228a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            BackupManager.dataChanged("com.android.providers.settings");
229a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        } catch (RemoteException e) {
230a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa            // Intentionally left blank
231a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa        }
232a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa    }
233a43b74a4ef3735e52d3fda348271b8e495d685a8Daisuke Miyakawa}