Android甚のストックファヌムりェアの倉曎。 パヌト2

こんにちは、Habr

最初の郚分を曞いた埌、私は1週間を通しお、私が玄束したこずに぀いお曞くか、いく぀かの読者の芁求に応じお、私の意芋では、基本的なこずに぀いお説明ず説明をするかどうかを考えたした。
私はしたくないが、あなたの䞀郚は動揺する必芁がありたす。 自分で曞くには、倚くの時間ず劎力がかかりたす。ほずんどの堎合、コピヌペヌストするのは奜きではありたせん。蚘事からさたざたなリ゜ヌスぞのリンクを䜜成するのは悪いニュヌスです。

たずえば、この蚘事でAndroidのロヌド方法を説明するこずは適切ではありたせん。 BIOSでコンピュヌタヌのハヌドりェアを初期化し、システムのカヌネルを介しおロヌドするずいう原則を知っおいる堎合、Androidはこの点で違いはありたせん。 唯䞀の違いはプロセッサアヌキテクチャです。 ファむルシステム構造 玳士、これは玔粋なUNIXシステムであり、どこに、䜕を、どのように保存するかを曞くのはばかげおいたす build.propの線集はシステムの調敎です。 はい、これは倉曎ですが、これらのパラメヌタヌのほずんどはサヌドパヌティ補のアプリケヌションで䜜成でき、たずえばSystem Tunerなど、より䜿いやすくなっおいたす。

Androidシステムの原理を自分で理解するのに2、3か月かかりたした。同じ時間をかけお、すべおの基本的なこずをカバヌする蚘事を曞きたす。 だから、Dalvikコヌドを逆アセンブルし、電話で「䜿甚」の䟿利さを䜜成する方法の特定の䟋に぀いおよりよく曞きたしょう。

それでは、行きたしょう 今日は、ネむティブの方法で電話䌚話の自動録音の機胜を実装した方法を説明したす。

前文


䞀郚の囜では、技術的な手段による電話での䌚話の録音を蚱可しおいたせん。 たずえば、米囜では、圓事者の事前の同意なしに個人的な電話での䌚話を録音するこずは犁じられおいたす。 ゜ビ゚ト埌のスペヌスでは、䌚話の他の参加者に譊告するこずなく、あなたがパヌティヌの1぀である䌚話を録音できたす。 同じ䞭囜では、蚘録は単に歓迎され、隣人ぞの「ノック」はむデオロギヌの原則です。 そしお、これは䌚話の蚘録だけに適甚されたせん。 むンタヌネットの䜿甚、SMSメッセヌゞの送信、゜ヌシャルネットワヌクの䜿甚、暗号化アルゎリズム、2枚のSIMカヌドを搭茉した電話なども、各囜の法埋によっお個別に芏制されおいたす。 今、あなたがビゞネスオヌナヌであり、䞖界䞭のIT補品を茞出しおいるず想像しおください。 もちろん、耇数ではなく1぀のブランチで゜フトりェアを「䜜成」したすが、構成は地域によっお異なりたす。 CIS諞囜にずっおは、ペヌロッパにずっおは、もう1぀です。 電話のメヌカヌも到着したす。 Androidオペレヌティングシステムは、メむンブランチのプログラマヌの1グルヌプのみによっおファむナラむズされおおり、地域ごずに、特定の構成ファむルが最終リリヌスのコンパむルに䜿甚されおいたす。 か぀おベンダヌの1぀で働いおいたので、私は自信を持っおこれを蚀いたす。

これを蚌明するために、ファヌムりェアを他の人のデバむスに移怍する方法に関する優れたガむドがありたす。

行こう


Phone.apkの逆アセンブルされたJAVAコヌドを読んでいるずきに、私は偶然に面癜い旗に぀たずいた。 実際、私たちには興味深いが隠れた機胜がたくさんありたす。 ちょうど今日、私は私の電話に日本のオペレヌタヌKDDIのためのパラメヌタがあるこずを発芋したした。 プロバむダヌからの特別に䜜成されたSMSメッセヌゞは、地震や接波が発生した堎合に、私の電話が心を打぀音を発し、数分間振動する原因になりたす。 しかし、私たちの旗に戻りたしょう。
public static final boolean IS_INCALL_RECORDING_ENABLE = false; 

面癜いず思いたした。 そのようなフラグがある堎合、どこかで䜿甚されたす。 しかし、ここでは明確ではありたせん。 ただし、通話䞭に通話録音ボタンを衚瀺するこずをお勧めしたす。 小物甚ケヌス FALSEをTRUEに倉曎し、パッチを適甚したPhone.apkを䞊曞きしたす。これは自宅の電話ず呌ばれ、電話を拟い䞊げるず「録音開始」ボタンが衚瀺されたした。 しかし、それがなかった前に!!!


もう䞀床、マテリアルを同化するためにそのようなこずをする方法を説明したす。

  1. ホテルフォルダヌを䜜成し、そこにPhone.apkファむルを配眮し、それにsmaliずbacksmaliを远加したす
  2. コマンドjava -Xmx512m -jar baksmali.jar -a -d -o Phone -x Phone.apk

    — API Android. JB — 16
    — , .
    , Phone\com\android\phone\util\VoiceRecorderHelper.smali
    䜿甚しお、Dalvikコヌドの前に解析するファむルをjava -Xmx512m -jar baksmali.jar -a -d -o Phone -x Phone.apk

    — API Android. JB — 16
    — , .
    , Phone\com\android\phone\util\VoiceRecorderHelper.smali
    java -Xmx512m -jar baksmali.jar -a -d -o Phone -x Phone.apk

    — API Android. JB — 16
    — , .

    , Phone\com\android\phone\util\VoiceRecorderHelper.smali
     .field public static final IS_INCALL_RECORDING_ENABLE:Z = false 
    に
     .field public static final IS_INCALL_RECORDING_ENABLE:Z = true 

    ファむルを戻す java -Xmx512m -jar smali.jar -a 16 Phone -o classes.dex
    元のファむルの結果のclasses.dexをアヌカむバヌに眮き換えたす
    電話でPhone.apkを曞き換える

    いく぀かの通話の録音をテストしたずころ、電話は暙準の内蔵ボむスレコヌダヌで䌚話を録音するず同時に、非垞に非垞に高品質で録音するこずがわかりたした。 ファむルの名前は自動的に生成され、通話者の番号たたは名前、および通話の日時が含たれたす。 ファむル保存圢匏は、ネむティブアプリケヌションでも蚭定できたす。 これらの通話蚘録が必芁なのはなぜですか

    たあ、最初に、それは非垞に䟿利です。 私の劻は、賌入する補品のリストを呌び出しお蚀ったが、録音する堎所はないので、レコヌダヌが圹立ちたす。
    第二に、電話で私はクラむアントや顧客ず話さなければなりたせん。時には、必芁で重芁な情報が玛倱したり、聞こえなかったりするこずがありたす。 たたは、重芁な䌚話が行われたずしたしょう。重芁な䌚話を聞いお分析し、タむムリヌな決定を䞋すか、ビゞネスパヌトナヌや他の人ず行動を起こす必芁がありたす。
    第䞉に、仕事ず生掻における非垞に䟿利な蚌拠ベヌス。

    たた、サヌドパヌティのアプリケヌションを䜿甚しない理由を尋ねるこずができたす。サヌドパヌティのアプリケヌションには、オヌプンで無料のアクセスがたくさんありたすか
    • サヌドパヌティのテストされおいないアプリケヌションを信頌しおいたせん。 倚くの堎合、これらの各アプリケヌションは携垯電話のメモリで絶えずハングアップし、プロセッサ時間を消費するため、バッテリヌが䞍足したす。
    • 録音品質は、垞に玄束されたものず䞀臎するずは限りたせん。
    • 私はむンタヌフェむスに぀いお奜き嫌いがありたす。 アプリケヌションの機胜は豊富かもしれたせんが、GUIが私にずっお郜合が悪い堎合は、䜿甚したせん。 残念なこずに、倚くの囜内の発展はこれに欠けおいたす。

    それはどのように機胜したすか


    すべおのAndroid開発者は、システムがさたざたな暙準ブロヌドキャストメッセヌゞでいっぱいであるこずを知っおいたす。 システムで䜕が起こっおも、そのようなメッセヌゞの「その」受信者を実装しおいれば、どのアプリケヌションでも受信できたす。 ブロヌドキャストメッセヌゞを䜜成できたす。このメッセヌゞの受信者のみが、アプリケヌション自䜓たたは䜜成したアプリケヌション党䜓ずなり、䜕らかの方法でこのメッセヌゞを凊理したす。 GoDialerずGoSMSProで実際にこれを芋たした。

    サヌドパヌティの通話録音アプリケヌションも同じように機胜したす。 通話が確立されたずいうメッセヌゞが枡されるずすぐに、録音が開始されたす。 呌び出しが停止するず、蚘録が停止し、バッファがファむルに曞き蟌たれたす。

    私の仕事は、このメッセヌゞが圢成たたは凊理される堎所を芋぀け、䞍必芁なゞェスチャヌをせずに通話の録音を匷制的に開始するこずでした。 結局のずころ、電源を入れるのを忘れたり、単に時間がないこずがよくありたす。 倧量のファヌムりェアコヌドで適切な堎所を䞀般的に芋぀ける方法は、次の蚘事のトピックですが、今は「私たちの堎所」に進みたしょう。

    ハンドラヌ、たたは2぀は、ファむル\ com \ android \ phone \ CallNotifier.javaになりたした

    JavaのDalvikからの逆コンパむルされたコヌドここではコヌドの䞀郚のみを瀺したすは、次のようになりたした。

      private void onCallConnected(AsyncResult paramAsyncResult) { Connection localConnection = (Connection)paramAsyncResult.result; String str = ((IfConnection)localConnection).getDialString(); VLog.d("onCallConnected() dialed number:" + str); removeMessages(120000); removeMessages(120001); this.mIsEccNeedRetry = false; this.mEccIsSwitchingForRetrying = false; //    } 
    そしお
      private void onDisconnect(AsyncResult paramAsyncResult) { Phone.State localState = this.mCM.getState(); if (CallNotifier.VDBG) super.log("onDisconnect()... CallManager state: " + this.mCM.getState()); VLog.d(this, "onDisconnect()"); removeMessages(120000); removeMessages(120001); //    } 

    前の蚘事に比べお、タスクは耇雑です。 前回単玔な関数を修正する必芁があった堎合、ここでは修正するこずができたせん。曞き換えるための゜ヌスコヌドがないためです。 ここで、コヌドを埋め蟌む必芁がありたす。

    Dalvikずは䜕ですか


    これはここずここに簡単に曞かれおいたす 。 さらに簡単な蚀語で蚀えば、仮想マシンのバむトコヌドは、レゞスタ倉数を凊理するために割り圓おられたメモリ領域ず倚くの呜什ず挔算子に基づいおいたす。 操䜜の意味ず原理は非垞に簡単です。レゞスタに倀を曞き蟌んでから操䜜を実行するず、操䜜の結果がアクションを適甚した堎所に返されたす。 すべおの挔算子ず手順の詳现に぀いおは、Dalvik VMのバむトコヌドを参照しおください。

    コヌドを埋め蟌む


    䜕かを入力するには、そこに䜕を入力するかを知る必芁がありたす。 [蚘録の開始]ボタンハンドラヌからコヌドをなめるこずができたす。
    Androidの初心者プログラマヌでさえ、ハンドラヌの保存堎所を芋぀けるこずは難しくありたせん。 その埌、今埌の蚘事で䜕をどのように探すかに戻りたす。 最初の蚘事の本質は、原則を説明しおいたす。

    ボタンが抌されるず、次のコヌドがトリガヌされたす。
      VoiceRecorderHelper localVoiceRecorderHelper = VoiceRecorderHelper.getInstance(); if (!localVoiceRecorderHelper.isRecording()) { localVoiceRecorderHelper.start(); } 
    ぀たり、すべおの呌び出しの蚘録を自動化するには、このコヌドをonCallConnectedハンドラヌに远加する必芁がありたす。

    この゚ントリのDalvikコヌドは次のようになりたす

      invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper; move-result-object v1 invoke-virtual/range {v1 .. v1}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z move-result v2 const/4 v3, 0x0 if-ne v3, v2, :cond_a9 invoke-virtual/range {v1 .. v1}, Lcom/android/phone/util/VoiceRecorderHelper;->start()Z :cond_a9 

    コヌドを1行ず぀解析しおみたしょう。
    1. invoke-staticはVoiceRecorderHelperクラスのむンスタンスを呌び出したす
    2. むンスタンスを保存しおv1を登録する
    3. このクラスのisRecordingずいうメ゜ッドを呌び出し、trueたたはfalseを返したす
    4. 結果はレゞスタv2に曞き蟌たれたす
    5. レゞスタv3に倀0を曞き蟌みたす
    6. 2぀のレゞスタv2ずv3の比范を行っおいたす。 ロゞックv2= V3。 isRecordingがTRUEを返す堎合、v2の倀は1になり、FALSEの堎合はその逆になりたす。 条件が機胜しない堎合は、cond_a9マヌカヌにゞャンプしたす。 そうでない堎合は、
    7. レゞスタv1に栌玍されおいるクラスむンスタンスのstartメ゜ッドが呌び出されたす
    8. 䌚話が録音され始めたした。


    onCallConnectedに戻りたす。 圌のdalvikコヌドは次のずおりです。
     .method private onCallConnected(Landroid/os/AsyncResult;)V .registers 8 .parameter "r" .prologue .line 2302 iget-object v0, p1, Landroid/os/AsyncResult;->result:Ljava/lang/Object; check-cast v0, Lcom/android/internal/telephony/Connection; .local v0, c:Lcom/android/internal/telephony/Connection; move-object v2, v0 

    このコヌドも分析しお、䜕が䜕であるかを明確にしたす

    • .registers 8この機胜に必芁か぀䜿甚されるメモリレゞスタの数
    • parameter "r"は、゜ヌスコヌドで䜿甚されたパラメヌタヌの名前です。 それが私たちの興味を匕くこずはめったにありたせん。
    • prologue -関数アルゎリズムの始たり
    • .line 2302゜ヌスコヌドの行番号。 これはデバッグ専甚です。
    • iget-object v0, p1, Landroid/os/AsyncResult;->result:Ljava/lang/Object; 次の行は、 (Connection)paramAsyncResult.result;察応しおい(Connection)paramAsyncResult.result;
    • check-cast v0, Lcom/android/internal/telephony/Connection; Connection察応
    • .local v0, c:Lcom/android/internal/telephony/Connection; localConnection䞀臎
    • move-object v2, v0ロヌカル倉数v0をレゞスタv2に耇補
    • など

    説明を参照しおJavaコヌドず比范すれば、コヌドを解析するこずはそれほど難しくありたせん。

    ボタンクリックハンドラヌからコヌドをコピヌし、コヌルハンドラヌの先頭に貌り付けるだけで完了です。 そこにはありたせんでした。 時々それは動䜜したすが、ほずんどは動䜜したせん。 実際、デヌタを曞き蟌むレゞスタはプログラムのさらなるコヌドで䜿甚でき、最初に間違ったレゞスタを䜿甚しお䜕かを曞き蟌むず、プログラムの実行䞭に゚ラヌが発生し、アルゎリズム党䜓が故障する可胜性がありたす。 この堎合、最初に関数を入力し、最初に初期化されないレゞスタを䜿甚できるずいう点で単玔です。これらのレゞスタは将来䞊曞きされるためです。 しかし、倚くの堎合、コヌドはプログラムの途䞭のどこかに埋め蟌む必芁があり、レゞスタに泚意する必芁がありたす。 これは将来の蚘事にもありたす。

    レゞスタ倉曎

    埋め蟌み可胜なコヌドの最初の2行には次のものがありたす。

      invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper; move-result-object v1 
    適切なレゞスタ番号を探す最も簡単な方法は、必芁なレゞスタ番号に曞き蟌たれおいるデヌタの皮類をメ゜ッド自䜓で調べるこずです。 コヌドを芋るず、v2ずv 3でmove-result-objectが曞き蟌たれおいるこずがわかりたす。
    したがっお、埋め蟌み可胜なコヌドのv1はすべおv2たたはv3に眮き換えられたす

    埋め蟌み可胜なコヌドのレゞスタ番号を眮き換えるためのすべおの操䜜を行った埌、次の図を取埗したす。

      invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper; move-result-object v3 invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z move-result v4 const/4 v5, 0x0 if-ne v5, v4, :cond_27 invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->start()Z :cond_27 
    マヌカヌcond_a9をcond_27に倉曎したこずは泚目に倀したす。 実際、cond_a9マヌカヌは、コヌドを埋め蟌んだファむル内に既に存圚しおおり、2回目はそのようなマヌカヌを䜿甚できたせん。 マヌカヌ番号は16進コヌドであり、任意の、最も重芁なこずには䞀意にするこずができたす。

    次に、゜ヌスファむルで、行.line 2302を埋め蟌み可胜コヌドに眮き換えお、
     .method private onCallConnected(Landroid/os/AsyncResult;)V .registers 8 .parameter "r" .prologue invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper; move-result-object v3 invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z move-result v4 const/4 v5, 0x0 if-ne v5, v4, :cond_27 invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->start()Z :cond_27 .line 2302 iget-object v0, p1, Landroid/os/AsyncResult;->result:Ljava/lang/Object; check-cast v0, Lcom/android/internal/telephony/Connection; .local v0, c:Lcom/android/internal/telephony/Connection; move-object v2, v0 


    コマンドjava -Xmx512m -jar smali.jar -a 16 Phone -o classes.dexを䜿甚しおコヌドを収集し、 java -Xmx512m -jar smali.jar -a 16 Phone -o classes.dexで眮き換えおテストしたす。

    Javaでは、私たちの仕事は次のようになり始めたした。
      private void onCallConnected(AsyncResult paramAsyncResult) { VoiceRecorderHelper localVoiceRecorderHelper = VoiceRecorderHelper.getInstance(); if (!localVoiceRecorderHelper.isRecording()) { localVoiceRecorderHelper.start(); } Connection localConnection = (Connection)paramAsyncResult.result; String str = ((IfConnection)localConnection).getDialString(); VLog.d("onCallConnected() dialed number:" + str); removeMessages(120000); removeMessages(120001); 


    すべおが正垞で、すべおが機胜したすが、唯䞀の問題は、䌚話が完了した埌、通話録音が無期限に継続するこずです。
    これを行うには、関数メ゜ッドonDisconnectの先頭に同様のコヌドを登録する必芁がありたす。ただし、リバヌスロゞックのみです。

      VoiceRecorderHelper localVoiceRecorderHelper = VoiceRecorderHelper.getInstance(); if (localVoiceRecorderHelper.isRecording()) { localVoiceRecorderHelper.stop(); } 


    録音の開始ず同様に、レゞスタ番号を眮き換える小さな手順を䜜成したす

     .method private onDisconnect(Landroid/os/AsyncResult;)V .registers 41 .parameter "r" .prologue invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper; move-result-object v34 invoke-virtual/range {v34 .. v34}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z move-result v4 if-eqz v4, :cond_33 invoke-virtual/range {v34 .. v34}, Lcom/android/phone/util/VoiceRecorderHelper;->stop()Z .line 2487 :cond_33 

    倉曎を収集し、電話ず出来䞊がりで眮き換えたす-すべおが正垞に機胜したす。

    ゚ピロヌグ


    この資料は、前の蚘事ず比范しお、数倍耇雑で混乱しおいるこずがわかったず思いたす。 いく぀かのレゞスタ、挔算子、修食子...それはナンセンスのようです。 Dalvikを自分で初めお芋たずき、私はぞっずし、ペヌゞを閉じお、半幎も開きたせんでした。 壁に抌し付けられたずき、2週間以内に、䜕が起こっおいたのか、それをどのように実行するのかをすぐに芋぀けたした。 喜ばしいこずに、私はレンガを受け取ったこずはありたせん。

    広告ではなく、倚くの情報を埗るこずができる2぀のリ゜ヌスをお䌝えしたす。

    ロシア語ず英語
    䞡方のリ゜ヌスで、同じニックネヌムで出垭したす。

    それたでの間、次の蚘事たで、䞀週間以内にお願いしたす。

Source: https://habr.com/ru/post/J182640/


All Articles