Send broadcasts on app-locale change.
Send below broadcasts: 1) explicit intent ACTION_LOCALE_CHANGED to app whose locale changed 2) explicit intent ACTION_APPPLICATION_LOCALE_CHANGED to installer of app 3) implicit ACTION_APPPLICATION_LOCALE_CHANGED to receivers with READ_APP_SPECIFIC_LOCALES permission Bug: 202275007 Test: Manual; install app via adb, set the installer, grant permission to some system app(eg. Settings). See that broadcast is received by all three receivers on app locale change. Change-Id: Ifef25aaf3c1fde0fdf0befc4eb67cfd07186e46c
This commit is contained in:
@@ -18,11 +18,14 @@ package com.android.server.locales;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.ILocaleManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.os.Binder;
|
||||
import android.os.LocaleList;
|
||||
@@ -142,7 +145,6 @@ public class LocaleManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setApplicationLocalesUnchecked(@NonNull String appPackageName,
|
||||
@UserIdInt int userId, @NonNull LocaleList locales) {
|
||||
if (DEBUG) {
|
||||
@@ -152,9 +154,76 @@ public class LocaleManagerService extends SystemService {
|
||||
final ActivityTaskManagerInternal.PackageConfigurationUpdater updater =
|
||||
mActivityTaskManagerInternal.createPackageConfigurationUpdater(appPackageName,
|
||||
userId);
|
||||
updater.setLocales(locales).commit();
|
||||
boolean isSuccess = updater.setLocales(locales).commit();
|
||||
|
||||
//We want to send the broadcasts only if config was actually updated on commit.
|
||||
if (isSuccess) {
|
||||
notifyAppWhoseLocaleChanged(appPackageName, userId, locales);
|
||||
notifyInstallerOfAppWhoseLocaleChanged(appPackageName, userId, locales);
|
||||
notifyRegisteredReceivers(appPackageName, userId, locales);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an implicit broadcast with action
|
||||
* {@link android.content.Intent#ACTION_APPLICATION_LOCALE_CHANGED}
|
||||
* to receivers with {@link android.Manifest.permission#READ_APP_SPECIFIC_LOCALES}.
|
||||
*/
|
||||
private void notifyRegisteredReceivers(String appPackageName, int userId,
|
||||
LocaleList locales) {
|
||||
Intent intent = createBaseIntent(Intent.ACTION_APPLICATION_LOCALE_CHANGED,
|
||||
appPackageName, locales);
|
||||
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId),
|
||||
Manifest.permission.READ_APP_SPECIFIC_LOCALES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an explicit broadcast with action
|
||||
* {@link android.content.Intent#ACTION_APPLICATION_LOCALE_CHANGED} to
|
||||
* the installer (as per {@link android.content.pm.InstallSourceInfo#getInstallingPackageName})
|
||||
* of app whose locale has changed.
|
||||
*
|
||||
* <p><b>Note:</b> This is can be used by installers to deal with cases such as
|
||||
* language-based APK Splits.
|
||||
*/
|
||||
private void notifyInstallerOfAppWhoseLocaleChanged(String appPackageName, int userId,
|
||||
LocaleList locales) {
|
||||
try {
|
||||
String installingPackageName = mContext.getPackageManager()
|
||||
.getInstallSourceInfo(appPackageName).getInstallingPackageName();
|
||||
if (installingPackageName != null) {
|
||||
Intent intent = createBaseIntent(Intent.ACTION_APPLICATION_LOCALE_CHANGED,
|
||||
appPackageName, locales);
|
||||
//Set package name to ensure that only installer of the app receives this intent.
|
||||
intent.setPackage(installingPackageName);
|
||||
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.w(TAG, "Package not found " + appPackageName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an explicit broadcast with action {@link android.content.Intent#ACTION_LOCALE_CHANGED}
|
||||
* to the app whose locale has changed.
|
||||
*/
|
||||
private void notifyAppWhoseLocaleChanged(String appPackageName, int userId,
|
||||
LocaleList locales) {
|
||||
Intent intent = createBaseIntent(Intent.ACTION_LOCALE_CHANGED, appPackageName, locales);
|
||||
//Set package name to ensure that only the app whose locale changed receives this intent.
|
||||
intent.setPackage(appPackageName);
|
||||
intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
|
||||
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
|
||||
}
|
||||
|
||||
private static Intent createBaseIntent(String intentAction, String appPackageName,
|
||||
LocaleList locales) {
|
||||
return new Intent(intentAction)
|
||||
.putExtra(Intent.EXTRA_PACKAGE_NAME, appPackageName)
|
||||
.putExtra(Intent.EXTRA_LOCALE_LIST, locales)
|
||||
.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
|
||||
| Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the package is owned by the calling app or not for the given user id.
|
||||
|
||||
Reference in New Issue
Block a user