Android Framework 常见解决方案(23)三方应用APP启动绑核setAffinity设置

1 原理解读

一般来说这个需求主要是为了应用启动时设定绑核相关操作,但是如果没有三方应用的源码想要让其绑定再其他核心上就要修改framework源码了。framework源码修改的原理是:在zygote创建应用子进程(Fork操作)时做白名单处理,针对不同的应用APP进程进行可以有不同的绑核策略。

关于Zygote的初始化以及创建APP进程的流程这里就不多说了,最终创建进程回调用到这里:com_android_internal_os_Zygote.cpp中的

com_android_internal_os_Zygote_nativeForkAndSpecialize方法。代码实现如下:

cpp 复制代码
com_android_internal_os_Zygote_nativeForkAndSpecialize(...){
//...
    if (pid == 0) {
        SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
                         mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
                         instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
                         allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
                         mount_storage_dirs == JNI_TRUE);
    }
//...
}

2 修改方案(Android Q R S)

修改文件为:AOSP/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp,这里主要给出了3个应用xxx1、xxx2、xxx3,绑核策略分别为7,456,234,根据此需求,具体修改内容为:

cpp 复制代码
// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags,
                             jobjectArray rlimits, jlong permitted_capabilities,
                             jlong effective_capabilities, jint mount_external,
                             jstring managed_se_info, jstring managed_nice_name,
                             bool is_system_server, bool is_child_zygote,
                             jstring managed_instruction_set, jstring managed_app_data_dir,
                             bool is_top_app, jobjectArray pkg_data_info_list,
                             jobjectArray allowlisted_data_info_list, bool mount_data_dirs,
                             bool mount_storage_dirs) {
    const char* process_name = is_system_server ? "system_server" : "zygote";
    auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
    auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);

    auto se_info = extract_fn(managed_se_info);
    auto nice_name = extract_fn(managed_nice_name);
    auto instruction_set = extract_fn(managed_instruction_set);
    auto app_data_dir = extract_fn(managed_app_data_dir);

    // Keep capabilities across UID change, unless we're staying root.
    if (uid != 0) {
        EnableKeepCapabilities(fail_fn);
    }

    SetInheritable(permitted_capabilities, fail_fn);

    DropCapabilitiesBoundingSet(fail_fn);
    //...
    const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
    const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;

    if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
        fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
                             is_system_server, se_info_ptr, nice_name_ptr));
    }

    // Make it easier to debug audit logs by setting the main thread's name to the
    // nice name rather than "app_process".
    
    if (nice_name.has_value()) {
        SetThreadName(nice_name.value());
+        //xxx1应用绑定核心7
+        if(strncmp(nice_name.value().c_str(),"com.xxx.xxx1",sizeof("com.xxx.xxx1"))==0){
+            cpu_set_t mask;
+            CPU_ZERO(&mask);
+            CPU_SET(7, &mask);
+            int ret = sched_setaffinity(0, sizeof(mask), &mask);
+            if (ret != 0) {
+                ALOGE("xxx1,setSchedAffinity call failure,ret:%d,(%s)", ret,nice_name.value().c_str());
+            }else{
+                ALOGE("xxx1,setSchedAffinity call success,ret==0,(%s)", nice_name.value().c_str());
+            }
+        }
+        //xxx2应用绑定核心4、5、6
+        if(strncmp(nice_name.value().c_str(),"com.xxx.xxx2",sizeof("com.xxx.xxx2"))==0){
+            cpu_set_t mask;
+            CPU_ZERO(&mask);
+            CPU_SET(6, &mask);
+            CPU_SET(5, &mask);
+            CPU_SET(4, &mask);
+            int ret = sched_setaffinity(0, sizeof(mask), &mask);
+            if (ret != 0) {
+                ALOGE("xxx2,setSchedAffinity call failure,ret:%d,(%s)", ret,nice_name.value().c_str());
+            }else{
+                ALOGE("xxx2,setSchedAffinity call success,ret==0,(%s)", nice_name.value().c_str());
+            }
+        }
+        //xxx3应用绑定核心2、3、4
+        if(strncmp(nice_name.value().c_str(),"com.xxx.xxx3",sizeof("com.xxx.xxx3"))==0){
+            cpu_set_t mask;
+            CPU_ZERO(&mask);
+            CPU_SET(4, &mask);
+            CPU_SET(3, &mask);
+            CPU_SET(2, &mask);
+            int ret = sched_setaffinity(0, sizeof(mask), &mask);
+            if (ret != 0) {
+                ALOGE("xxx3,setSchedAffinity call failure,ret:%d,(%s)", ret,nice_name.value().c_str());
+           }else{
+                ALOGE("xxx3,setSchedAffinity call success,ret==0,(%s)", nice_name.value().c_str());
+            }
+        }        
    } else if (is_system_server) {
        SetThreadName("system_server");
    }
    
    // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
    UnsetChldSignalHandler();

    if (is_system_server) {
        env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags);
        if (env->ExceptionCheck()) {
            fail_fn("Error calling post fork system server hooks.");
        }

        // TODO(b/117874058): Remove hardcoded label here.
        static const char* kSystemServerLabel = "u:r:system_server:s0";
        if (selinux_android_setcon(kSystemServerLabel) != 0) {
            fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
        }
    }

    if (is_child_zygote) {
        initUnsolSocketToSystemServer();
    }

    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                              is_system_server, is_child_zygote, managed_instruction_set);

    // Reset the process priority to the default value.
    setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);

    if (env->ExceptionCheck()) {
        fail_fn("Error calling post fork hooks.");
    }
}
相关推荐
图王大胜10 天前
Android Framework AMS(10)广播组件分析-1
android·framework·应用·组件·broadcast·ams·广播
胖虎125 天前
实现iOS Framework生成全流程详解
ios·framework·swift·xcframework
千里马学框架1 个月前
安卓窗口wms/input小知识NO_INPUT_CHANNEL剖析
android·车载系统·framework·wms·input·系统开发
图王大胜1 个月前
Android Framework AMS(06)startActivity分析-3(补充:onPause和onStop相关流程解读)
android·framework·activity·startactivity·onstop·超时设计·onpause
风恋残雪1 个月前
OpenGL RHI优化
优化·卡顿·性能·rhi
图王大胜1 个月前
Android Framework AMS(05)startActivity分析-2(ActivityThread启动到Activity拉起)
android·framework·ams·startactivity
图王大胜1 个月前
Android Framework AMS(04)startActivity分析-1(am启动到ActivityThread启动)
android·framework·ams·activity·startactivity
千里马学框架1 个月前
安卓如何实现双击触摸唤醒点亮屏幕功能-源码分析linage os高通平台
android·智能手机·framework·锁屏·车机车载·双击·亮屏
图王大胜1 个月前
Android SystemUI组件(11)SystemUIVisibility解读
android·framework·systemui·visibility
图王大胜1 个月前
Android Framework AMS(01)AMS启动及相关初始化1-4
android·framework·ams·systemserver