本文作者
作者:qing的世界
链接:
https://juejin.cn/post/7152278664980201503
本文由作者授权发布。
历史系列文章:
今天我想用通俗一点的语言稍微讲解一下安卓端的CS架构,每个组件设计的理念,让大家更清晰的理解一下安卓的客户端和服务器到底是个什么东西。
简单的说,安卓的APP应用层可以当做是安卓C/S架构中的客户端。而安卓系统中,运行在系统进程system process的系统服务system service,被认为是服务器端。
public CellLocation getCellLocation() {
try {
Bundle bundle = getITelephony().getCellLocation();
return CellLocation.newFromBundle(bundle);
}
catch (RemoteException ex) {
return null;
}
public class PhoneInterfaceManager extends ITelephony.Stub {
@Override public CellIdentity getCellLocation(String callingPackage, String callingFeatureId) {
.....
}
}
这个小节我先简单的教大家怎么找到manager类的对应服务器端的实现,至于安卓是具体怎么实现这样的一对一映射我们接下来的小节再详细说明。
dependencies {
compileOnly 'javax.servlet:servlet-api:2.5'
}
但是在之前的图里,我明明还是把Manager类画在了APP的进程里面,也就是说运行时我们还是需要Manager类的。那这些类到底从哪来的呢?
关于Zygote的细节我们就不聊那么多,网上资源挺多的。但是我们需要知道的重点就是,每一个APP都是Zygote复制出来的一个进程(具体的实现应该是linux里面的fork),这个进程Dalvik(或者是ART)都是一个独立的虚拟机,virtual machine。在最原始的进程里面,所有的public API, 也就是那些客户端的Manager类都已经被加载进该进程(虚拟机)了。所以当每个app被启动的时候,启动APP的dalvik或者ART已经加载过了所有的客户端API的类。这样,app在运行时就不会找不到对应的Manager类 (symbol not found),但是同时通过android的stub sdk又减少了apk大小,可以说是一举两得。
https://man7.org/linux/man-pages/man2/fork.2.html
/** *
Get the stream type whose volume is driving the UI sounds volume.
UI sounds are screen lock/unlock, camera shutter, key clicks...
@hide
*/
public int getMasterStreamType() {
}
加了这个注释之后,安卓在编译Stub sdk 的时候,就会把带这个注释的方法从stub类里面删掉,这样导致app开发者在编译阶段找不到该方法,从而达到隐藏的效果。大家通过android studio打开AudioManager的stub 就可以发现。
void enforceShellRestriction(String restriction, int userHandle)
{
if (Binder.getCallingUid() == Process.SHELL_UID)
{ if (userHandle < 0 || mUserManager.hasUserRestriction(restriction, userHandle))
{ throw new SecurityException("Shell does not have permission to access user " + userHandle);
}
} }
说了这么多客户端的实现。是时候聊聊服务器端的实现了。服务器端的具体实现,我推荐大家看看这篇文章 如何实现一个 System Services?,这是博主吴小龙写的,步骤非常详细,大家可以先过一遍有个印象。
https://juejin.cn/post/6961760668705882142
ServiceManager and SystemService
所以这一套设计方案说到底,就是为了开发者,尤其是app开发者更方便的开发而已。它的出现让跨进程变得更方便,但是这个跨进程也是在现有框架下进行,比如,客户端app开发要想和系统进行通信,必须通过系统现有的service与manager API进行通信,也还是有一定的限制。
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
{
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
}
catch (RemoteException e) { Log.e(TAG, "error in addService", e); }
}
@SystemApi(client = Client.SYSTEM_SERVER)
public abstract class SystemService {
public void onBootPhase(@BootPhase int phase) {}
}
class ThermalManagerService extends SystemService {
@Override public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
onActivityManagerReady();
}
}
}
那么有了这么多服务,在哪里开始执行呢。就在SystemServer里面。
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/power/ThermalManagerService.java;drc=b0193ccac5b8399f9b5ef270d102b5a50f9446ab;l=72
try {
t.traceBegin("StartServices");
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);
}
ServiceManager.addService("sec_key_att_app_id_provider", new KeyAttestationApplicationIdProviderService(context));
class SystemServiceManager {
private List<SystemService> mServices;
}
最显著的就是蓝牙模块:
https://cs.android.com/android/platform/superproject/+/master:packages/modules/Bluetooth/
APEX文件的具体格式可以看这:
https://source.android.com/docs/core/ota/apex
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!