반응형


아예 코드를 새로 알려주세요.  - Android.mk를 가진  aaa라는 모듈 (C 데몬)은 send(),  register() (이 둘의 반환값은 모두 "hello world") 이 2개의  API를 제공하는 AIDL 서버 입니다.


네, 처음부터 완전히 새로 작성하겠습니다.
디렉토리 구조
external/aaa/
├── Android.mk
├── aidl/
│   └── com/
│       └── example/
│           └── IAaaService.aidl
├── include/
│   ├── aaa_core.h
│   └── aidl_server.h
├── src/
│   ├── aaa_main.c
│   ├── aaa_core.c
│   └── aidl_server.cpp
└── sepolicy/
    └── aaa.te
1. AIDL 인터페이스 정의
external/aaa/aidl/com/example/IAaaService.aidl
package com.example;

interface IAaaService {
    String send();
    String register();
}
2. Android.mk
external/aaa/Android.mk
LOCAL_PATH := $(call my-dir)

###########################################
# aaa 데몬
###########################################

include $(CLEAR_VARS)

LOCAL_MODULE := aaa
LOCAL_MODULE_TAGS := optional
LOCAL_PROPRIETARY_MODULE := true
LOCAL_VENDOR_MODULE := true

# AIDL 파일
LOCAL_SRC_FILES := \
    aidl/com/example/IAaaService.aidl

LOCAL_AIDL_INCLUDES := \
    $(LOCAL_PATH)/aidl

# C/C++ 소스 파일
LOCAL_SRC_FILES += \
    src/aaa_main.c \
    src/aaa_core.c \
    src/aidl_server.cpp

LOCAL_CPP_EXTENSION := .cpp

# 헤더 경로
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include

# 라이브러리
LOCAL_SHARED_LIBRARIES := \
    libc++ \
    liblog \
    libcutils \
    libutils \
    libbinder_ndk \
    libbase

# 헤더 라이브러리
LOCAL_HEADER_LIBRARIES := \
    libbinder_ndk_headers

# 컴파일 플래그
LOCAL_CFLAGS := -Wall -Werror
LOCAL_CPPFLAGS := -std=c++17 -Wall -Werror

include $(BUILD_EXECUTABLE)
3. C 헤더
external/aaa/include/aaa_core.h
#ifndef AAA_CORE_H
#define AAA_CORE_H

#ifdef __cplusplus
extern "C" {
#endif

// C 데몬 코어 함수
void aaa_core_init(void);
void aaa_core_cleanup(void);
void aaa_core_process(void);

#ifdef __cplusplus
}
#endif

#endif // AAA_CORE_H
external/aaa/include/aidl_server.h
#ifndef AIDL_SERVER_H
#define AIDL_SERVER_H

#ifdef __cplusplus
extern "C" {
#endif

// AIDL 서버 초기화/정리
int aidl_server_init(void);
void aidl_server_cleanup(void);

#ifdef __cplusplus
}
#endif

#endif // AIDL_SERVER_H
4. C 소스 파일
external/aaa/src/aaa_core.c
#include "aaa_core.h"
#include <stdio.h>
#include <log/log.h>

void aaa_core_init(void) {
    ALOGI("aaa core initialized");
    printf("aaa core initialized\n");
}

void aaa_core_cleanup(void) {
    ALOGI("aaa core cleanup");
    printf("aaa core cleanup\n");
}

void aaa_core_process(void) {
    ALOGI("aaa core processing...");
    // 데몬 로직 처리
}
external/aaa/src/aaa_main.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <log/log.h>
#include "aaa_core.h"
#include "aidl_server.h"

// Binder 스레드 풀 시작 (C++에서 구현)
extern void start_binder_threadpool(void);

static volatile int running = 1;

void signal_handler(int sig) {
    ALOGI("Received signal %d, shutting down", sig);
    running = 0;
}

int main(int argc, char** argv) {
    ALOGI("aaa daemon starting...");
    printf("aaa daemon starting...\n");
    
    // 시그널 핸들러 등록
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    // C 코어 초기화
    aaa_core_init();
    
    // AIDL 서버 초기화
    if (aidl_server_init() < 0) {
        ALOGE("Failed to initialize AIDL server");
        fprintf(stderr, "Failed to initialize AIDL server\n");
        aaa_core_cleanup();
        return 1;
    }
    
    // Binder 스레드 풀 시작 (백그라운드)
    start_binder_threadpool();
    
    ALOGI("aaa daemon ready");
    printf("aaa daemon ready\n");
    
    // 메인 루프
    while (running) {
        aaa_core_process();
        sleep(5);  // 5초마다 처리
    }
    
    // 정리
    ALOGI("aaa daemon shutting down");
    printf("aaa daemon shutting down\n");
    
    aidl_server_cleanup();
    aaa_core_cleanup();
    
    return 0;
}
5. C++ AIDL 서버 구현
external/aaa/src/aidl_server.cpp
#include "aidl_server.h"
#include <aidl/com/example/BnAaaService.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android-base/logging.h>
#include <memory>

using aidl::com::example::IAaaService;
using aidl::com::example::BnAaaService;

// AIDL 서버 구현
class AaaServiceImpl : public BnAaaService {
public:
    AaaServiceImpl() {
        LOG(INFO) << "AaaServiceImpl created";
    }
    
    ~AaaServiceImpl() {
        LOG(INFO) << "AaaServiceImpl destroyed";
    }
    
    // send() API 구현
    ndk::ScopedAStatus send(std::string* _aidl_return) override {
        LOG(INFO) << "send() called";
        *_aidl_return = "hello world";
        return ndk::ScopedAStatus::ok();
    }
    
    // register() API 구현
    ndk::ScopedAStatus register_(std::string* _aidl_return) override {
        LOG(INFO) << "register() called";
        *_aidl_return = "hello world";
        return ndk::ScopedAStatus::ok();
    }
};

// 전역 서비스 인스턴스
static std::shared_ptr<AaaServiceImpl> gService = nullptr;

extern "C" {

int aidl_server_init(void) {
    LOG(INFO) << "Initializing AAA AIDL service";
    
    // 서비스 인스턴스 생성
    gService = std::make_shared<AaaServiceImpl>();
    
    // 서비스 이름
    const std::string instance = std::string() + IAaaService::descriptor + "/default";
    
    // ServiceManager에 등록
    binder_status_t status = AServiceManager_addService(
        gService->asBinder().get(),
        instance.c_str()
    );
    
    if (status != STATUS_OK) {
        LOG(ERROR) << "Failed to register service: " << status;
        gService = nullptr;
        return -1;
    }
    
    LOG(INFO) << "AAA service registered as: " << instance;
    return 0;
}

void aidl_server_cleanup(void) {
    LOG(INFO) << "Cleaning up AAA AIDL service";
    gService = nullptr;
}

// Binder 스레드 풀 시작 (Non-blocking)
void start_binder_threadpool(void) {
    LOG(INFO) << "Starting Binder thread pool";
    ABinderProcess_setThreadPoolMaxThreadCount(4);
    ABinderProcess_startThreadPool();
}

} // extern "C"
6. Init RC 파일
vendor/your_vendor/etc/init/aaa.rc
service aaa /vendor/bin/aaa
    class late_start
    user root
    group root system
    seclabel u:r:aaa:s0
    disabled

on property:aaa.start=1
    start aaa

on property:aaa.start=0
    stop aaa

on boot
    setprop aaa.start 0
7. SEPolicy
vendor/your_vendor/sepolicy/aaa.te
# aaa 데몬 타입
type aaa, domain;
type aaa_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(aaa)

# Binder 사용
binder_use(aaa)

# ServiceManager 접근
allow aaa servicemanager:binder { call transfer };
allow aaa aaa_service:service_manager add;

# 클라이언트 허용
binder_call(system_server, aaa)
binder_call(platform_app, aaa)
binder_call(priv_app, aaa)
binder_call(untrusted_app, aaa)

# 로그
allow aaa kmsg_device:chr_file write;

# 프로세스 권한
allow aaa self:process signal;
vendor/your_vendor/sepolicy/service.te
type aaa_service, service_manager_type, vendor_service;
vendor/your_vendor/sepolicy/service_contexts
com.example.IAaaService/default         u:object_r:aaa_service:s0
vendor/your_vendor/sepolicy/file_contexts
/vendor/bin/aaa                         u:object_r:aaa_exec:s0
8. 빌드 및 테스트
빌드
# aaa 빌드
m aaa

# 결과 확인
ls out/target/product/*/vendor/bin/aaa

# 디바이스에 푸시
adb push out/target/product/*/vendor/bin/aaa /vendor/bin/
adb shell chmod 755 /vendor/bin/aaa
실행
# 수동 실행
adb shell /vendor/bin/aaa

# Property로 실행
adb shell setprop aaa.start 1

# 프로세스 확인
adb shell ps -A | grep aaa
서비스 확인
# 서비스 등록 확인
adb shell service list | grep IAaaService

# 출력 예:
# 123    com.example.IAaaService/default: [com.example.IAaaService]
AIDL 호출 테스트
# send() 호출 (service call 명령어 사용)
adb shell service call com.example.IAaaService/default 1

# register() 호출
adb shell service call com.example.IAaaService/default 2
9. 클라이언트 예제 (테스트용)
test_client.cpp
#include <aidl/com/example/IAaaService.h>
#include <android/binder_manager.h>
#include <android-base/logging.h>
#include <iostream>

using aidl::com::example::IAaaService;

int main() {
    const std::string instance = std::string() + IAaaService::descriptor + "/default";
    
    AIBinder* binder = AServiceManager_checkService(instance.c_str());
    if (binder == nullptr) {
        std::cerr << "Failed to get service" << std::endl;
        return 1;
    }
    
    auto service = IAaaService::fromBinder(ndk::SpAIBinder(binder));
    if (service == nullptr) {
        std::cerr << "Failed to create service interface" << std::endl;
        return 1;
    }
    
    std::string result;
    
    // send() 호출
    auto status = service->send(&result);
    if (status.isOk()) {
        std::cout << "send() returned: " << result << std::endl;
    } else {
        std::cerr << "send() failed" << std::endl;
    }
    
    // register() 호출
    status = service->register_(&result);
    if (status.isOk()) {
        std::cout << "register() returned: " << result << std::endl;
    } else {
        std::cerr << "register() failed" << std::endl;
    }
    
    return 0;
}
test_client Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := test_aaa_client
LOCAL_PROPRIETARY_MODULE := true

LOCAL_SRC_FILES := test_client.cpp

# aaa의 AIDL 사용
LOCAL_AIDL_INCLUDES := \
    external/aaa/aidl

LOCAL_SHARED_LIBRARIES := \
    libc++ \
    liblog \
    libutils \
    libbinder_ndk \
    libbase

LOCAL_CPPFLAGS := -std=c++17

include $(BUILD_EXECUTABLE)
클라이언트 실행
# 빌드
m test_aaa_client

# 실행
adb shell /vendor/bin/test_aaa_client

# 출력:
# send() returned: hello world
# register() returned: hello world
10. 로그 확인
# aaa 데몬 로그
adb logcat -s aaa:V

# AIDL 호출 로그
adb logcat | grep -E "AaaServiceImpl|send\(\)|register\(\)"
요약
구조
aaa (C 데몬)
├── C 메인 루프 (aaa_main.c)
├── C 코어 로직 (aaa_core.c)
└── C++ AIDL 서버 (aidl_server.cpp)
    ├── send() → "hello world"
    └── register() → "hello world"
핵심 포인트
Android.mk: AIDL 파일을 직접 포함하여 빌드
C/C++ 혼용: C 데몬 + C++ AIDL 서버
Non-blocking: startThreadPool()로 메인 루프와 독립 실행
2개 API: send(), register() 모두 "hello world" 반환
빌드하고 실행해보세요! 추가 질문 있으시면 알려주세요!

반응형