1/*
2 * Copyright (C) 2011 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
17package com.android.dialer.util;
18
19import android.content.Context;
20import android.content.res.Configuration;
21import android.content.res.Resources;
22
23import java.util.Locale;
24
25/**
26 * Utility class to save and restore the locale of the system.
27 * <p>
28 * This can be used for tests that assume to be run in a certain locale, e.g., because they
29 * check against strings in a particular language or require an assumption on how the system
30 * will behave in a specific locale.
31 * <p>
32 * In your test, you can change the locale with the following code:
33 * <pre>
34 * public class CanadaFrenchTest extends AndroidTestCase {
35 *     private LocaleTestUtils mLocaleTestUtils;
36 *
37 *     &#64;Override
38 *     public void setUp() throws Exception {
39 *         super.setUp();
40 *         mLocaleTestUtils = new LocaleTestUtils(getContext());
41 *         mLocaleTestUtils.setLocale(Locale.CANADA_FRENCH);
42 *     }
43 *
44 *     &#64;Override
45 *     public void tearDown() throws Exception {
46 *         mLocaleTestUtils.restoreLocale();
47 *         mLocaleTestUtils = null;
48 *         super.tearDown();
49 *     }
50 *
51 *     ...
52 * }
53 * </pre>
54 * Note that one should not call {@link #setLocale(Locale)} more than once without calling
55 * {@link #restoreLocale()} first.
56 * <p>
57 * This class is not thread-safe. Usually its methods should be invoked only from the test thread.
58 */
59public class LocaleTestUtils {
60    private final Context mContext;
61    private boolean mSaved;
62    private Locale mSavedContextLocale;
63    private Locale mSavedSystemLocale;
64
65    /**
66     * Create a new instance that can be used to set and reset the locale for the given context.
67     *
68     * @param context the context on which to alter the locale
69     */
70    public LocaleTestUtils(Context context) {
71        mContext = context;
72        mSaved = false;
73    }
74
75    /**
76     * Set the locale to the given value and saves the previous value.
77     *
78     * @param locale the value to which the locale should be set
79     * @throws IllegalStateException if the locale was already set
80     */
81    public void setLocale(Locale locale) {
82        if (mSaved) {
83            throw new IllegalStateException(
84                    "call restoreLocale() before calling setLocale() again");
85        }
86        mSavedContextLocale = setResourcesLocale(mContext.getResources(), locale);
87        mSavedSystemLocale = setResourcesLocale(Resources.getSystem(), locale);
88        mSaved = true;
89    }
90
91    /**
92     * Restores the previously set locale.
93     *
94     * @throws IllegalStateException if the locale was not set using {@link #setLocale(Locale)}
95     */
96    public void restoreLocale() {
97        if (!mSaved) {
98            throw new IllegalStateException("call setLocale() before calling restoreLocale()");
99        }
100        setResourcesLocale(mContext.getResources(), mSavedContextLocale);
101        setResourcesLocale(Resources.getSystem(), mSavedSystemLocale);
102        mSaved = false;
103    }
104
105    /**
106     * Sets the locale for the given resources and returns the previous locale.
107     *
108     * @param resources the resources on which to set the locale
109     * @param locale the value to which to set the locale
110     * @return the previous value of the locale for the resources
111     */
112    private Locale setResourcesLocale(Resources resources, Locale locale) {
113        Configuration contextConfiguration = new Configuration(resources.getConfiguration());
114        Locale savedLocale = contextConfiguration.locale;
115        contextConfiguration.locale = locale;
116        resources.updateConfiguration(contextConfiguration, null);
117        return savedLocale;
118    }
119}
120