Androidのテレフォニー分析(6)----インターフェース拡張(実践論文)

これは、インタフェースの拡張機能を実装し、一緒に、説明前の5つの記事の知識を結合します。
以前の5つの記事の内容を読んでいない場合は、お読みください:
「アンドロイド電話解析() -電話のコメント、」
「アンドロイドテレフォニー分析(2) - RegistrantListコメント、」
「アンドロイド電話解析(3) - RILJの説明」
」 Androidの電話の解析(4) - TelephonyManagerコメント、「
- 」のAndroidテレフォニー分析(5)はTelephonyRegistryは説明し、「

APPからRILに新しいAPPコールへのインターフェイスであるインターフェイスの拡張、用として、一般的なプロセスは以下の通りであります:

1.送信要求が達成
1.1 BaseCommands拡大インタフェースを

主に送信要求にBaseCommands方法RIL.javaモデムインタフェースを拡張するために。
継承RILJは次の通り:

 

したがって、この方法は、RIL.javaでこのメソッドをオーバーライドして、モデムに送信RILJ要求にBaseCommandsを拡大する必要性を追加します。
メソッドのBaseCommands.javaを追加します(フレームワーク\オプト\電話\ SRC \ javaの\ COM \ androidの\内部\テレフォニー):

    公共 のボイド setValueToModem(int型のINPUT、メッセージ応答){
         // このメソッドは空なので、サブクラスプレスを書き換える必要があり 
    }

RILConstants.java(フレームワーク\ベース\電話\ javaの\ COM \ androidの\内部\テレフォニー)でアクティブ追加する要求メッセージ:

    // 200この図は、実際のプロジェクトに応じて変更する必要が
    int型の RIL_REQUEST_SET_VALUE = 200;

RIL.javaの新しい送信要求(フレームワーク\オプト\電話\ SRC \ javaの\ COM \ androidの\内部\テレフォニー)の方法:

    @Override
     公共 ボイド setValueToModem(int型のINPUT、メッセージ応答){
         // 取得RILRequestオブジェクト
        RILRequest RR
                 = RILRequest.obtain(RIL_REQUEST_SET_VALUE、応答);
         //はAPPに上を通過RILRequestオブジェクトパラメータ
        rr.mParcel.writeInt( INPUT);
         // キー出力ログ
        IF(RILJ_LOGD)riljLog(rr.serialString()+ ">" + requestToString(rr.mRequest)
                     + "" + INPUT); 

        送信(RR); 
        // テスト用
         // レスポンス。 sendToTarget(); 
    }

RILC抜けの拡張用として、このインターフェイスは、デバッグのために利用可能であるかどうか、意図的に書いた
()response.sendToTargetと、コード行をデバッグします。

1.2インターフェース拡張PhoneInternalInterfaceは

主に通話RILJ間接的な方法を得るために、例として長いメソッドRILJを包装するためPhoneInternalInterfaceインタフェースを拡張しました。
電話での継承次のとおりです。

Phone.javaは全体の関係の中央ハブであるので、あなたはImsPhoneおよびIMSプロセスのために行っていない場合、我々はPhoneInternalInterfaceインターフェイスを拡張することができ、その後、あなたはPhone.javaでコンクリート中に達成することができます。
PhoneInternalInterface.java(フレームワーク\オプト\電話\にインターフェイスを追加するには SRC \ javaの\ COM \ androidの\内部\テレフォニー):

    無効 setValueToModem(int型の値)。

Phone.javaで(枠組み\オプト\電話\ SRC \ javaの\ COM \ androidの\内部\テレフォニー)統一されたインタフェースを実現するために、電話でこの方法を使用してすべてのサブクラス:

    @Override
    public void setValueToModem(int input){
        //对于回调事件的处理,第2小节再讲
        Message resp = obtainMessage(EVENT_SET_VALUE_DONE,0,0);
        //直接调用RILJ中的方法
        mCi.setValueToModem(input,resp);
    }

1.3 扩展ITelephony接口

扩展ITelephony接口主要是为了进一步封装Phone对象中的方法,让那些不能直接得到Phone对象的类也可以间接地调用Phone对象中的方法。
先在ITelephony.aidl(frameworks\base\telephony\java\com\android\internal\telephony)中新增一个接口:

    void setValueToModem(int input);

在PhoneInterfaceManager.java (packages\services\telephony\src\com\android\phone)中实现该接口:

    @Override
    public void setValueToModem(int input){
        try{
            //得到Phone对象
            Phone phone = PhoneFactory.getDefaultPhone();
            if(phone != null){
                phone.setValueToModem(input);
            }
        }catch(IllegalStateException e){

        }
    }

由于PhoneInterfaceManager运行在Phone进程中,所以还需进一步封装,让不运行在Phone进程中的类也可以调用。
在TelephonyManager.java (frameworks\base\telephony\java\android\telephony)中封装Phone Service的方法:

    /** @hide */
    public void setValueToModem(int input){
        try {
            //得到PhoneInterfaceManager的代理对象
            ITelephony telephony = getITelephony();
            if (telephony != null){
                telephony.setValueToModem(input);
            }
        } catch (RemoteException ex) {

        } catch (NullPointerException ex) {

        }
    }

从RILJ—>Phone—>PhoneInterfaceManager—>TelephonyManager,经过一层层的封装,APP终于可以通过TelephonyManager来间接调用RILJ中的方法了。
整个过程的时序图如下:

2. 返回结果的实现
2.1 RILJ中的处理

在RILJ向modem发送请求之后,modem处理完会上报Solicited Response消息并且附带着结果
所以我们需要在RIL.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)的processSolicited()方法中增加

    case RIL_REQUEST_SET_VALUE:      ret = responseInts(p); break;

在requestToString方法中增加

    case RIL_REQUEST_SET_VALUE: return "RIL_REQUEST_SET_VALUE";

2.2 Phone中的处理

在《Android Telephony分析(三) — RILJ详解 》的2.2.1小节中我们说过,接着会通过rr.mResult.sendToTarget();返回到创建Message对象的地方,也就是上面1.2小节说到的
在Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中:

    @Override
    public void setValueToModem(int input){
        //对于回调事件的处理,第2小节再讲
        Message resp = obtainMessage(EVENT_SET_VALUE_DONE,0,0);
        //直接调用RILJ中的方法
        mCi.setValueToModem(input,resp);
    }

还需要对于回调事件进行处理,也就是先在Phone.java中定义EVENT_SET_VALUE_DONE消息:

    //100这个数字需要根据实际项目进行修改
    protected static final int EVENT_SET_VALUE_DONE                 = 100;
    protected static final int EVENT_LAST                           =
                               EVENT_SET_VALUE_DONE;

接着在handleMessage()方法中增加对EVENT_SET_VALUE_DONE的处理:

            case EVENT_SET_VALUE_DONE:
                //取出返回结果
                ar = (AsyncResult)msg.obj;
                String result = null;
                //如果返回结果不为空且没有异常
                if (ar != null && ar.exception == null) {
                    result = "success";
                }else{
                    result = "fail";
                }
                //其实最偷懒的方式是直接在这里发广播通知APP,
                //但是为了结合我们学过的知识,我还是通过PhoneNotifier来实现
                mNotifier.notifySetValueDone(result);
                break;

2.3 扩展PhoneNotifier接口

扩展PhoneNotifier接口主要为了进一步上报消息并且附带这结果。PhoneNotifier的常用子类是DefaultPhoneNotifier。
先在PhoneNotifier.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增一个接口:

    public void notifySetValueDone(String result);

接着在DefaultPhoneNotifier.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中实现该接口:

    @Override
    public void notifySetValueDone(String result){
        try {
            if (mRegistry != null) {
                //需要依赖TelephonyRegistry进一步上报通知
                mRegistry.notifySetValueDone(result);
            }
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
    }

2.4 扩展ITelephonyRegistry接口

先在ITelephonyRegistry.aidl(frameworks\base\telephony\java\com\android\internal\telephony)中新增接口:

    void notifySetValueDone(String result);

在TelephonyRegistry.java (frameworks\base\services\core\java\com\android\server)中实现该接口:

    @Override
    public void notifySetValueDone(String result){
        synchronized (mRecords) {
            for (Record r : mRecords) {
            //通知所有监听了LISTEN_SET_VALUE_DONE的类
            if((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SET_VALUE_DONE))){
                    try {
                        r.callback.onSetValueDone(result);
                    } catch (RemoteException ex) {
                        mRemoveList.add(r.binder);
                    }
                }
            }
            handleRemoveListLocked();
        }
    }

2.5 扩展IPhoneStateListener接口

扩展IPhoneStateListener接口主要为了新增一个可以监听的事件LISTEN_SET_VALUE_DONE。通过APP事先监听,当有该事件上报的时候,就会通知到APP。
先IPhoneStateListener.aidl(frameworks/base/telephony/java/com/android/internal/telephony)中新增接口:

    void onSetValueDone(String result);

在PhoneStateListener.java (frameworks\base\telephony\java\android\telephony)中新增可监听的事件,并且初步实现接口中的方法

    /** @hide */
    //这个数字按项目实际需要修改
    public static final int LISTEN_SET_VALUE_DONE                      = 0x00800000;

    /** @hide*/
    public void onSetValueDone(String result){
        //由子类来重写
    }

在IPhoneStateListener callback = new IPhoneStateListener.Stub()中新增:

        public void onSetValueDone(String result){
            Message.obtain(mHandler, LISTEN_SET_VALUE_DONE, 0, 0, result).sendToTarget();
        }

在handleMessage中新增:

    case LISTEN_SET_VALUE_DONE:
         //调用子类重写的方法,也就是APP中的方法
         PhoneStateListener.this.onSetValueDone((String)msg.obj);
         break;

到这里,从RILJ—>Phone—>DefaultPhoneNotifier—>TelephonyRegistry—>APP,消息和结果就上报到APP了。
整个过程的时序图如下(步骤10~15):

 

 

3. APP如何使用接口

在APP中可以这样调用并调试接口:

    //监听事件
    TelephonyManager.getDefault().listen(new PhoneStateListener(){
        @Override
        public void onSetValueDone(String result){
            //对结果进行处理
        }
    }, PhoneStateListener.LISTEN_SET_VALUE_DONE);
    //发送请求
    TelephonyManager.getDefault().setValueToModem(1);

 

 

 ————————————————
版权声明:本文为CSDN博主「linyongan」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/linyongan/article/details/52151651

おすすめ

転載: www.cnblogs.com/yz123/p/12024104.html