Android - hasSystemFeature判断设备是否
经常用到 pm().hasSystemFeature,但是没了解过它的具体实现。
所以根据SDK31 (Android 12) 源码,跟了一遍具体的实现流程。
1.客户端使用
PackageManager pm = context.getPackageManager();
boolean hasWIFIFeature = pm().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
2. PMS
- PackageManager 抽象类
public abstract boolean hasSystemFeature(@NonNull String featureName);
- ApplicationPackageManager实现类
hasSystemFeature(String name)
->hasSystemFeature(String name, int version)
mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version));
//(1) 查询的字符串封装成了HasSystemFeatureQuery
//(2) mHasSystemFeatureCache 为 PropertyInvalidatedCache 实现类的对象(需要实现 recompute方法,进而调用PMS)
- PackageManagerService (在上面的recompute方法中,通过 ActivityThread 获取)
hasSystemFeature
根据传入的name, 在 mAvailableFeatures map 中查找
ArrayMap<String, FeatureInfo> mAvailableFeatures = systemConfig.getAvailableFeatures();
3. SystemConfig.getAvailableFeatures
- 直接返回内部map 变量: mAvailableFeatures
- 该map通过 addFeature(String name, int version) 添加
- addFeature 在readPermissionsFromXml(File permFile, int permissionFlag)中被调用
- readPermissionsFromXml 在 readPermissions(File libraryDir, int permissionFlag)中被调用
- readPermissions 在 readAllPermissions 中被调用
- readAllPermissions 在 SystemConfig 构造函数中 被调用
重点 readAllPermissions
读取设备以下目录的xml文件 ,查找有 feature 定义的
(1)etc/sysconfig
(2)etc/permissions
(3) (1)和(2) vendor /ODM/ OEM/system_ext 自定义的目录
XML来源为native目录下的文件
例如:
frameworks/native/data/etc/android.hardware.bluetooth.xml#1
-->
<!-- Adds the feature indicating support for the Bluetooth API -->
<permissions>
<feature name="android.hardware.bluetooth" />
</permissions>
存放在设备的目录可能为
/vendor/etc/permissions/android.hardware.bluetooth.xml
4.参考:
https://www.jianshu.com/p/ad3b8c56d203
https://blog.csdn.net/u013398960/article/details/78582096