2021년 9월 12일 일요일

scrcpy (안드로이드 단말을 PC에 연결해서 화면 보기, 스크린 미러링) #3 소스 분석

 

jar파일을 android에서 실행시킬 수 있을까?

구글링을 해보면 할 수 없다는 내용이 대부분입니다. 

여기에서는 어떤 식으로 jar 파일을 생성 했는지 알아보도록 하겠습니다.


안드로이드의 기본이라면 manifest 부터 봐야겠습니다.

https://github.com/Genymobile/scrcpy/blob/master/server/src/main/AndroidManifest.xml

원래는 여기에 activity 정보가 기록되야 하지만 패키지 이름만 있을뿐 특이점이라면 아무것도 없습니다.


결국 adb에서 jar 파일을 보내고 나서 실행하는 부분을 다시 살펴보자면, 아래 소스에서 찾아볼 수 있습니다.

https://github.com/Genymobile/scrcpy/blob/master/app/src/server.c

static process_t
execute_server(struct server *server, const struct server_params *params) {
    char max_size_string[6];
    char bit_rate_string[11];
    char max_fps_string[6];
    char lock_video_orientation_string[5];
    char display_id_string[11];
    sprintf(max_size_string, "%"PRIu16, params->max_size);
    sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
    sprintf(max_fps_string, "%"PRIu16, params->max_fps);
    sprintf(lock_video_orientation_string, "%"PRIi8,
            params->lock_video_orientation);
    sprintf(display_id_string, "%"PRIu32, params->display_id);
    const char *const cmd[] = {
        "shell",
        "CLASSPATH=" DEVICE_SERVER_PATH,
        "app_process",
#ifdef SERVER_DEBUGGER
# define SERVER_DEBUGGER_PORT "5005"
# ifdef SERVER_DEBUGGER_METHOD_NEW
        /* Android 9 and above */
        "-XjdwpProvider:internal -XjdwpOptions:transport=dt_socket,suspend=y,"
        "server=y,address="
# else
        /* Android 8 and below */
        "-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address="
# endif
            SERVER_DEBUGGER_PORT,
#endif
        "/", // unused
        "com.genymobile.scrcpy.Server",
        SCRCPY_VERSION,
        log_level_to_server_string(params->log_level),
        max_size_string,
        bit_rate_string,
        max_fps_string,
        lock_video_orientation_string,
        server->tunnel_forward ? "true" : "false",
        params->crop ? params->crop : "-",
        "true", // always send frame meta (packet boundaries + timestamp)
        params->control ? "true" : "false",
        display_id_string,
        params->show_touches ? "true" : "false",
        params->stay_awake ? "true" : "false",
        params->codec_options ? params->codec_options : "-",
        params->encoder_name ? params->encoder_name : "-",
        params->power_off_on_close ? "true" : "false",
    };
#ifdef SERVER_DEBUGGER
    LOGI("Server debugger waiting for a client on device port "
         SERVER_DEBUGGER_PORT "...");
    // From the computer, run
    //     adb forward tcp:5005 tcp:5005
    // Then, from Android Studio: Run > Debug > Edit configurations...
    // On the left, click on '+', "Remote", with:
    //     Host: localhost
    //     Port: 5005
    // Then click on "Debug"
#endif
    return adb_execute(server->serial, cmd, ARRAY_LEN(cmd));
}


cmd 내용을 보자면 아래과 같은 형태로 실행됩니다.

adb shell CLASSPATH=/data/local/tmp/scrcpy-server.jar app_process -XjdwpProvider:internal -XjdwpOptions:transport=dt_socket,suspend=y, server=y,address= / com.genymobile.scrcpy.Server ... 대충 이런형태가 됩니다.


app_process에 대한 정보는 여기도 참고 바랍니다.

https://codechacha.com/ko/convert-jar-to-dex-and-run-on-device/


핵심은 app_process를 실행키시면서 옵션을 전달하는 형태가 되며, app_process란 process를 실행시키기 위한 zygote(수정란) 으로 생각하면 됩니다.


jar 파일은 여기에 있는 소스들을 빌드해서 만들어지며

https://github.com/Genymobile/scrcpy/tree/master/server/src/main/java/com/genymobile/scrcpy

java의 특성상 실행은 static main 함수를 찾아서 실행하게 됩니다.

    public static void main(String... args) throws Exception {

해당 소스는 server.java파일 내에 있습니다.


댓글 없음:

댓글 쓰기