前言:
安卓底层对于不同APP通常有不同的参数配置。这个功能可以通过接口实现,让APP自己决定具体的参数配置。但是在一些情况下,APP自己设置的参数并不一定符合所有客户的需求,所以需要厂商根据自己实际情况去做不同改变。
下面以设置vidoe的比特率为例介绍具体实现方法:
方法一. 在native层获取APP name然后做不同处理
1. 包含头文件
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#ifndef __ANDROID_VNDK___
#include <binder/IPermissionController.h>
#endif
2. 获取包名:
String16 mClientName;
const uid_t uid = IPCThreadState::self()->getCallingUid();
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("permission"));
if (binder == 0) {
ALOGE("Cannot get permission service");
return;
}
sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
Vector<String16> packages;
permCtrl->getPackagesForUid(uid, packages);
if (packages.isEmpty()) {
ALOGE("No packages for calling UID");
}else {
mClientName = packages[0];
}
3. 判断是否是某个APP并做相应处理
if(!String16("com.xxx.mm").compare(mClientName)){
msg->setInt32("bitrate", bitrate);
}
此方法的问题: 只能获取当前APP的name,无法得知当前APP的操作。
方法二:在activity.java中获取APP的操作,并设置系统属性,在native中获取属性,并做相应处理
1. 在java中获取APP的操作
import android.os.SystemProperties;
final void attach(……){
mComponent = intent.getComponent(); // 获取APP name及当前的操作
if(needChangeBitRate(mComponent.toShortString())){ // 判断是否是需要改变的APP操作
SystemProperties.set("sys.highbitrate", "1"); // 设置系统属性
}
else{
SystemProperties.set("sys.highbitrate", "0"); // 设置系统属性
}
}
2. 在native中获取系统属性,并做响应处理
#include <cutils/properties.h>
……
string str;
property_get("sys.highbitrate", str);
if(str == "1")
{
msg->setInt32("bitrate", 2400000);
}
此处有坑!!!!
事实证明上面的方法二并不可用,运行过程中,SystemProperties.set("sys.highbitrate", "1");总是报错: Unable to set property "sys.xiaomi.highratevideo" to "yes": connection failed; errno=13 (Permission denied)。从log就可以看出是权限问题。网上搜了一大推,全是关于设置Manifest和makefile的,但是此处并不适用。后来才知道,SystemProperties.set( key, value);此处的key的前缀是与权限相关的。
具体权限对应前缀:
vendor image里 要用vendor 开头的前缀
system image也有默认,可以不加,系统会自己加上。
然后我试了sys/persist/ro/audio/不加,然后发现所有的都还是一样的报错。
然后发现是selinux相关,设置adb shell setenforce 0,然后报错就会变成Unable to set property "ro.highratevideo" to "yes": error code: 0xb。
最后改为: SystemProperties.set("persist.highbitrate", "1");
并adb shell setenforce 0,
ok,可以成功设置。
但是adb shell setenforce 0,是禁掉了selinux的相关检查,只能用来临时测试。如果要用来正式改动,还是需要去文件里面设置相关权限。具体可参考下面。
分析selinux权限缺失的解决办法:
sepolicy 有两种类型,一种是进程,一种是文件。 可分别用ps -Z和ls -Z查看进程和文件的selinux权限。
分析过程:
缺少什么权限: { search }权限,
谁缺少权限: scontext=u:r:system_app:s0
对哪个文件缺少权限:tcontext=u:object_r:fs_bpf:s0
什么类型的文件: tclass=dir
完整的意思: system_app进程对fs_bpf类型的dir缺少search权限。
解决方法:
关于权限添加的文件:
platform/system/sepolicy
xxui/system/sepolicy
在xxui/system/sepolicy 中找到system_server.te文件添加
allow system_app fs_bpf:dir { search };
ps:
针对dir缺少的任何权限,建议赋予create_dir_perms,基本涵盖对dir的所有权限,比如:
{ open search write read rename create rmdir getattr }等等。
针对file缺少的任何权限,建议赋予rwx_file_perms,基本涵盖对file的所有权限,比如:
包含{ open read write open execute getattr create ioctl }等等。
最后,关于这种和权限相关的改动,很有可能引起TS类测试fail,一定要跑一遍试试!!!
还有这种改动每次activity发生变化都需要设置全局系统属性,很有可能引起系统卡顿,请慎重操作!!!