Android System Server大纲之TelecomLoaderService

来源:互联网 发布:java恶魔城 编辑:程序博客网 时间:2024/05/22 04:34

Android System Server大纲之TelecomLoaderService

Telecom:通话逻辑控制

前言

在Android 5.0版本中,Android大幅地修改了Call(通话)模块,把Call的逻辑处理从Telephony抽出来,独立成Telecom模块。从此Call的流程中就多了Telecom,分工越来越明细,耦合度进一步降低,给维护带来了良好的改进。但是逻辑上也稍微变得复杂了那么一些。从Android 5.0开始到现在的最新的Android 7.0,Call的架构如下:

这里写图片描述

从Android 4.4开始,Android出于对Android安全方面的考虑,创立了默认APP的机制,当然这个默认APP的机制值限制于浏览器、通话、短彩信三个模块,只有用户设置了对应模块功能的默认APP,这个APP才能完成这些模块的功能,读者可以参考文章《Android default phone mechanism 》。

TelecomLoaderService在开机时会加载Call架构中Telecom的模块,把Telecom模块的服务添加在系统服务当中。对默认短信、通话模块的默认APP进行相应的授权,当然,这个是Android 6.0运行时权限处理时才需要添加的。运行时权限读者可以参考文章《Android M App Permissions 》。

TelecomLoaderService的启动

参考文章《Android系统之System Server大纲 》可知,启动过程如下:

mSystemServiceManager.startService(TelecomLoaderService.class);

这条语句定义在文件frameworks/base/services/java/com/android/server/SystemServer.java中。

参考文章《Android系统之System Server大纲 》中系统服务的启动方式,TelecomLoaderService启动之后会回调方法onStart(),以及system_process启动完毕后会回调所有SystemService的onBootPhase()方法。

@Overridepublic void onStart() {}@Overridepublic void onBootPhase(int phase) {    if (phase == PHASE_ACTIVITY_MANAGER_READY) {        registerDefaultAppNotifier();        registerCarrierConfigChangedReceiver();        connectToTelecom();    }}

这些方法定义在文件frameworks/base/services/core/java/com/android/server/telecom/TelecomLoaderService.java中。

上面的代码中,onStart()方法什么事情也没有做,onBootPhase()中分别调用了registerDefaultAppNotifier()、registerCarrierConfigChangedReceiver()、connectToTelecom(),前两个方法会监听一些数据的变化,如默认短彩信APP的变化等,本文不再往下阐述它们。最后一个方法connectToTelecom()就是便是连接到Telecom。如下:

private static final String SERVICE_ACTION = "com.android.ITelecomService";private static final ComponentName SERVICE_COMPONENT = new ComponentName(        "com.android.server.telecom",        "com.android.server.telecom.components.TelecomService");private void connectToTelecom() {    synchronized (mLock) {        TelecomServiceConnection serviceConnection = new TelecomServiceConnection();        Intent intent = new Intent(SERVICE_ACTION);        intent.setComponent(SERVICE_COMPONENT);        int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE                | Context.BIND_AUTO_CREATE;        // Bind to Telecom and register the service        if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {            mServiceConnection = serviceConnection;        }    }}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/telecom/TelecomLoaderService.java中。

实例化一个Intent,action是SERVICE_ACTION,以及指定Component为SERVICE_COMPONENT,随后调用bindServiceAsUser绑定远程服务,在Android四大组件的Service架构中,启动/绑定一个Service,需要传递一个ServiceConnection的子类,上面的代码传的是TelecomServiceConnection。被绑定的这个服务定义在文件packages/services/Telecomm/src/com/android/server/telecom/components/TelecomService.java中。当成功绑定应用com.android.server.telecom/.components.TelecomService中的Service后,便会回调TelecomServiceConnection中的onServiceConnected()方法:

public void onServiceConnected(ComponentName name, IBinder service) {    // Normally, we would listen for death here, but since telecom runs in the same process    // as this loader (process="system") thats redundant here.    try {        SmsApplication.getDefaultMmsApplication(mContext, false);        ServiceManager.addService(Context.TELECOM_SERVICE, service);        synchronized (mLock) {            ......                    if (smsComponent != null) {                        ......                            packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(                                    smsComponent.getPackageName(), userid);                        }                    }                }                if (mDefaultDialerAppRequests != null) {                    ......                            packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(                                    packageName, userId);                        }                    }                }                if (mDefaultSimCallManagerRequests != null) {                    ......                            packageManagerInternal                                    .grantDefaultPermissionsToDefaultSimCallManager(                                            packageName, userId);              ......}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/telecom/TelecomLoaderService.java中。

为了看起来简洁,这里省略了很多代码,但是不会影响对功能的理解。在onServiceConnected()方法中,主要完成4个事情。

第一:

把Context.TELECOM_SERVICE添加到系统的服务中,这里的IBinder是绑定service返回的远程句柄,这个句柄的实现定义在文件packages/services/Telecomm/src/com/android/server/telecom/TelecomServiceImpl.java中,在以后的文章中再阐述这个服务。

第二:

给默认的短彩信(SMS)应用授予运行时权限。

第三:

给默认的通话(Dialer)应用授予运行时权限。

第四:

给默认的SimCallManager应用授予运行时权限。

由于授权的过程是一样的,本文就以通话的授权为例,阐述这个过程:

public void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId) {    synchronized (mPackages) {        mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultDialerAppLPr(                packageName, userId);    }}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java中。

这里直接调用了grantDefaultPermissionsToDefaultDialerAppLPr()方法,如下:

public void grantDefaultPermissionsToDefaultDialerAppLPr(String packageName, int userId) {    PackageParser.Package dialerPackage = getPackageLPr(packageName);    if (dialerPackage != null            && doesPackageSupportRuntimePermissions(dialerPackage)) {        grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, false, true, userId);        grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, false, true, userId);        grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, false, true, userId);        grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, false, true, userId);    }}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java中。

通过getPackageLPr()把Dialer抽象成PackageParser.Package对象,调用grantRuntimePermissionsLPw()分别给Dialer应用授予PHONE_PERMISSIONS、CONTACTS_PERMISSIONS、SMS_PERMISSIONS、MICROPHONE_PERMISSIONS权限,这几个权限的明细如下:

private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();static {    PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE);    PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE);    PHONE_PERMISSIONS.add(Manifest.permission.READ_CALL_LOG);    PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG);    PHONE_PERMISSIONS.add(Manifest.permission.ADD_VOICEMAIL);    PHONE_PERMISSIONS.add(Manifest.permission.USE_SIP);    PHONE_PERMISSIONS.add(Manifest.permission.PROCESS_OUTGOING_CALLS);}
private static final Set<String> CONTACTS_PERMISSIONS = new ArraySet<>();static {    CONTACTS_PERMISSIONS.add(Manifest.permission.READ_CONTACTS);    CONTACTS_PERMISSIONS.add(Manifest.permission.WRITE_CONTACTS);    CONTACTS_PERMISSIONS.add(Manifest.permission.GET_ACCOUNTS);}
private static final Set<String> SMS_PERMISSIONS = new ArraySet<>();static {    SMS_PERMISSIONS.add(Manifest.permission.SEND_SMS);    SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_SMS);    SMS_PERMISSIONS.add(Manifest.permission.READ_SMS);    SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_WAP_PUSH);    SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_MMS);    SMS_PERMISSIONS.add(Manifest.permission.READ_CELL_BROADCASTS);}
private static final Set<String> MICROPHONE_PERMISSIONS = new ArraySet<>();static {    MICROPHONE_PERMISSIONS.add(Manifest.permission.RECORD_AUDIO);}

所以,在手机启动后,会给默认的通话应用Dialer授予以上运行时的危险权限。

到这里,TelecomLoaderService的工作基本上就完成了。TelecomLoaderService所负责的事情并不多,由于Android系统用于很多设备,在某些设备上,会没有Telecom模块,所以,独立一个TelecomLoaderService来加载Telecom模块,也是非常美好的一个业务分配。

总结

TelecomLoaderService的名字非常完美的总结了TelecomLoaderService所需要完成的业务,虽然TelecomLoaderService的业务并不多,也不是很难理解,但是涉及到其它模块却不是很少,有TelecomService、默认应用、运行时权限等等。最后附一张时序图:

这里写图片描述

0 0