IPCThreadState對象維護(hù)了2個變量
pid_t mCallingPid;
uid_t mCallingUid;
從變量名稱來看,這2個變量保存了進(jìn)程的PID和UID,并且由于這兩個變量由IPCThreadState對象維護(hù),可見它們是與IPC相關(guān)的。具體它們保存的是IPC發(fā)送方的PID和UID還是當(dāng)前進(jìn)程的IPD和UID,視情況而定。
在IPC調(diào)用過程中,被調(diào)用方需要知道調(diào)用方的UID和PID,以便被調(diào)用方用于權(quán)限檢測;所以需要一種方式來提供調(diào)用方的UID和PID,因此上述2個變量的主要作用就是用于權(quán)限檢測。
那么我們想象一下,下面描述的情況下,mCallingPid和mCallingUid又應(yīng)該保存誰的UID和PID?假如有2個進(jìn)程process A和process B,我們站在process B的角度來分析,process A IPC調(diào)用process B, 而process B 又調(diào)用同樣處于process B的Service的接口(盡管此時實際上不是遠(yuǎn)程調(diào)用,并且開發(fā)者是知道的,但是對于Binder調(diào)用機(jī)制來說,它本身并不知道當(dāng)前的調(diào)用是否為遠(yuǎn)程調(diào)用,前幾篇文章中有分析系統(tǒng)如何確定是否為遠(yuǎn)程調(diào)用,這個過程是在binder driver中實現(xiàn)的),那么此時mCallingPid和mCallingUid是不是應(yīng)該保存process B的UID和PID?
1. process B在被process A IPC調(diào)用時, process B需知道process A的UID和PID,來檢查process A的訪問權(quán)限,此時mCallingUid和mCallingPid保存的是process A的UID和PID。
2. 在IPC遠(yuǎn)程調(diào)用process B的過程中,process B的方法調(diào)用了同進(jìn)程中的service的接口,process B既是調(diào)用方也是被調(diào)用方,雖然這個過程比較無聊,但是鑒于IPC過程的不透明性,因此process B仍然需要進(jìn)行權(quán)限檢測。

前面的文章中分析過,binder driver會判斷當(dāng)前的Binder調(diào)用是否為遠(yuǎn)程調(diào)用,如果是同進(jìn)程調(diào)用的話,BD就不會再向應(yīng)用提供進(jìn)程的PID和UID。因此在process B中需要顯示的設(shè)置當(dāng)前的PID和UID。
為實現(xiàn)以上case,android提供了一組函數(shù)
public static final native long clearCallingIdentity();
public static final native void restoreCallingIdentity(long token);
process B的方法調(diào)用了同進(jìn)程中的service的接口前,clearCallingIdentity()方法會清除process A的UID和PID,重置為process B的UID和PID。
process B的方法調(diào)用了同進(jìn)程中的service的接口后,此時仍然處在process A遠(yuǎn)程調(diào)用process B方法的過程中,此時需要restore process A的UID和PID。
本文描述的case,雖然在application 開發(fā)中并不常見,但是在system_server中很常見,比如client調(diào)用ActivityManagerService的方法,而ActivityManagerService又調(diào)用了PackageManagerService的方法,并且ActivityManagerService和PackageManagerService均會運行在system_server進(jìn)程中。
摘自 杜文濤的專欄