Android系统中framework和app用到名称为phone的服务还是比较多的,需要用到的是ITelephony.aidl
frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl
void answerRingingCall();
ITelephony中有各种通讯相关接口,从设计角度来说这个服务中的很多方法是不供三方app调用的,但还是有方法(例如反射)可以使用ITelphony的。不然各种系统管家和骚扰拦截程序怎么能挂断电话呢
服务实现是在PhoneInterfaceManager.java中,位于Telephony包下,该包编译后是TeleService.apk,进程就是包名com.android.phone
packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java
public class PhoneInterfaceManager extends ITelephony.Stub {
/* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
synchronized (PhoneInterfaceManager.class) {
if (sInstance == null) {
sInstance = new PhoneInterfaceManager(app, phone);
} else {
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
}
return sInstance;
}
}
单例模式
private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
...
publish();
}
private void publish() {
if (DBG) log("publish: " + this);
ServiceManager.addService("phone", this);
}
构造函数中调用publish(), 然后添加名称为phone的服务到系统中。init的调用链如下:
packages/services/Telephony/src/com/android/phone/PhoneApp.java
public class PhoneApp extends Application {
该类继承自Application类,即phone进程一启动必会走onCreate方法
@Override
public void onCreate() {
if (UserHandle.myUserId() == 0) {
// We are running as the primary user, so should bring up the
// global phone state.
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();
...
}
}
packages/services/Telephony/src/com/android/phone/PhoneGlobals.java
public void onCreate() {
...
phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
...
}
phone进程一启动phone服务就添加到系统中,其它进程就可以通过ITelephony调用phone服务
public void answerRingingCall() {
answerRingingCallForSubscriber(getDefaultSubscription());
}
public void answerRingingCallForSubscriber(int subId) {
if (DBG) log("answerRingingCall...");
// TODO: there should eventually be a separate "ANSWER_PHONE" permission,
// but that can probably wait till the big TelephonyManager API overhaul.
// For now, protect this call with the MODIFY_PHONE_STATE permission.
enforceModifyPermission();
sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId));
}
/**
* Posts the specified command to be executed on the main thread,
* waits for the request to complete, and returns the result.
* @see #sendRequestAsync
*/
private Object sendRequest(int command, Object argument, Integer subId) {
if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
throw new RuntimeException("This method will deadlock if called from the main thread.");
}
MainThreadRequest request = new MainThreadRequest(argument, subId);
Message msg = mMainThreadHandler.obtainMessage(command, request);
msg.sendToTarget();
// Wait for the request to complete
synchronized (request) {
while (request.result == null) {
try {
request.wait();
} catch (InterruptedException e) {
// Do nothing, go back and wait until the request is complete
}
}
}
return request.result;
}
发送CMD_ANSWER_RINGING_CALL请求到mMainThreadHandler处理,如字面意思该Handler的作用就是把代码运行在主线程,然后binder线程同步wait到结果返回给调用端。Looper.myLooper() 获得的Looper实际就是
binder thread的Looper,所以它们一般情况下肯定是不相等的,除非是phone进程代码直接调用该类方法(这个就和binder没有任何关系了,相当于调用一个类的成员方法,但是phone进程这样做其实没有任何意义,因为这个本来就是对外提供服务,phone进程本身要实现同样功能很简单)。
case CMD_ANSWER_RINGING_CALL:
request = (MainThreadRequest) msg.obj;
int answer_subId = request.subId;
answerRingingCallInternal(answer_subId);
// Wake up the requesting thread
/// M: for ALPS02014935. 2015-04-02 @{
synchronized (request) {
request.result = "OK";
request.notifyAll();
}
/// @}
break;
mMainThreadHandler消息处理中调用answerRingingCallInternal方法
private void answerRingingCallInternal(int subId) {
final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
if (hasRingingCall) {
final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
if (hasActiveCall && hasHoldingCall) {
// Both lines are in use!
// TODO: provide a flag to let the caller specify what
// policy to use if both lines are in use. (The current
// behavior is hardwired to "answer incoming, end ongoing",
// which is how the CALL button is specced to behave.)
PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
return;
} else {
// answerCall() will automatically hold the current active
// call, if there is one.
PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
return;
}
} else {
// No call was ringing.
return;
}
}
answerRingingCallInternal调用PhoneUtils中相关方法,例如answerCall方法,其实通话UI中接听电话调用的也是该方法,可见phone服务就是开放部分功能对外使用。
frameworks/base/telephony/java/android/telephony/TelephonyManager.java
大多三方app不必直接使用ITelephony.aidl,用TelephonyManager即可,这个是sdk中设计的通讯相关类。
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
getITelephony方法获取的就是phone服务
public String getDeviceId() {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
return telephony.getDeviceId(mContext.getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
return null;
}
}
拿getDeviceId举例,就是使用phone服务获取设备imei或者meid