看下DynamicIndexableContentMonitor.java代码:
public void register(Activity activity, int loaderId) { ... boolean hasFeaturePrinting = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING); ... if (hasFeaturePrinting) { activity.getLoaderManager().initLoader(loaderId, null, this); } ...有木有发现一个熟悉的代码?
对,代码里再次出现了一个有关SystemFeature的判断!上一次出现时SystemServer启动服务前也做了相同的判断。
所以要裁剪掉打印机服务,我们只需要将FEATURE_PRINTING关闭即可。
通过修改SystemFeature判断后,在SystemServer里面的裁剪代码就可以不再添加了。但是有些服务的裁剪Android并没有添加系统特性的处理,所以还是建议使用我的方法进行裁剪。
SystemFeature加载流程先看一看FEATURE_PRINTING
PackageManager.java
/** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: * The device supports printing. */ @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_PRINTING = "android.software.print"; /** * Get a list of features that are available on the * system. * * @return An array of FeatureInfo classes describing the features * that are available on the system, or null if there are none(!!). */ public abstract FeatureInfo[] getSystemAvailableFeatures(); /** * Check whether the given feature name is one of the available features as * returned by {@link #getSystemAvailableFeatures()}. This tests for the * presence of <em>any</em> version of the given feature name; use * {@link #hasSystemFeature(String, int)} to check for a minimum version. * * @return Returns true if the devices supports the feature, else false. */ public abstract boolean hasSystemFeature(String name); /** * Check whether the given feature name and version is one of the available * features as returned by {@link #getSystemAvailableFeatures()}. Since * features are defined to always be backwards compatible, this returns true * if the available feature version is greater than or equal to the * requested version. * * @return Returns true if the devices supports the feature, else false. */ public abstract boolean hasSystemFeature(String name, int version);都是抽象方法,我们去PMS查找对应的实现
PackageManagerService.java
public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() { synchronized (mPackages) { final ArrayList<FeatureInfo> res = new ArrayList<>(mAvailableFeatures.values()); final FeatureInfo fi = new FeatureInfo(); fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version", FeatureInfo.GL_ES_VERSION_UNDEFINED); res.add(fi); return new ParceledListSlice<>(res); } } @Override public boolean hasSystemFeature(String name, int version) { synchronized (mPackages) { final FeatureInfo feat = mAvailableFeatures.get(name); if (feat == null) { return false; } else { return feat.version >= version; } } }这里的逻辑都是通过mAvailableFeatures得到所有的feature,查找该成员变量的相关代码
final ArrayMap<String, FeatureInfo> mAvailableFeatures; SystemConfig systemConfig = SystemConfig.getInstance(); mGlobalGids = systemConfig.getGlobalGids(); mSystemPermissions = systemConfig.getSystemPermissions(); mAvailableFeatures = systemConfig.getAvailableFeatures();了解到,首先获取一个SystemConfig的单例,然后通过getAvailableFeatures方法获取可用的feature。
SystemConfig.java
// These are the features this devices supports that were read from the // system configuration files. final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); public ArrayMap<String, FeatureInfo> getAvailableFeatures() { return mAvailableFeatures; } private void addFeature(String name, int version) { FeatureInfo fi = mAvailableFeatures.get(name); if (fi == null) { fi = new FeatureInfo(); fi.name = name; fi.version = version; mAvailableFeatures.put(name, fi); } else { fi.version = Math.max(fi.version, version); } } private void removeFeature(String name) { if (mAvailableFeatures.remove(name) != null) { Slog.d(TAG, "Removed unavailable feature " + name); } }根据mAvailableFeatures的注释,设备支持的feature是从配置文件里读取出来的。调用读取配置文件的地方是:
SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); // Read configuration from the old permissions dir readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); // Allow ODM to customize system configs around libs, features and apps int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS; readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); // Only allow OEM to customize features readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES); readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES); }到此就很明白了,它是读取了几个目录:
/system/etc/permission
/system/etc/sysconfig
/oem/etc/permission
/oem/etc/sysconfig
/odm/etc/permission
/odm/etc/sysconfig
然后遍历xml文件,进行解析处理。SystemFeature就是解析的Feature标签。
最后再总结一下加载流程:
屏蔽SystemFeature知道原理就好做了,在系统扫描的几个目录中使用grep命令查找控制打印机的字串,找到: