在实际定制开发中,往往有这样的客户需求:在白名单内的应用能允许安装,不在白名单的应用禁止安装,从而避免系统会被安装流氓软件。
我们都知道安卓系统应用安装都通过系统安装服务来完成--PackageManagerService
系统源码路径:frameworksaseservicescorejavacomandroidserverpmPackageManagerService.java
系统有4种应用的安装方式:
1.系统预置应用安装---开机时完成,没有安装界面
2.通过网络应用市场下载应用安装---有安装界面
3.ADB工具安装---没有安装界面
4.第三方应用安装---通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面
在系统安装应用期间,可以通过log跟踪源码的执行,你就会发现第三方应用的安装都会经过
PackageManagerService.java的installPackageLI函数处理
installPackageLI函数
此函数作用就是检测安装包的信息以及完整,这里回到我所需要的安装判断条件---应用包名。在安装期间,通过预置应用白名单列表与获取到正在安装的应用包名实现对比,在列表中的不拦截,不在列表中的就直接退出。
预置白名单列表有两种方式:
第一种:通过在installPackageLI函数中提前写死白名单应该
第二种:通过在persist分区存储配置文件,可实现自由增加白名单
第一种方式没啥好解释了,就是提前准备好应该白名单,安装应用时进行包名对比,直接上代码:
boolean isWhiteListApp = false;
String[] isWhiteListApppackageName = {"
"com.xxx.xxx", "com.xxxx.xxx", "com.xxx.xxxx"};
for (int i = 0; i < isWhiteListApppackageName.length; i ) {
if ((pkg.packageName != null) && (pkg.packageName.equals(isWhiteListApppackageName[i]))) {
Slog.e(TAG, "Instant app package isWhiteListApp1" isWhiteListApppackageName[i]);
isWhiteListApp=true;
break;
}
}
if (!isWhiteListApp) {
Slog.e(TAG, "Instant app package 2 " pkg.packageName);
res.setError(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Signature mismatch");
return;
}
第二种方式,通过在系统预置WhiteListApp.conf文件,在安装过程中对比文件中的包名,实现安装拦截。
预置WhiteListApp.conf到persist分区,因为system_app可对这个分区进行读写,从而实现动态修改白名单应用。
WhiteListApp.conf内容如下:
com.xxx.xxx
com.xxx.xxx
代码块:
1、在installPackageLI添加逻辑判断:
if(!isWhiteListApp(pkg.packageName)){
Log.d(TAG,"--isWhiteListApp--");
res.setError(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
"this is not in the whitelist. packageName:" pkg.packageName);
return;
}
2、在PackageManagerService.java最后增加文件读取函数:
private boolean isWhiteListApp(String packagename){
ArrayList<String> whiteListApp = new ArrayList<String>();
try{
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("/mnt/vendor/persist/WhiteListApp.conf")));
String line ="";
while ((line = br.readLine()) != null){
whiteListApp.add(line);
}
br.close();
}catch(java.io.FileNotFoundException ex){
return false;
}catch(java.io.IOException ex){
return false;
}
Iterator<String> it = whiteListApp.iterator();
while (it.hasNext()) {
String whitelistItem = it.next();
if (whitelistItem.equals(packagename)) {
return true;
}
}
return false;
}
3、预置到系统,增加权限
PRODUCT_COPY_FILES = vendor/simcom/3rd-party/WhiteListApp.conf:persist/WhiteListApp.conf
chown system system /mnt/vendor/persist/WhiteListApp.conf
chmod 0664 /mnt/vendor/persist/WhiteListApp.conf
结语:
实现应用白名单的两种方式,各有优点,开发者可以择优选择。