@ITelephony.aidl
interface ITelephony {
//发起通话
void dial(String number);
void call(String callingPackage, String number);
boolean showCallScreen();
boolean showCallScreenWithDialpad(boolean showDialpad);
//挂断通话
boolean endCall();
//接听通话
void answerRingingCall();
void silenceRinger();
//通话状态判断
boolean isOffhook();
boolean isRinging();
boolean isIdle();
boolean isRadioOn();
boolean isSimPinEnabled();
void cancelMissedCallsNotification();
//Pin/Puk码查询
boolean supplyPin(String pin);
int getIccPin1RetryCount();
boolean supplyPuk(String puk, String pin);
int[] supplyPinReportResult(String pin);
int[] supplyPukReportResult(String puk, String pin);
boolean handlePinMmi(String dialString);
void toggleRadioOnOff();
boolean setRadio(boolean turnOn);
boolean setRadioPower(boolean turnOn);
void updateServiceLocation();
void enableLocationUpdates();
void disableLocationUpdates();
//数据连接业务
int enableApnType(String type);
int disableApnType(String type);
boolean enableDataConnectivity();
boolean disableDataConnectivity();
boolean isDataConnectivityPossible();
Bundle getCellLocation();
List getNeighboringCellInfo(String callingPkg);
//通话状态获取
int getCallState();
int getDataActivity();
int getDataState();
int getActivePhoneType();
int getCdmaEriIconIndex();
int getCdmaEriIconMode();
String getCdmaEriText();
boolean needsOtaServiceProvisioning();
int getVoiceMessageCount();
//网络、数据类型
int getNetworkType();
int getDataNetworkType();
int getVoiceNetworkType();
boolean hasIccCard();
int getLteOnCdmaMode();
List getAllCellInfo();
void setCellInfoListRate(int rateInMillis);
String transmitIccLogicalChannel(int cla, int command, int channel, int p1, int p2, int p3, String data);
String transmitIccBasicChannel(int cla, int command, int p1, int p2, int p3, String data);
int openIccLogicalChannel(String AID);
boolean closeIccLogicalChannel(int channel);
int getLastError();
byte[] transmitIccSimIO(int fileID, int command, int p1, int p2, int p3, String filePath);
byte[] getATR();
//通话中合并、切换、静音、Dtmf处理
void toggleHold();
void merge();
void swap();
void mute(boolean mute);
void playDtmfTone(char digit, boolean timedShortCode);
void stopDtmfTone();
//添加、删除监听器
void addListener(ITelephonyListener listener);
void removeListener(ITelephonyListener listener);
}
从他所提供的接口来看,其提供了Telephony比较全面的功能,包括:通话、Pin/Puk、Radio状态、数据连接业务等功能的查询或控制。
phoneMgr = PhoneInterfaceManager.init(this, phone, callHandlerServiceProxy);
我们来看具体的创建过程:
@PhoneInterfaceManager.java
static PhoneInterfaceManager init(PhoneGlobals app, Phone phone, CallHandlerServiceProxy callHandlerService) {
synchronized (PhoneInterfaceManager.class) {
if (sInstance == null) {
//创建对象
sInstance = new PhoneInterfaceManager(app, phone, callHandlerService);
} else {
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
}
return sInstance;
}
}
继续看构造方法:
private PhoneInterfaceManager(PhoneGlobals app, Phone phone, CallHandlerServiceProxy callHandlerService) {
mApp = app;
mPhone = phone;
mCM = PhoneGlobals.getInstance().mCM;
mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
mMainThreadHandler = new MainThreadHandler();
mCallHandlerService = callHandlerService;
publish();
}
在构造方法中除了将PhoneGlobals中初始化的Phone、CallManager等信息传递给PhoneInterfaceManager外,还将PhoneInterfaceManager通过publish()注册给ServiceManager:
private void publish() {
//注册给ServiceManager,名字是“phone”
ServiceManager.addService("phone", this);
}
这里看到,PhoneInterfaceManager将自己注册为SystemServer,其他模块可以通过ServiceManager来获取他的服务。
客户端通过ServiceManager获取到PhoneInterfaceManager的代理对象后,就可以对其发起各种请求,我们挑选几个比较重要的事务来简要分析。
public void dial(String number) {
String url = createTelUrl(number);
if (url == null) {
return;
}
PhoneConstants.State state = mCM.getState();
if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
//发送Intent实现拨号
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mApp.startActivity(intent);
}
}
这里可以看到,PhoneInterfaceManager会通过Intent的形式发起拨号的任务。
public boolean endCall() {
//权限检查
enforceCallPermission();
//发送CMD_END_CALL的Message
return (Boolean) sendRequest(CMD_END_CALL, null);
}
private final class MainThreadHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CMD_END_CALL:
request = (MainThreadRequest) msg.obj;
boolean hungUp = false;
int phoneType = mPhone.getPhoneType();
if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
//通过PhoneUtils挂断电话
hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
} else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
//通过PhoneUtils挂断电话
hungUp = PhoneUtils.hangup(mCM);
} else {
throw new IllegalStateException("Unexpected phone type: " + phoneType);
}
request.result = hungUp;
synchronized (request) {
request.notifyAll();
}
break;
default:
break;
}
}
}
在这里,PhoneInterfaceManager又将请求传给了PhoneUtils来处理结束通话的操作。
public boolean supplyPin(String pin) {
//权限检查
enforceModifyPermission();
//通过IccCard来操作
final UnlockSim checkSimPin = new UnlockSim(mPhone.getIccCard());
//启用查询线程
checkSimPin.start();
return checkSimPin.unlockSim(null, pin);
}
看以下线程内部的操作:
synchronized boolean unlockSim(String puk, String pin) {
Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
//通过IccCard来查询Pin、Puk
if (puk == null) {
mSimCard.supplyPin(pin, callback);
} else {
mSimCard.supplyPuk(puk, pin, callback);
}
return mResult;
}
可以看到,最终是通过IccCard来实现Pin、Puk的查询。
public boolean disableDataConnectivity() {
enforceModifyPermission();
//通过ConnectivityManager来禁用数据连接
ConnectivityManager cm = (ConnectivityManager)mApp.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setMobileDataEnabled(false);
return true;
}
这里又通过ConnectivityManager来禁用数据连接业务。
如图所示: