1.简介
这个功能默认是打开的,如何默认关闭?
- settings >> notifications >> 最底部
- 参考2.3.2,首次开机的时候本地配置文件是没有的,会走catch,里边会加载默认的,并且把默认的加入allow
- 如果默认不要打开的话,那么在2.3.2里的catch代码里,注释掉allowDefaultApprovedServices调用
- 关于enhanced notifications
1.1.ConfigureNotificationSettings
>1.configure_notification_settings.xml
根据字符串搜索到xml如下
<com.android.settingslib.PrimarySwitchPreference
android:key="notification_assistant"
android:order="24"
android:title="@string/notification_assistant_title"
android:summary="@string/notification_assistant_summary"
settings:controller="com.android.settings.notification.NotificationAssistantPreferenceController"/>
1.2.NotificationAssistantPreferenceController
protected NotificationBackend mNotificationBackend;
>1.isChecked
是否选中需要现编2个组件都不为空
public boolean isChecked() {
ComponentName acn = mNotificationBackend.getAllowedNotificationAssistant();
ComponentName dcn = mNotificationBackend.getDefaultNotificationAssistant();
return (acn != null && acn.equals(dcn));
}
>2.setChecked
public boolean setChecked(boolean isChecked) {
ComponentName cn = isChecked
? mNotificationBackend.getDefaultNotificationAssistant() : null;
if (isChecked) {
//打开开关会弹框提示,ok后最终调用的也是补充3,设置上边的 cn
showDialog(cn);
return false;
} else {
setNotificationAssistantGranted(null);//补充3,使默认组件不可用
return true;
}
}
>3.setNotificationAssistantGranted
设置通知助手是否可用
protected void setNotificationAssistantGranted(ComponentName cn) {
//读取的值是1,不知道干啥的
if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) {
mNotificationBackend.setNASMigrationDoneAndResetDefault(mUserId, cn != null);
}
mNotificationBackend.setNotificationAssistantGranted(cn);//1.3.3
}
1.3.NotificationBackend
//最终调用的NotificationManagerService里的代码
static INotificationManager sINM = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
>1.getAllowedNotificationAssistant
public ComponentName getAllowedNotificationAssistant() {
try {
return sINM.getAllowedNotificationAssistant();
} catch (Exception e) {
return null;
}
}
>2.getDefaultNotificationAssistant
public ComponentName getDefaultNotificationAssistant() {
try {
return sINM.getDefaultNotificationAssistant();
} catch (Exception e) {
return null;
}
}
>3.setNotificationAssistantGranted
public boolean setNotificationAssistantGranted(ComponentName cn) {
try {
sINM.setNotificationAssistantAccessGranted(cn, true);
//设置完以后判断设置的是否和获取的一样
if (cn == null) {
return sINM.getAllowedNotificationAssistant() == null;
} else {
return cn.equals(sINM.getAllowedNotificationAssistant());
}
} catch (Exception e) {
return false;
}
}
>4.setNASMigrationDoneAndResetDefault
public void setNASMigrationDoneAndResetDefault(int userId, boolean loadFromConfig) {
try {
sINM.setNASMigrationDoneAndResetDefault(userId, loadFromConfig);
}
}
2.NotificationManagerService.java
private NotificationListeners mListeners;
private NotificationAssistants mAssistants;
2.1.mService
final IBinder mService = new INotificationManager.Stub() {
>1.getAllowedNotificationAssistantForUser
public ComponentName getAllowedNotificationAssistantForUser(int userId) {
checkCallerIsSystemOrSystemUiOrShell();
//参考4.3
List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
if (allowedComponents.size() > 1) {
//只允许有一个
throw new IllegalStateException(
"At most one NotificationAssistant: " + allowedComponents.size());
}
return CollectionUtils.firstOrNull(allowedComponents);
}
>2.getDefaultNotificationAssistant
public ComponentName getDefaultNotificationAssistant() {
checkCallerIsSystem();
return mAssistants.getDefaultFromConfig();
}
>3.setNotificationAssistantAccessGrantedForUser
public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
int userId, boolean granted) {
try {//参考2.2
setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted,
true);
}
}
2.2.setNotificationAssistantAccessGrantedForUserInternal
protected void setNotificationAssistantAccessGrantedForUserInternal(
ComponentName assistant, int baseUserId, boolean granted, boolean userSet) {
List<UserInfo> users = mUm.getEnabledProfiles(baseUserId);
if (users != null) {
for (UserInfo user : users) {
int userId = user.id;
if (assistant == null) {
//组件为空,说明是要关闭这个功能,那么找到已经allow的,设置granted为false
ComponentName allowedAssistant = CollectionUtils.firstOrNull(
mAssistants.getAllowedComponents(userId));
if (allowedAssistant != null) {
//把allowed改为不允许
setNotificationAssistantAccessGrantedForUserInternal(
allowedAssistant, userId, false, userSet);
}
continue;
}
if (!granted || mAllowedManagedServicePackages.test(assistant.getPackageName(),
userId, mAssistants.getRequiredPermission())) {
mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(),
userId, false, granted);
//参考4.5
mAssistants.setPackageOrComponentEnabled(assistant.flattenToString(),
userId, true, granted, userSet);
getContext().sendBroadcastAsUser(
new Intent(ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
.setPackage(assistant.getPackageName())
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
UserHandle.of(userId), null);
//保存到本地文件
handleSavePolicyFile();
}
}
}
}
2.3.init
void init(WorkerHandler handler, RankingHandler rankingHandler,
//..
// Needs to be set before loadPolicyFile
mAllowedManagedServicePackages = this::canUseManagedServices;//补充1
mPolicyFile = policyFile;
//这个就是读取本地保存的策略了,通知相关的基本都在这里,补充2
loadPolicyFile();
>1.canUseManagedServices
如果有权限需求的话则验证对应的权限。
boolean canUseManagedServices(String pkg, Integer userId, String requiredPermission) {
boolean canUseManagedServices = true;
if (requiredPermission != null) {
try {
if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
!= PackageManager.PERMISSION_GRANTED) {
canUseManagedServices = false;
}
}
}
return canUseManagedServices;
}
>2.loadPolicyFile
- 保存的文件路径 /data/system/notification_policy.xml
protected void loadPolicyFile() {
synchronized (mPolicyFile) {
InputStream infile = null;
try {
infile = mPolicyFile.openRead();
readPolicyXml(infile, false /*forRestore*/, UserHandle.USER_ALL);
} catch (FileNotFoundException e) {
//第一次的话文件应该是不存在的,加载默认的数据
loadDefaultApprovedServices(USER_SYSTEM);
//默认的加入到allow集合里
allowDefaultApprovedServices(USER_SYSTEM);
}
}
}
>3.loadDefaultApprovedServices
void loadDefaultApprovedServices(int userId) {
mListeners.loadDefaultsFromConfig();
mConditionProviders.loadDefaultsFromConfig();
mAssistants.loadDefaultsFromConfig();
}
2.4.setDefaultAssistantForUser
- 小节2.5会调用,以及重置的时候会调用
// public static final String NAS_DEFAULT_SERVICE = "nas_default_service";
// public static final String NAMESPACE_SYSTEMUI = "systemui";
protected void setDefaultAssistantForUser(int userId) {
//补充1
String overrideDefaultAssistantString = DeviceConfig.getProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
if (overrideDefaultAssistantString != null) {
ArraySet<ComponentName> approved = mAssistants.queryPackageForServices(
overrideDefaultAssistantString,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
userId);
for (int i = 0; i < approved.size(); i++) {
//有覆写的默认助手,并且添加到allow集合成功
if (allowAssistant(userId, approved.valueAt(i))) return;
}
}
ArraySet<ComponentName> defaults = mAssistants.getDefaultComponents();
//把默认的组件加入allow集合
for (int i = 0; i < defaults.size(); i++) {
ComponentName cn = defaults.valueAt(i);
if (allowAssistant(userId, cn)) return;
}
}
>1.getProperty
- 根据namespace从Settings.Config里读取map数据,然后从根据name从map里拿到value
public static String getProperty(@NonNull String namespace, @NonNull String name) {
return getProperties(namespace, name).getString(name, null);
}
public static Properties getProperties(@NonNull String namespace, @NonNull String ... names) {
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
return new Properties(namespace,
Settings.Config.getStrings(contentResolver, namespace, Arrays.asList(names)));
}
2.5.allowDefaultApprovedServices
添加默认允许的服务到allow集合
- 监听新用户的add会调用
- 加载默认的配置失败的话会调用
protected void allowDefaultApprovedServices(int userId) {
ArraySet<ComponentName> defaultListeners = mListeners.getDefaultComponents();
for (int i = 0; i < defaultListeners.size(); i++) {
ComponentName cn = defaultListeners.valueAt(i);
allowNotificationListener(userId, cn);
}
ArraySet<String> defaultDnds = mConditionProviders.getDefaultPackages();
for (int i = 0; i < defaultDnds.size(); i++) {
allowDndPackage(userId, defaultDnds.valueAt(i));
}
//参考2.4
setDefaultAssistantForUser(userId);
}
3.NotificationAssistants
public class NotificationAssistants extends ManagedServices {
3.1.loadDefaultsFromConfig
先看下默认的配置哪里来的
protected void loadDefaultsFromConfig() {
loadDefaultsFromConfig(true);
}
protected void loadDefaultsFromConfig(boolean addToDefault) {
ArraySet<String> assistants = new ArraySet<>();
assistants.addAll(Arrays.asList(mContext.getResources().getString(
com.android.internal.R.string.config_defaultAssistantAccessComponent)
.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)));
for (int i = 0; i < assistants.size(); i++) {
ComponentName assistantCn = ComponentName
.unflattenFromString(assistants.valueAt(i));
String packageName = assistants.valueAt(i);
if (assistantCn != null) {
packageName = assistantCn.getPackageName();
}
if (TextUtils.isEmpty(packageName)) {
continue;
}
//参考4.1,查找有对应action和权限的服务,配置参考3.2
ArraySet<ComponentName> approved = queryPackageForServices(packageName,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, USER_SYSTEM);
if (approved.contains(assistantCn)) {
if (addToDefault) {
//加入默认的组件里
addDefaultComponentOrPackage(assistantCn.flattenToString());
} else {
//
mDefaultFromConfig = assistantCn;
}
}
}
}
>1.config_defaultAssistantAccessComponent
我们集成了谷歌应用,所以被覆写了,默认的不是这个
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Component name that should be granted Notification Assistant access -->
<string name="config_defaultAssistantAccessComponent" translatable="false">com.google.android.ext.services/android.ext.services.notification.Assistant</string>
<!-- Package name of the required service extension package. -->
<string name="config_servicesExtensionPackage" translatable="false">com.google.android.ext.services</string>
</resources>
3.2.getConfig
protected Config getConfig() {
Config c = new Config();
c.caption = "notification assistant";
c.serviceInterface = NotificationAssistantService.SERVICE_INTERFACE;
c.xmlTag = TAG_ENABLED_NOTIFICATION_ASSISTANTS;
c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT;
c.bindPermission = Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE;
c.settingsAction = Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS;
c.clientLabel = R.string.notification_ranker_binding_label;
return c;
}
3.3.getDefaultFromConfig
ComponentName getDefaultFromConfig() {
if (mDefaultFromConfig == null) {
loadDefaultsFromConfig(false);
}
return mDefaultFromConfig;
}
4.ManagedServices.java
public ManagedServices(Context context, Object mutex, UserProfiles userProfiles,
IPackageManager pm) {
mContext = context;
mMutex = mutex;
mUserProfiles = userProfiles;
mPm = pm;
mConfig = getConfig();//子类实现,参考3.2
mApprovalLevel = APPROVAL_BY_COMPONENT;//默认是enable/disable 服务组件的
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
4.1.queryPackageForServices
- 查找包下所有满足action的服务,action的配置参考3.2
protected ArraySet<ComponentName> queryPackageForServices(String packageName, int extraFlags,
int userId) {
ArraySet<ComponentName> installed = new ArraySet<>();
final PackageManager pm = mContext.getPackageManager();
Intent queryIntent = new Intent(mConfig.serviceInterface);
if (!TextUtils.isEmpty(packageName)) {
queryIntent.setPackage(packageName);
}
List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
queryIntent,
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA | extraFlags,
userId);
if (installedServices != null) {
for (int i = 0, count = installedServices.size(); i < count; i++) {
ResolveInfo resolveInfo = installedServices.get(i);
ServiceInfo info = resolveInfo.serviceInfo;
ComponentName component = new ComponentName(info.packageName, info.name);
if (!mConfig.bindPermission.equals(info.permission)) {
//判断是否有对应的bind权限,见3.2
continue;
}
installed.add(component);
}
}
return installed;
}
4.2.addDefaultComponentOrPackage
- 根据mApprovalLevel是包还是组件,加入不同的集合里
protected void addDefaultComponentOrPackage(String packageOrComponent) {
if (!TextUtils.isEmpty(packageOrComponent)) {
synchronized (mDefaultsLock) {
if (mApprovalLevel == APPROVAL_BY_PACKAGE) {
mDefaultPackages.add(packageOrComponent);
return;
}
ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
if (cn != null && mApprovalLevel == APPROVAL_BY_COMPONENT) {
mDefaultPackages.add(cn.getPackageName());
mDefaultComponents.add(cn);
return;
}
}
}
}
4.3.getAllowedComponents
还是得看mApproved里的数据哪里来的,参考4.4,4.5
protected List<ComponentName> getAllowedComponents(int userId) {
final List<ComponentName> allowedComponents = new ArrayList<>();
synchronized (mApproved) {
final ArrayMap<Boolean, ArraySet<String>> allowedByType =
mApproved.getOrDefault(userId, new ArrayMap<>());
for (int i = 0; i < allowedByType.size(); i++) {
final ArraySet<String> allowed = allowedByType.valueAt(i);
for (int j = 0; j < allowed.size(); j++) {
ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j));
if (cn != null) {
allowedComponents.add(cn);
}
}
}
}
return allowedComponents;
}
4.4.addApprovedList
protected void addApprovedList(String approved, int userId, boolean isPrimary, String userSet) {
if (TextUtils.isEmpty(approved)) {
approved = "";
}
if (userSet == null) {
userSet = approved;
}
synchronized (mApproved) {
ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
if (approvedByType == null) {
approvedByType = new ArrayMap<>();
mApproved.put(userId, approvedByType);
}
ArraySet<String> approvedList = approvedByType.get(isPrimary);
if (approvedList == null) {
approvedList = new ArraySet<>();
approvedByType.put(isPrimary, approvedList);
}
String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
for (String pkgOrComponent : approvedArray) {
String approvedItem = getApprovedValue(pkgOrComponent);
if (approvedItem != null) {
approvedList.add(approvedItem);
}
}
ArraySet<String> userSetList = mUserSetServices.get(userId);
if (userSetList == null) {
userSetList = new ArraySet<>();
mUserSetServices.put(userId, userSetList);
}
String[] userSetArray = userSet.split(ENABLED_SERVICES_SEPARATOR);
for (String pkgOrComponent : userSetArray) {
String approvedItem = getApprovedValue(pkgOrComponent);
if (approvedItem != null) {
userSetList.add(approvedItem);
}
}
}
}
调用的地方:一种是从settings里迁移过来的(不看了),一种是读取本地存储的(补充1),NMS里调用的
>1.readXml
- allowedManagedServicePackages数据参考2.3.1
public void readXml(
TypedXmlPullParser parser,
TriPredicate<String, Integer, String> allowedManagedServicePackages,
boolean forRestore,
int userId)
//..
if (type == XmlPullParser.START_TAG) {
if (TAG_MANAGED_SERVICES.equals(tag)) {
final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST);
//..
readExtraAttributes(tag, parser, resolvedUserId);
if (allowedManagedServicePackages == null || allowedManagedServicePackages.test(
getPackageName(approved), resolvedUserId, getRequiredPermission())
|| approved.isEmpty()) {
if (mUm.getUserInfo(resolvedUserId) != null) {
//这里
addApprovedList(approved, resolvedUserId, isPrimary, userSetComponent);
}
mUseXml = true;
}
>2.writeXml
也是NMS里调用的,保存数据
public void writeXml(TypedXmlSerializer out, boolean forBackup, int userId) throws IOException {
out.startTag(null, getConfig().xmlTag);
out.attributeInt(null, ATT_VERSION, Integer.parseInt(DB_VERSION));
writeDefaults(out);
4.5.setPackageOrComponentEnabled
eanbled为true的话加入集合里,为false的话移除
protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
boolean isPrimary, boolean enabled, boolean userSet) {
synchronized (mApproved) {
ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
if (allowedByType == null) {
allowedByType = new ArrayMap<>();
mApproved.put(userId, allowedByType);
}
ArraySet<String> approved = allowedByType.get(isPrimary);
if (approved == null) {
approved = new ArraySet<>();
allowedByType.put(isPrimary, approved);
}
String approvedItem = getApprovedValue(pkgOrComponent);
if (approvedItem != null) {
if (enabled) {
approved.add(approvedItem);
} else {
approved.remove(approvedItem);
}
}
ArraySet<String> userSetServices = mUserSetServices.get(userId);
if (userSetServices == null) {
userSetServices = new ArraySet<>();
mUserSetServices.put(userId, userSetServices);
}
if (userSet) {
userSetServices.add(pkgOrComponent);
} else {
userSetServices.remove(pkgOrComponent);
}
}
//最终重新bind或者unbind服务
rebindServices(false, userId);
}
>1.getApprovedValue
根据mApprovalLevel返回包或者组件
private String getApprovedValue(String pkgOrComponent) {
if (mApprovalLevel == APPROVAL_BY_COMPONENT) {
if(ComponentName.unflattenFromString(pkgOrComponent) != null) {
return pkgOrComponent;
}
return null;
} else {
return getPackageName(pkgOrComponent);
}
}
>2.getPackageName
protected String getPackageName(String packageOrComponent) {
final ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
if (component != null) {
return component.getPackageName();
} else {
return packageOrComponent;
}
}
5.NotificationAssistantService
public abstract class NotificationAssistantService extends NotificationListenerService {
5.1.常量
>1.SERVICE_INTERFACE
public static final String SERVICE_INTERFACE
= "android.service.notification.NotificationAssistantService";
6.ConditionProviders.java
同样继承的小节4
public class ConditionProviders extends ManagedServices {
6.1.构造方法
public ConditionProviders(Context context, UserProfiles userProfiles, IPackageManager pm) {
super(context, new Object(), userProfiles, pm);
//获取系统属性的值,以逗号隔开解析为数组,如果没有的话用默认的数组
mSystemConditionProviderNames = safeSet(PropConfig.getStringArray(mContext,
"system.condition.providers",
R.array.config_system_condition_providers));
mApprovalLevel = APPROVAL_BY_PACKAGE;//这里的级别是包
}
>1.config_system_condition_providers
默认值
<!-- Enabled built-in zen mode condition providers -->
<string-array translatable="false" name="config_system_condition_providers">
<item>countdown</item>
<item>schedule</item>
<item>event</item>
</string-array>