From 0524ebc2f2c24cb10769d3ef455f32c3c3d22c55 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Sat, 25 Sep 2021 23:35:46 +0800 Subject: [PATCH] [core] Listen to configuration change (#1174) --- .../lspd/service/ActivityManagerService.java | 7 ++++ .../lspd/service/ConfigFileManager.java | 22 ++++++----- .../lspd/service/LSPManagerService.java | 22 +++++------ .../lsposed/lspd/service/LSPosedService.java | 37 +++++++++++++++++-- .../lsposed/lspd/service/ServiceManager.java | 2 +- .../java/android/app/IActivityManager.java | 3 ++ 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java b/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java index ba1f19e4..1f017196 100644 --- a/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java +++ b/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java @@ -30,6 +30,7 @@ import android.content.IIntentReceiver; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; import android.os.IBinder; @@ -164,6 +165,12 @@ public class ActivityManagerService { return am.getCurrentUser(); } + public static Configuration getConfiguration() throws RemoteException { + IActivityManager am = getActivityManager(); + if (am == null) return null; + return am.getConfiguration(); + } + public static IContentProvider getContentProvider(String auth, int userId) throws RemoteException { IActivityManager am = getActivityManager(); if (am == null) return null; diff --git a/core/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java b/core/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java index c85e2bdb..72cbd23d 100644 --- a/core/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java +++ b/core/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java @@ -75,7 +75,7 @@ public class ConfigFileManager { } public static Resources getResources() { - loadLocale(); + loadRes(); return res; } @@ -116,7 +116,7 @@ public class ConfigFileManager { return productLanguage + "-" + productRegion; } - private static void loadLocale() { + private static void loadRes() { if (res != null) return; try { am = AssetManager.class.newInstance(); @@ -132,14 +132,16 @@ public class ConfigFileManager { } } - static void reloadLocale() { - loadLocale(); - Locale locale = Locale.forLanguageTag(readLocale()); - Locale.setDefault(locale); - var conf = res.getConfiguration(); - conf.setLocale(Locale.forLanguageTag(readLocale())); - //noinspection deprecation - res.updateConfiguration(conf, res.getDisplayMetrics()); + static void reloadConfiguration() { + loadRes(); + try { + var conf = ActivityManagerService.getConfiguration(); + if (conf != null) + //noinspection deprecation + res.updateConfiguration(conf, res.getDisplayMetrics()); + } catch (Throwable e) { + Log.e(TAG, "reload configuration", e); + } } static ParcelFileDescriptor getManagerApk() throws IOException { diff --git a/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java b/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java index 9ba47792..1372b714 100644 --- a/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java +++ b/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java @@ -83,8 +83,6 @@ public class LSPManagerService extends ILSPManagerService.Stub { public static final String CHANNEL_NAME = "LSPosed Manager"; public static final int CHANNEL_IMP = NotificationManager.IMPORTANCE_HIGH; - private static Icon managerIcon = null; - private static Icon notificationIcon = null; private static Intent managerIntent = null; public class ManagerGuard implements IBinder.DeathRecipient { @@ -153,21 +151,15 @@ public class LSPManagerService extends ILSPManagerService.Stub { } private static Icon getManagerIcon() { - if (managerIcon == null) { - try { - managerIcon = getIcon(org.lsposed.manager.R.mipmap.ic_launcher); - } catch (Throwable e) { - managerIcon = getIcon(org.lsposed.manager.R.drawable.ic_launcher); - } + try { + return getIcon(org.lsposed.manager.R.mipmap.ic_launcher); + } catch (Throwable e) { + return getIcon(org.lsposed.manager.R.drawable.ic_launcher); } - return managerIcon; } private static Icon getNotificationIcon() { - if (notificationIcon == null) { - notificationIcon = getIcon(org.lsposed.manager.R.drawable.ic_extension); - } - return notificationIcon; + return getIcon(org.lsposed.manager.R.drawable.ic_extension); } private static Intent getManagerIntent() { @@ -251,6 +243,10 @@ public class LSPManagerService extends ILSPManagerService.Stub { public static void createOrUpdateShortcut() { try { + while (!UserService.isUserUnlocked(0)) { + Log.d(TAG, "user is not yet unlocked, waiting for 1s..."); + Thread.sleep(1000); + } var smCtor = ShortcutManager.class.getDeclaredConstructor(Context.class); smCtor.setAccessible(true); var context = new FakeContext("com.android.settings"); diff --git a/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java b/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java index 2b6a1c0d..c9ca9611 100644 --- a/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java +++ b/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java @@ -32,6 +32,7 @@ import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; +import android.util.DisplayMetrics; import android.util.Log; import java.util.Arrays; @@ -159,16 +160,21 @@ public class LSPosedService extends ILSPosedService.Stub { synchronized public void dispatchUserUnlocked(Intent intent) { try { - while (!UserService.isUserUnlocked(0)) { - Log.d(TAG, "user is not yet unlocked, waiting for 1s..."); - Thread.sleep(1000); - } LSPManagerService.createOrUpdateShortcut(); } catch (Throwable e) { Log.e(TAG, "dispatch user unlocked", e); } } + synchronized public void dispatchConfigurationChanged(Intent intent) { + try { + ConfigFileManager.reloadConfiguration(); + LSPManagerService.createOrUpdateShortcut(); + } catch (Throwable e) { + Log.e(TAG, "dispatch configuration changed", e); + } + } + private void registerPackageReceiver() { try { IntentFilter packageFilter = new IntentFilter(); @@ -222,12 +228,35 @@ public class LSPosedService extends ILSPosedService.Stub { Log.d(TAG, "registered unlock receiver"); } + private void registerConfigurationReceiver() { + try { + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + + ActivityManagerService.registerReceiver("android", null, new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { + new Thread(() -> dispatchConfigurationChanged(intent)).start(); + try { + ActivityManagerService.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); + } catch (Throwable e) { + Log.e(TAG, "finish receiver", e); + } + } + }, intentFilter, null, 0, 0); + } catch (Throwable e) { + Log.e(TAG, "register configuration receiver", e); + } + Log.d(TAG, "registered configuration receiver"); + } + @Override public void dispatchSystemServerContext(IBinder activityThread, IBinder activityToken) { Log.d(TAG, "received system context"); ActivityManagerService.onSystemServerContext(IApplicationThread.Stub.asInterface(activityThread), activityToken); registerPackageReceiver(); registerUnlockReceiver(); + registerConfigurationReceiver(); } @Override diff --git a/core/src/main/java/org/lsposed/lspd/service/ServiceManager.java b/core/src/main/java/org/lsposed/lspd/service/ServiceManager.java index 1e4718b7..5e0f7280 100644 --- a/core/src/main/java/org/lsposed/lspd/service/ServiceManager.java +++ b/core/src/main/java/org/lsposed/lspd/service/ServiceManager.java @@ -104,7 +104,7 @@ public class ServiceManager { waitSystemService(Context.USER_SERVICE); waitSystemService(Context.APP_OPS_SERVICE); - ConfigFileManager.reloadLocale(); + ConfigFileManager.reloadConfiguration(); BridgeService.send(mainService, new BridgeService.Listener() { @Override diff --git a/hiddenapi-stubs/src/main/java/android/app/IActivityManager.java b/hiddenapi-stubs/src/main/java/android/app/IActivityManager.java index e72b1a23..1b5d417c 100644 --- a/hiddenapi-stubs/src/main/java/android/app/IActivityManager.java +++ b/hiddenapi-stubs/src/main/java/android/app/IActivityManager.java @@ -23,6 +23,7 @@ import android.content.IIntentReceiver; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.content.res.Configuration; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -104,6 +105,8 @@ public interface IActivityManager extends IInterface { ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token); + Configuration getConfiguration() throws RemoteException; + abstract class Stub extends Binder implements IActivityManager { public static int TRANSACTION_setActivityController;