Android12,修改源码中launcher包名后,需要修改很多默认配置。其它模块调用launcher包名修改,framework默认配置修改,gms下面overlay修改等等。
本问简单记录一下桌面设置中“通知圆点”。在修改包名之后变成三角形,没有默认open的问题。
1、问题原因
因为界面在launcher中,现在launcher中找到菜单的显示逻辑,看看是根据什么判断的状态。
packages\apps\Launcher3\src\com\android\launcher3\settings\NotificationDotsPreference.java
private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
@Override
public void onSettingsChanged(boolean enabled) {
int summary = enabled
? R.string.notification_dots_desc_on
: R.string.notification_dots_desc_off;
boolean serviceEnabled = true;
if (enabled) {
// Check if the listener is enabled or not.
//获取setting数据库中的值
String enabledListeners = Settings.Secure.getString(
getContext().getContentResolver(), NOTIFICATION_ENABLED_LISTENERS);
//当前类包类名
ComponentName myListener =
new ComponentName(getContext(), NotificationListener.class);
//判断是否打开
serviceEnabled = enabledListeners != null &&
(enabledListeners.contains(myListener.flattenToString()) ||
enabledListeners.contains(myListener.flattenToShortString()));
if (!serviceEnabled) {
summary = R.string.title_missing_notification_access;
}
}
setWidgetFrameVisible(!serviceEnabled);
setFragment(serviceEnabled ? null : NotificationAccessConfirmation.class.getName());
setSummary(summary);
NotifyDotNumWrapper.setNotifyDotsExtPrefEnabled(getContext(), enabled && !mWidgetFrameVisible);
}
以上可以看出,其实关键在于Settings.Secure.getString(getContext().getContentResolver(), NOTIFICATION_ENABLED_LISTENERS);这个值。
正常情况下adb打印如下:
adb shell settings get secure enabled_notification_listeners
com.google.android.projection.gearhead/com.google.android.gearhead.notifications.SharedNotificationListenerManager$ListenerService:com.android.launcher3/com.android.launcher3.notification.NotificationListener
修改包名之后,这个值没有launcher的NotificationListener了。所以launcher桌面设置中显示三角形。
2、NOTIFICATION_ENABLED_LISTENERS
NOTIFICATION_ENABLED_LISTENERS = “enabled_notification_listeners”
那么现在的问题就是这个值是哪里设置进去的。
弯路1:
一开始以为是在setting或者settingprovider里,后来发现这两个代码里没有相关的东西。
弯路2:
在framework中搜索enabled_notification_listeners,发现直接调用enabled_notification_listeners的地方,没有调用Settings.Secure.putStringForUser()方法。那么可能是间接调用然后本地临时变量存了key值,再去put。这样就不容易找到默认值是哪里写入的了。
解套
1、frameworks\base\core\java\android\provider\Settings.java
直接找到putStringForUser方法,添加调用堆栈打印:
if("enabled_notification_listeners".equals(name)){
Log.i(TAG, "putStringForUser"+Log.getStackTraceString(new Throwable()));
}
2022-11-23 23:19:28.003 1125-1255/system_process I/Settings: putStringForUserjava.lang.Throwable
at android.provider.Settings$Secure.putStringForUser(Settings.java:5900)
at android.provider.Settings$Secure.putStringForUser(Settings.java:5890)
at com.android.server.notification.ManagedServices.writeXml(ManagedServices.java:536)
at com.android.server.notification.NotificationManagerService.writePolicyXml(NotificationManagerService.java:1100)
at com.android.server.notification.NotificationManagerService.access$200(NotificationManagerService.java:338)
at com.android.server.notification.NotificationManagerService$SavePolicyFileRunnable.run(NotificationManagerService.java:1075)
at android.os.Handler.handleCallback(Handler.java:938)
2、由此跟踪到frameworks\base\services\core\java\com\android\server\notification\ManagedServices.java
写值的方法都在这个类里
writeXml方法去调用的put值
//它里面所有put的值来源mApproved
protected ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>();
//查一查mApproved值的来源
//整个类只有2个地方调用mApproved.put
//添加堆栈打印,再次编译后得到调用堆栈如下
//setPackageOrComponentEnabled方法
addDefaultComponentOrPackage: java.lang.Throwable
at com.android.server.notification.ManagedServices.addDefaultComponentOrPackage(ManagedServices.java:219)
at com.android.server.notification.NotificationManagerService$NotificationListeners.loadDefaultsFromConfig(NotificationManagerService.java:10247)
at com.android.server.notification.NotificationManagerService.loadDefaultApprovedServices(NotificationManagerService.java:748)
at com.android.server.notification.NotificationManagerService.loadPolicyFile(NotificationManagerService.java:1040)
at com.android.server.notification.NotificationManagerService.init(NotificationManagerService.java:2384)
at com.android.server.notification.NotificationManagerService.onStart(NotificationManagerService.java:2554)
at com.android.server.SystemServiceManager.startService(SystemServiceManager.java:205)
at com.android.server.SystemServiceManager.startService(SystemServiceManager.java:192)
at com.android.server.SystemServer.startOtherServices(SystemServer.java:2064)
at com.android.server.SystemServer.run(SystemServer.java:933)
由此可见,系统启动流程中启动了service,service的init调用了加载默认配置。
3、跟踪上面流程中,加载默认配置的值是配在哪里
frameworks\base\services\core\java\com\android\server\notification\NotificationManagerService.java
内部类public class NotificationListeners extends ManagedServices
@Override
protected void loadDefaultsFromConfig() {
String defaultListenerAccess = mContext.getResources().getString(
R.string.config_defaultListenerAccessPackages);
Log.v(TAG, " loadDefaultsFromConfig defaultListenerAccess: "+defaultListenerAccess);
if (defaultListenerAccess != null) {
String[] listeners =
defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
for (int i = 0; i < listeners.length; i++) {
if (TextUtils.isEmpty(listeners[i])) {
continue;
}
ArraySet<ComponentName> approvedListeners =
this.queryPackageForServices(listeners[i],
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE, USER_SYSTEM);
for (int k = 0; k < approvedListeners.size(); k++) {
ComponentName cn = approvedListeners.valueAt(k);
Log.v(TAG, " loadDefaultsFromConfig cn: "+cn);
addDefaultComponentOrPackage(cn.flattenToString());
}
}
}
}
最终定位到config_defaultListenerAccessPackages配置。
vendor\partner_gms\overlay\GmsConfigOverlayCommon\res\values\config.xml
<string name="config_defaultListenerAccessPackages" translatable="false">com.tblenovo.launcher:com.google.android.projection.gearhead</string>
1、SystemServer.startOtherServices
NotificationManagerService.init
NotificationManagerService.loadPolicyFile
protected void loadPolicyFile() {
if (DBG) Slog.d(TAG, "loadPolicyFile");
if(mPolicyFile != null ){
if (mPolicyFile.getBaseFile() != null){
Slog.d(TAG, "loadPolicyFile: "+mPolicyFile.getBaseFile().getAbsolutePath());
}
}
synchronized (mPolicyFile) {
InputStream infile = null;
try {
infile = mPolicyFile.openRead();
readPolicyXml(infile, false /*forRestore*/, UserHandle.USER_ALL);
} catch (FileNotFoundException e) {
// No data yet
// Load default managed services approvals
loadDefaultApprovedServices(USER_SYSTEM);//加载默认配置
allowDefaultApprovedServices(USER_SYSTEM);//默认配置bind并缓存
} catch (IOException e) {
Log.wtf(TAG, "Unable to read notification policy", e);
} catch (NumberFormatException e) {
Log.wtf(TAG, "Unable to parse notification policy", e);
} catch (XmlPullParserException e) {
Log.wtf(TAG, "Unable to parse notification policy", e);
} finally {
IoUtils.closeQuietly(infile);
}
}
}
//文件不存在时加载默认值,文件存在时加载文件。文件路径如下
final File systemDir = new File(Environment.getDataDirectory(), "system");
new File(systemDir, "notification_policy.xml"), "notification-policy"),