diff --git a/core/api/current.txt b/core/api/current.txt index 9514447582e9f..7370af382b142 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -5631,6 +5631,11 @@ package android.app { method @Deprecated public android.view.Window startActivity(String, android.content.Intent); } + public class LocaleManager { + method @NonNull public android.os.LocaleList getApplicationLocales(); + method public void setApplicationLocales(@NonNull android.os.LocaleList); + } + public class MediaRouteActionProvider extends android.view.ActionProvider { ctor public MediaRouteActionProvider(android.content.Context); method public android.view.View onCreateActionView(); @@ -10753,6 +10758,7 @@ package android.content { field public static final String KEYGUARD_SERVICE = "keyguard"; field public static final String LAUNCHER_APPS_SERVICE = "launcherapps"; field @UiContext public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; + field public static final String LOCALE_SERVICE = "locale"; field public static final String LOCATION_SERVICE = "location"; field public static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; field public static final String MEDIA_METRICS_SERVICE = "media_metrics"; diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 258adcf8cd953..27b2b2084f9c0 100755 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -745,6 +745,11 @@ package android.app { field public static final int PIN = 1; // 0x1 } + public class LocaleManager { + method @NonNull @RequiresPermission(android.Manifest.permission.READ_APP_SPECIFIC_LOCALES) public android.os.LocaleList getApplicationLocales(@NonNull String); + method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void setApplicationLocales(@NonNull String, @NonNull android.os.LocaleList); + } + public class Notification implements android.os.Parcelable { field public static final String CATEGORY_CAR_EMERGENCY = "car_emergency"; field public static final String CATEGORY_CAR_INFORMATION = "car_information"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 3267473b805b4..da9fd3ebca641 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -281,6 +281,11 @@ package android.app { method @RequiresPermission(anyOf={android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"}) public boolean setLock(int, @Nullable byte[], int, @Nullable byte[]); } + public class LocaleManager { + method @Nullable public android.os.LocaleList getSystemLocales(); + method public void setSystemLocales(@NonNull android.os.LocaleList); + } + public class Notification implements android.os.Parcelable { method public boolean shouldShowForegroundImmediately(); } diff --git a/core/java/android/app/LocaleManager.java b/core/java/android/app/LocaleManager.java new file mode 100644 index 0000000000000..2aa7c8e60236a --- /dev/null +++ b/core/java/android/app/LocaleManager.java @@ -0,0 +1,152 @@ +/* + * 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). + * + *
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. + * + * @param locales the desired locales for the calling app. + */ + @UserHandleAware + public void setApplicationLocales(@NonNull LocaleList locales) { + setApplicationLocales(mContext.getPackageName(), locales); + } + + /** + * Sets the UI locales for a specified app (described by package name). + * + *
Pass a {@link LocaleList#getEmptyLocaleList()} to reset to the system locale. + * + * @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) { + try { + mService.setApplicationLocales(appPackageName, mContext.getUser().getIdentifier(), + locales); + } 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 specific app (described by package name). + * + *
Returns a {@link LocaleList#getEmptyLocaleList()} if no app-specific locales are set.
+ *
+ * Note: Non-system apps should read Locale information via their in-process
+ * LocaleLists.
+ *
+ * @param appPackageName the package name of the app for which to retrieve the locales.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_APP_SPECIFIC_LOCALES)
+ @UserHandleAware
+ @NonNull
+ public LocaleList getApplicationLocales(@NonNull String appPackageName) {
+ try {
+ return mService.getApplicationLocales(appPackageName, mContext.getUser()
+ .getIdentifier());
+ } 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 = ActivityManager.getService().getConfiguration();
+ conf.setLocales(locales);
+ ActivityManager.getService().updatePersistentConfiguration(conf);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current system locales for the device.
+ *
+ * @hide
+ */
+ @TestApi
+ @Nullable
+ public LocaleList getSystemLocales() {
+ try {
+ return ActivityManager.getService().getConfiguration().getLocales();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+}
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 4da51c13045b2..1909f3c03da4d 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -40,6 +40,9 @@ per-file *Alarm* = file:/apex/jobscheduler/OWNERS
# AppOps
per-file *AppOp* = file:/core/java/android/permission/OWNERS
+# LocaleManager
+per-file *Locale* = file:/services/core/java/com/android/server/locales/OWNERS
+
# Multiuser
per-file *User* = file:/MULTIUSER_OWNERS
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6ba185f486c38..fc40179890b66 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1393,6 +1393,14 @@ public final class SystemServiceRegistry {
throws ServiceNotFoundException {
return new SystemLightsManager(ctx);
}});
+ registerService(Context.LOCALE_SERVICE, LocaleManager.class,
+ new CachedServiceFetcher