Android RIL 사용 설명

10059 단어 AndroidRIL
머리말
안 드 로 이 드 는 통용 되 는 모 바 일 플랫폼 으로서 가장 중요 한 기능 은 통화,문자,인터넷 등 통신 기능 이다.그렇다면 시스템 의 측면 에서 볼 때 안 드 로 이 드 는 도대체 어떻게 네트워크 와 의 상호작용 을 실현 합 니까?이 글 은 안 드 로 이 드 에서 통신 기능 을 담당 하 는 텔 레 포 니 중간 층 을 살 펴 보면 보통 RIL(Radio Interface Layer)의 구체 적 인 실현 원리 와 구조 라 고도 불 린 다.
안 드 로 이 드 폰 이 네트워크 와 의 통신 을 실현 하려 면 두 층 을 뛰 어 넘 어야 합 니 다.
RIL Java(RILJ):상위 앱 의 통신 요청 을 HAL 층 에 전송 하 는 것 을 책임 집 니 다.RIL C++(RILD):시스템 데 몬,RILJ 요청 명령 을 CP(Communication Processor)에 보 냅 니 다.
RIL 이 뭐야?
쉽게 말 해 RIL(Radio Interface Layer)은 애플 리 케 이 션 의 통신 요청 을 CP 의 중간 층 으로 보 내 는 것 으로,두 부분 을 포함해 하 나 는 자바 층 RILJ,하 나 는 C++층(CP 에 대응 하 는 HAL 층 으로 봐 도 무방)RILD 다.
RILJ 는 시스템 Phone 프로 세 스 의 일부분 으로 Phone 프로 세 스 가 시작 되면 불 러 옵 니 다.RILD 데 몬 은 Android 의 Init 프로 세 스 를 통 해 불 러 옵 니 다.
RIL 구조
다음 그림 은 Android RIL 의 구성 도 입 니 다.전체 통신 과정 은 네 개의 층 이 있다.
  • 최상 위 는 응용 프로그램 이다.예 를 들 어 통화,문자 와 SIM 카드 관 리 는 주로 사용자 의 명령 을 RIL Framework(이후 RILJ 라 고 통칭)에 보 내 는 것 을 책임 진다.
  • RILJ 는 텔 레 포 니 관리자(통화,네트워크 상태 포함)와 같은 일반적인 API 를 상부 에 제공 했다.SubscriptionManager(카드 상태)및 SmsManager 등 과 함께 RILJ 는 RILD 와 의 통신 을 유지 하고 상부 의 요청 을 RILD 에 보 내 는 일 도 맡 는 다.
  • RILD 는 시스템 의 데 몬 으로 통화 기능 을 지원 하 는 모 바 일 플랫폼 에 없어 서 는 안 된다.RILD 의 주요 기능 은 RILJ 가 보 낸 요청 을 CP 에 계속 전달 하 는 동시에 CP 의 상태 변 화 를 즉시 RILJ 에 보 내 는 것 이다.
  • Linux 구동 층:kernel 구동 층 이 데 이 터 를 받 은 후에 명령 을 CP 에 전달 하고 마지막 으로 CP 에서 네트워크 단 에 보 내 며 네트워크 가 결 과 를 되 돌려 주면 CP 는 RILD 에 게 전 달 됩 니 다.

  • RILJ 와 RILD(RILD 와 CP 의 통신)는 모두 하나의 메 시 지 를 통 해 데 이 터 를 전달한다.메 시 지 는 주로 두 가지 로 나 뉜 다.하 나 는 RILJ 가 자발적으로 보 낸 요청(solicited)이 고 흔히 볼 수 있 는 것 은 RIL 이다.REQUEST_GET_SIM_STATUS(SIM 카드 상태 획득),RILREQUEST_DIAL(전화 걸 기),RILREQUEST_SEND_SMS(문자 발송),RILREQUEST_GET_CURRENT_CALLS(현재 통화 상태 획득),RILREQUEST_VOICE_REGISTRATION_STATE(네트워크 상태 가 져 오기);다른 하 나 는 CP 에서 RIL 에 자발적으로 보고 하 는 메시지(unsolicited)입 니 다.예 를 들 어 네트워크 상태 가 바 뀌 면 CP 는 RIL 에 보고 합 니 다.UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,새로운 문자 가 있 을 때 RILUNSOL_RESPONSE_NEW_SMS,전화 가 오 면 RIL 에 보고 합 니 다.UNSOL_CALL_RING。
    RIL 관련 요청 명령 과 데이터 구 조 는/android/hardware/ril/include/telephony/ril.h 로 정의 되 어 있 습 니 다.
    전체 과정 에서 몇 가지 관건 적 인 문제 가 있다.
  • 상층 부 는 RILJ 의 상태 변 화 를 어떻게 알 았 습 니까?
  • RILJ 와 RILD 는 어떻게 통신 합 니까?
  • RILJD 와 CP 는 어떻게 통신 합 니까?
  • 이 세 가지 문제 점 을 둘러싸 고 우 리 는 구체 적 인 세부 사항 을 살 펴 보 자.
    상부 에서 어떻게 RILJ 의 상태 변 화 를 알 게 되 었 습 니까?
    RIL 은 상부 에서 실시 간 으로 네트워크 상태,통화 상태 와 CP 의 상태 변 화 를 감청 하 는 데 편리 하도록 전문 적 인 감청 인터페이스 IPhoneState Listener.aidl 을 제공 했다.상부 에서 상기 상태 변 화 를 감청 해 야 할 때 상기 인터페이스 만 실현 하고 안 드 로 이 드 시스템 서비스 Telephony Registry 에서 상기 인 터 페 이 스 를 등록 해 야 한다.
    
    public void listen(String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow);
    
    또한 Telephony Manager 에서 RIL 상 태 를 감청 할 수도 있다.
    
     public void listen(PhoneStateListener listener, int events)
    
    소스 코드:/android/frameworks/base/telephony/java/com/android/internal/telephone/IPhoneStateListener.aidl
    
    oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
     void onSignalStrengthChanged(int asu);
     void onMessageWaitingIndicatorChanged(boolean mwi);
     void onCallForwardingIndicatorChanged(boolean cfi);
    
     // we use bundle here instead of CellLocation so it can get the right subclass
     void onCellLocationChanged(in Bundle location);
     void onCallStateChanged(int state, String incomingNumber);
     void onDataConnectionStateChanged(int state, int networkType);
     void onDataActivity(int direction);
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
     void onOtaspChanged(in int otaspMode);
     void onCellInfoChanged(in List<CellInfo> cellInfo);
     void onPreciseCallStateChanged(in PreciseCallState callState);
     void onPreciseDataConnectionStateChanged(in PreciseDataConnectionState dataConnectionState);
     void onDataConnectionRealTimeInfoChanged(in DataConnectionRealTimeInfo dcRtInfo);
     void onVoLteServiceStateChanged(in VoLteServiceState lteState);
     void onOemHookRawEvent(in byte[] rawData);
     void onCarrierNetworkChange(in boolean active);
     void onFdnUpdated();
    
     void onVoiceRadioBearerHoStateChanged(int state);
     }
    RILJ 와 RILD 는 어떻게 통신 합 니까?
    RILJ 는 생 성 과정 에서 두 개의 스 레 드 를 시작 합 니 다.RILSender 와 RILReceiver,RILSender 는 RILD 에 명령 을 보 내 고 RILReceiver 는 RILD 에서 보 낸 데 이 터 를 읽 는 것 을 책임 집 니 다.RILJ 와 RILD 의 통신 통 로 는 RILReceiver 에서 세 워 진 것 이다.
    RILReciver 의 코드 를 살 펴 보 겠 습 니 다.
    
    class RILReceiver implements Runnable {
     byte[] buffer;
    
     RILReceiver() {
     ...
     @Override
     public void
     run() {
     int retryCount = 0;
     String rilSocket = "rild";
    
     //    RILD    
     try {for (;;) {
     LocalSocket s = null;
     LocalSocketAddress l;
    
     if (mInstanceId == null || mInstanceId == 0 ) {
      rilSocket = SOCKET_NAME_RIL[0];
     } else {
      rilSocket = SOCKET_NAME_RIL[mInstanceId];
     }
    
     try {
      s = new LocalSocket();
      l = new LocalSocketAddress(rilSocket,
      LocalSocketAddress.Namespace.RESERVED);
      s.connect(l);
     } catch (IOException ex){
      ...
      // don't print an error message after the the first time
      // or after the 8th time
    
      if (retryCount == 8) {
      Rlog.e (RILJ_LOG_TAG,
      "Couldn't find '" + rilSocket
      + "' socket after " + retryCount
      + " times, continuing to retry silently");
      } else if (retryCount >= 0 && retryCount < 8) {
      Rlog.i (RILJ_LOG_TAG,
      "Couldn't find '" + rilSocket
      + "' socket; retrying after timeout");
      }
      ...
    
      retryCount++;
      continue;
     }
    
     retryCount = 0;
     mSocket = s;
    
     //  socket    
     int length = 0;
     try {
      InputStream is = mSocket.getInputStream();
    
      for (;;) {
      Parcel p;
    
      length = readRilMessage(is, buffer);
    
      if (length < 0) {
      // End-of-stream reached
      break;
      }
    
      p = Parcel.obtain();
      p.unmarshall(buffer, 0, length);
      p.setDataPosition(0);
    
      processResponse(p);
      p.recycle();
      }
     } catch (java.io.IOException ex) {
      Rlog.i(RILJ_LOG_TAG, "'" + rilSocket + "' socket closed",
      ex);
     } catch (Throwable tr) {
      Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length=" + length +
      "Exception:" + tr.toString());
     }
    
     //      , CP        
     setRadioState (RadioState.RADIO_UNAVAILABLE);
     ...
     mSocket = null;
     RILRequest.resetSerial();
    
     // Clear request list on close
     clearRequestList(RADIO_NOT_AVAILABLE, false);
     }} catch (Throwable tr) {
     Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr);
     }
     }
     }
      RILReceiver 가 시 작 될 때 UNIX Domain socket(Local Socket,kernel 계층 대응/dev/socket/rild)을 만들어 RILD 와 통신 한 후 socket 에서 데 이 터 를 계속 읽 고 상부 로 전송 합 니 다.연결 이 성공 하면 RILD 는 RILJ 에 게 연결 이 성공 했다 는 메 시 지 를 보 냅 니 다.그러면 RILJ 는 요청 데 이 터 를 RILD 에 보 내 통신 할 수 있 습 니 다.
    RILD 와 CP 는 어떻게 통신 합 니까?
    RILD 와 CP 는 일반적으로 두 가지 경우 가 있다.만약 AP 와 CP 가 하나의 칩 에 집중 된다 면,예 를 들 어 퀄 컴 의 플랫폼 은 AP 와 CP 를 하나의 칩 에 집중 하 는 것 이다.이 때 는 보통 공유 메모리 방식 으로 크로스 프로 세 스 통신 을 실현 한다.같은 칩 이 아 닌 AP 와 CP 가 각각 다른 업 체 의 플랫폼 을 사용한다 면 일반적으로 문자 장치(character devices)로 통신 한다.전반적 으로 메모리 공유 방식 은 문자 장치 보다 속도 가 좋다.
    다음은 RILJ 부분의 코드 구 조 를 소개 한다.
    RILJ 코드 구조
    RIL Framework(RILJ)의 코드 를 기능 에 따라 구분 하면 다음 과 같은 몇 가지 구성 부분 이 있 습 니 다.
  • 관리 네트워크 상태(신호 강도,네트워크 등록 상태 등):ServiceStateTracker 등;
  • 통화 관리(전화 걸 기,받 기,통화 대기 등):CallManager,GsmCallTracker 등
  • SMS 문자 수신 발송:InboundSMSHandler,SmsDispater 등
  • SIM 카드 관리:UiccController,SubscriptionsController 등
  • 데이터 링크 관리:DcTracker,DctController 등
  • Telephony 집사:Phone Base,GsmPhone,Phone Proxy 등

  • 상기 코드 는 주로 두 개의 디 렉 터 리 에 있 습 니 다.
  • /android/frameworks/opt/telephony/(RILD 와 의 상호작용 담당)
  • /android/frameworks/base/telephony/(상층 부 에 인터페이스 제공)
  • 다음은 전 화 를 거 는 절 차 를 예 로 들 어 RIL 이 어떻게 역할 을 하 는 지 살 펴 보 자.
    예제:CALL 프로 세 스
    다음 그림 은 MO(Mobile Originated)통화 프로 세 스 약도 입 니 다.
  • APP 는 TelecomManager 에 전화 걸 기 요청 을 보 냅 니 다(TelecomManager 에 관 해 서 는 다른 글 Android Telecom 시스템 서비스 을 참고 할 수 있 습 니 다).
  • TelecomManager 는 통화 요청 을 GsmPhone 에 보 냅 니 다.
  • GsmPhone 은 GsmCallTracker 에 명령 을 계속 전달 합 니 다.
  • GsmCallTracker 는 RILJ 를 호출 하고 RILJ 는 RILD 에 통화 요청 을 보 냅 니 다.
  • RILD 가 통화 명령 을 받 았 을 때 CP 에 보 내기;
  • CP 는 네트워크 에 보 내 고 MT(Mobile Terminal)는 통 화 를 받 은 후에 네트워크 에서 이 메 시 지 를 MO 에 전달 하여 MT(핸드폰 이 뚜뚜 소 리 를 낼 때)에 게 보 냈 다 고 알려 준다.통화 상 태 는 DIALING C>ALERTING 이다.
  • RILD 통화 상태 변화 소식 을 받 고 UNSOLRESPONSE_CALL_STATE_CHANGED 의 소식 을 RILJ 에 게 전하 기;
  • RILJ 는 GsmCallTracker 의 통화 상태 가 변 했다 고 알 렸 다.
  • GsmCallTracker 는 CALL 상 태 를 주동 적 으로 조회 합 니 다.pollCallWhenSafe()는 얻 은 정보 가 옳 고 변화 가 없 음 을 확보 합 니 다.
  • RILJ 가 RILD 에 getCurrentCalls()를 보 내 는 요청;
  • RILD 가 CALL 상 태 를 획득 한 후 RILJ 에 보고 하고 RILJ 에서 결 과 를 되 돌려 주 는 GsmCallTracker
  • GsmCallTracker 가 CALL 상 태 를 확인 한 후 GsmPhone:notify PreciseCallStateChanged()에 게 알 립 니 다.
  • GsmPhone 은 CALL 상태 변화 소식 을 Telecom 시스템 서비스 에 알 립 니 다.
  • 마지막 으로 Telecom 시스템 서 비 스 는 CALL 상태 변화 에 대한 방송 을 상부 APP
  • 에 보 냈 다.
    이 쯤 되면 통화 가 시작 되 지 않 고 MT 가 전 화 를 받 으 면 MO 는 CALL 상태 변화 에 대한 메 시 지 를 받 고 나 서 야 진정 으로 통화 링크 를 만 들 기 시작한다.
     안 드 로 이 드 RIL 사용 에 대한 자세 한 설명 은 여기까지 입 니 다.안 드 로 이 드 RIL 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기