/* * 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 android.app; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserHandleAware; import android.content.Context; import android.content.res.Configuration; import android.os.LocaleList; import android.os.RemoteException; /** * This class gives access to system locale services. These services allow applications to * control granular locale settings (such as per-app locales) or override their list of supported * locales while running. * *
Third party applications should treat this as a write-side surface, and continue reading * locales via their in-process {@link LocaleList}s. */ @SystemService(Context.LOCALE_SERVICE) public class LocaleManager { private static final String TAG = "LocaleManager"; /** Context required for getting the user for which API calls are made. */ private Context mContext; private ILocaleManager mService; /** @hide Instantiated by ContextImpl */ public LocaleManager(Context context, ILocaleManager service) { mContext = context; mService = service; } /** * Sets the UI locales for the calling app. * *
Pass a {@link LocaleList#getEmptyLocaleList()} to reset to the system locale. * *
Note: Changes to app locales will result in a configuration change (and potentially * an Activity lifecycle event) being applied to the calling application. For more information, * see the section on * handling configuration changes. The set locales are persisted; they are backed up if the * user has enabled Backup & Restore. * *
Note: Users' locale preferences are passed to applications by creating a union of * any app-specific locales and system locales, with the app-specific locales appearing first. * Language resources are then chosen per usual (as described in the section on * locale resolution). * * @param locales the desired locales for the calling app. */ @UserHandleAware public void setApplicationLocales(@NonNull LocaleList locales) { setApplicationLocales(mContext.getPackageName(), locales, false); } /** * Sets the UI locales for a specified app (described by package name). * *
Pass a {@link LocaleList#getEmptyLocaleList()} to reset to the system locale. * *
Note: Changes to app locales will result in a configuration change (and potentially * an Activity lifecycle event) being applied to the specified application. For more * information, see the section on * handling configuration changes. The set locales are persisted; they are backed up if the * user has enabled Backup & Restore. * *
Note: Users' locale preferences are passed to applications by creating a union of * any app-specific locales and system locales, with the app-specific locales appearing first. * Language resources are then chosen per usual (as described in the section on * locale resolution). * * @param appPackageName the package name of the app for which to set the locales. * @param locales the desired locales for the specified app. * @hide */ @SystemApi @RequiresPermission(Manifest.permission.CHANGE_CONFIGURATION) @UserHandleAware public void setApplicationLocales(@NonNull String appPackageName, @NonNull LocaleList locales) { setApplicationLocales(appPackageName, locales, true); } private void setApplicationLocales(@NonNull String appPackageName, @NonNull LocaleList locales, boolean fromDelegate) { try { mService.setApplicationLocales(appPackageName, mContext.getUserId(), locales, fromDelegate); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the UI locales for the calling app. * *
Returns a {@link LocaleList#getEmptyLocaleList()} if no app-specific locales are set. */ @UserHandleAware @NonNull public LocaleList getApplicationLocales() { return getApplicationLocales(mContext.getPackageName()); } /** * Returns the current UI locales for a specified app (described by package name). * *
Returns a {@link LocaleList#getEmptyLocaleList()} if no app-specific locales are set. * *
This API can be used by an app's installer * (per {@link android.content.pm.InstallSourceInfo#getInstallingPackageName}) to retrieve * the app's locales. *
This API can be used by the current input method to retrieve locales of another packages. * All other cases require {@code android.Manifest.permission#READ_APP_SPECIFIC_LOCALES}. * Apps should generally retrieve their own locales via their in-process LocaleLists, * or by calling {@link #getApplicationLocales()}. * * @param appPackageName the package name of the app for which to retrieve the locales. */ @RequiresPermission(value = Manifest.permission.READ_APP_SPECIFIC_LOCALES, conditional = true) @UserHandleAware @NonNull public LocaleList getApplicationLocales(@NonNull String appPackageName) { try { return mService.getApplicationLocales(appPackageName, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the current system locales, ignoring app-specific overrides. * *
Note: Apps should generally access the user's locale preferences as indicated in * their in-process {@link LocaleList}s. However, in case an app-specific locale is set, this * method helps cater to rare use-cases which might require specifically knowing the system * locale. * *
Note: This API is not user-aware. It returns the system locales for the foreground * user. */ @NonNull public LocaleList getSystemLocales() { try { return mService.getSystemLocales(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Sets the current system locales to the provided value. * * @hide */ @TestApi public void setSystemLocales(@NonNull LocaleList locales) { try { Configuration conf = new Configuration(); conf.setLocales(locales); ActivityManager.getService().updatePersistentConfiguration(conf); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Sets the override LocaleConfig for the calling app. * *
Note: Only the app itself with the same user can override its own LocaleConfig. * *
Note: This function takes in a {@link LocaleConfig} which is intended to * override the original config in the application's resources. This LocaleConfig will * become the override config, and stored in a system file for future access. * *
Note: Using this function, applications can update their list of supported * locales while running, without an update of the application's software. For more * information, see the section on * dynamic updates for an app's localeConfig. * *
Applications can remove the override LocaleConfig with a {@code null} object. * * @param localeConfig the desired {@link LocaleConfig} for the calling app. */ @UserHandleAware public void setOverrideLocaleConfig(@Nullable LocaleConfig localeConfig) { try { // The permission android.Manifest.permission#SET_APP_SPECIFIC_LOCALECONFIG is // required to set an override LocaleConfig of another packages mService.setOverrideLocaleConfig(mContext.getPackageName(), mContext.getUserId(), localeConfig); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the override LocaleConfig for the calling app. * * @return the override LocaleConfig, or {@code null} if the LocaleConfig isn't overridden. */ @Nullable @UserHandleAware public LocaleConfig getOverrideLocaleConfig() { try { return mService.getOverrideLocaleConfig(mContext.getPackageName(), mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }