Android Java 系统服务框架与第三方 App 使用自定义 Java 系统服务

8/3/2023

# Android Java 系统服务框架

我们在 Android 开发过程中经常会用到各种各样的系统管理服务,如进行窗口相关的操作会用到窗口管理服务 WindowManager,进行电源相关的操作会用到电源管理服务 PowerManager,还有很多其他的系统管理服务,如通知管理服务 NotifacationManager、振动管理服务 Vibrator、电池管理服务 BatteryManager……

这些 Manager 提供了很多对系统层的控制接口。对于 App 开发者,只需要了解这些接口的使用方式就可以方便的进行系统控制,获得系统各个服务的信息,而不需要了解这些接口的具体实现方式。而对于 Framework 开发者,则需要了解这些 Manager 服务的常用实现模式,维护这些 Manager 的接口,扩展这些接口,或者实现新的Manager。

我们从一个简单的系统服务 Vibrator 服务来看一下一个系统服务是怎样建立的。

Vibrator 服务提供了控制手机振动器的接口,应用可以调用 Vibrator 的接口,让手机产生振动,达到提醒用户的目的。

从源码中可以看到 Vibrator 是一个抽象类,常用的接口如下:

    // frameworks/base/core/java/android/os/Vibrator.java
    /*
    * 是否有振动功能
    */
    public abstract boolean hasVibrator();

    /*
     * 持续振动,但是已经 Deprecated 了
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.VIBRATE)
    public void vibrate(long milliseconds) {
        vibrate(milliseconds, null);
    }

    /*
     * 按节奏重复振动,但是已经 Deprecated 了
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.VIBRATE)
    public void vibrate(long[] pattern, int repeat) {
        vibrate(pattern, repeat, null);
    }

    /*
     * 用于代替上面两个接口
     */
    @RequiresPermission(android.Manifest.permission.VIBRATE)
    public void vibrate(VibrationEffect vibe) {
        vibrate(vibe, null);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

应用中使用振动服务的方法也很简单,如让手机持续振动500毫秒:

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);
1
2

接着我们看下 Vibrator 的获取过程:

getSystemService 方法定义在 frameworks/base/core/java/android/app/ContextImpl.java 中:

@Override
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}
1
2
3
4

SystemServiceRegistry.getSystemService 定义在 frameworks/base/core/java/android/app/SystemServiceRegistry.java 中:

public static Object getSystemService(ContextImpl ctx, String name) {
    ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}
1
2
3
4

上述代码使用了 SYSTEM_SERVICE_FETCHERS,SYSTEM_SERVICE_FETCHERS 是一个 Map 类型:

private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
        new ArrayMap<String, ServiceFetcher<?>>();
1
2

在 SystemServiceRegistry 的静态块中调用了 registerService 插入 Vibrator 对象:

static {
    registerService(Context.VIBRATOR_SERVICE, Vibrator.class,
        new CachedServiceFetcher<Vibrator>() {
            @Override
            public Vibrator createService(ContextImpl ctx) {
                    return new SystemVibrator(ctx);
        }});
}

private static <T> void registerService(String serviceName, Class<T> serviceClass,
        ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这里传入了一个匿名对象,内部方法返回了一个 new 出来的 SystemVibrator,其具体实现如下:

// frameworks/base/core/java/android/os/SystemVibrator.java
// 客户端代理类的马甲
public class SystemVibrator extends Vibrator {
    private static final String TAG = "Vibrator";

    private final IVibratorService mService;
    private final Binder mToken = new Binder();

    @UnsupportedAppUsage
    public SystemVibrator() {
        mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
    }

    @UnsupportedAppUsage
    public SystemVibrator(Context context) {
        super(context);
        mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
    }

    @Override
    public boolean hasVibrator() {
        if (mService == null) {
            Log.w(TAG, "Failed to vibrate; no vibrator service.");
            return false;
        }
        try {
            return mService.hasVibrator();
        } catch (RemoteException e) {
        }
        return false;
    }

    @Override
    public boolean hasAmplitudeControl() {
        if (mService == null) {
            Log.w(TAG, "Failed to check amplitude control; no vibrator service.");
            return false;
        }
        try {
            return mService.hasAmplitudeControl();
        } catch (RemoteException e) {
        }
        return false;
    }

    @Override
    public void vibrate(int uid, String opPkg, VibrationEffect effect,
            String reason, AudioAttributes attributes) {
        if (mService == null) {
            Log.w(TAG, "Failed to vibrate; no vibrator service.");
            return;
        }
        try {
            mService.vibrate(uid, opPkg, effect, attributes, reason, mToken);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to vibrate.", e);
        }
    }

    @Override
    public void cancel() {
        if (mService == null) {
            return;
        }
        try {
            mService.cancelVibrate(mToken);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to cancel vibration.", e);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

在构造函数中有我们熟悉的 AIDL 生成代码,通过 IVibratorService.Stub.asInterface 构建了一个 IVibratorService 代理类。SystemVibrator 通过 IVibratorService 代理类实现了 Vibrator 抽象类的对外接口。

IVibratorService 通过 AIDL 生成:

// frameworks/base/core/java/android/os/IVibratorService.aidl
package android.os;

import android.media.AudioAttributes;
import android.os.VibrationEffect;

/** {@hide} */
interface IVibratorService
{
    boolean hasVibrator();
    boolean hasAmplitudeControl();
    void vibrate(int uid, String opPkg, in VibrationEffect effect, in AudioAttributes attributes,
            String reason, IBinder token);
    void cancelVibrate(IBinder token);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

代理端类又 AIDL 生成,服务端类 VibratorService,需要自己实现:

// frameworks/base/services/core/java/com/android/server/VibratorService.java

public class VibratorService extends IVibratorService.Stub {
    //......

}
1
2
3
4
5
6

振动器的实际操作都是通过 VibratorService 中的 native 函数实现,在 native 层中再调用到 hal 层,hal 层操作驱动,驱动操作实际硬件来完成。

接着我们再来看看,VibratorService 系统服务是如何启动的:

// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    // ......
    VibratorService vibrator = null;
    // ......
    traceBeginAndSlog("StartVibratorService");
    vibrator = new VibratorService(context);
    ServiceManager.addService("vibrator", vibrator);
    traceEnd();
}
1
2
3
4
5
6
7
8
9
10

从上面的分析,我们可以总结出 Vibrator 服务的整个实现流程:

服务端

  1. 实现一个 AIDL 接口文件 IVibratorService(frameworks/base/core/java/android/os/IVibratorService.aidl),定义系统服务接口
  2. 定义 Binder 服务端实现类 VibratorService,实现 IVibratorService 定义的接口 frameworks/base/services/java/com/android/server/VibratorService.java
    public class VibratorService extends IVibratorService.Stub {
     //......
    }
    
    1
    2
    3
  3. VibratorService 开机启动 frameworks/base/services/java/com/android/server/SystemServer.java

客户端

  1. frameworks/base/core/java/android/content/Context.java 中添加服务注册名称, 添加该服务名称, 用于快捷注册和快捷引用
  2. 实现一个抽象类 Vibrator (frameworks/base/core/java/android/os/Vibrator.java),定义了应用中可以访问的一些抽象方法
  3. 定义 SystemVibrator 类 (frameworks/base/core/java/android/os/SystemVibrator.java),继承 Vibrator,实现抽象方法,实际就是 Vibrator Binder 服务端代理类马甲,所有的接口功能都是通过 Binder 服务端代理类实现。
  4. 在 SystemServiceRegistry 的静态块中调用了 registerService 插入 SystemVibrator 对象

# 第三方 App 使用自定义 Java 系统服务

添加 Java 系统服务 (opens new window) 中我们添加了一个 Java 系统服务,不过这个服务并没有按照 Android Java 系统服务框架 的要求编写,导致我们只能在系统 App 中使用我们自定义的 Java 系统服务,接下来我们根据上文的分析来改造它,使得我们能在第三方 App 中使用我们自定义的 Java 系统服务。

服务端不用改动,主要是客户端:

Context.java 中添加服务注册名称, 添加该服务名称, 用于快捷注册和快捷引用:

    // frameworks/base/core/java/android/content/Context.java
   public static final String JAVA_HELLO_SERVICE = "java_hello_service";

    /** @hide */
    @StringDef(suffix = { "_SERVICE" }, value = {
            JAVA_HELLO_SERVICE,
            POWER_SERVICE,
            WINDOW_SERVICE,
            //......
    }    
1
2
3
4
5
6
7
8
9
10

实现一个抽象类 JavaHello,用于定义服务对外的接口:

// frameworks/base/core/java/com/yuandaima/JavaHello.java
package com.yuandaima;

public abstract class JavaHello {
    public abstract void sayhello();
	public abstract int sayhello_to(String name);
}
1
2
3
4
5
6
7

定义 SystemJavaHello 类 ,继承 JavaHello,实现抽象方法:

// frameworks/base/core/java/com/yuandaima/SystemJavaHello.java
package com.yuandaima;

import android.os.ServiceManager;
import android.os.RemoteException;

public class SystemJavaHello extends JavaHello {

    private final IJavaHelloService mService;

    public SystemJavaHello() {
        mService = IJavaHelloService.Stub.asInterface(ServiceManager.getService("JavaHelloService"));
    }

    public void sayhello() {
        if(mService != null) {
            try {
                mService.sayhello();
            } catch (RemoteException e) {
            }
        }
    }

	public int sayhello_to(String name) {
        if(mService != null) {
            try {
                return mService.sayhello_to(name);
            } catch (RemoteException e) {
            }
        } 
        return 0;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

接着在 frameworks/base/core/java/android/app/SystemServiceRegistry.java 的静态块中调用了 registerService 插入 SystemJavaHello 对象:

import com.yuandaima.SystemJavaHello;
import com.yuandaima.JavaHello;

static {
        registerService(Context.JAVA_HELLO_SERVICE, JavaHello.class,
            new CachedServiceFetcher<JavaHello>() {
        @Override
        public JavaHello createService(ContextImpl ctx) {
            return new SystemJavaHello();
        }});
}
1
2
3
4
5
6
7
8
9
10
11

在 Android 10 中,针对非 SDK 接口进行了限制,默认是 blacklist 的,为了让我们的 App 能使用我们自定义的 Java 服务,需要在 frameworks/base/config/hiddenapi-greylist-packages.txt 中最后一行增加:

com.yuandaima
1

接着编译系统启动模拟器:

source build/envsetup.sh
lunch  rice14-eng
#make update-api
make -j32
emulator
1
2
3
4
5

然后编译 App 使用的 Jar 包:

source build/envsetup.sh
lunch rice14-eng
# Android10 及以前
make framework
# Android11 及以后
#make framework-minus-apex
1
2
3
4
5
6

编译完成后,我们在 out/target/common/obj/JAVA_LIBRARIES/framework_intermediates 目录下找到 classes.jar 文件,为方便识别,我们将该文件拷贝到其他地方,并将文件名修改为 framework.jar

使用 Android Studio(推荐版本 3.6.3) 创建一个 Empty Activity 空项目。接着把之前准备好的 framework.jar 拷贝到项目的 app/framework 文件夹中。

接着修改项目根目录下的 build.gradle,添加如下内容:

allprojects {

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            //相对位置,根据存放的位置修改路径
            options.compilerArgs.add('-Xbootclasspath/p:app/framework/framework.jar')
        }
    }

    repositories {
        google()
        jcenter()
        
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

接着修改 app/build.gradle:

dependencies {
    compileOnly files('framework/framework.jar')
    //.......
}
1
2
3
4

最后在 MainActivity 中加入使用自定义服务的代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        JavaHello javaHello = (JavaHello) getSystemService(Context.JAVA_HELLO_SERVICE);
        javaHello.sayhello_to("test");
    }
}
1
2
3
4
5
6
7
8
9
10
11

接着添加 selinux 配置:

同时修改 system/sepolicy/private 和 system/sepolicy/prebuilts/api/29.0/private 目录下的:

untrusted_app.te

allow untrusted_app JavaHelloServiceType:service_manager find;
1

接着运行启动 App,就可以在看到我们调用成功的 Log 了:

# 参考资料

# 关于

我叫阿豪,2015 年本科毕业于国防科学技术大学指挥信息系统专业,毕业后从事信息化装备的研发工作,主要研究方向是 Android Framework 与 Linux Kernel。

如果你对 Android Framework 感兴趣或者正在学习 Android Framework,可以关注我的微信公众号和抖音,我会持续分享我的学习经验,帮助正在学习的你少走一些弯路。学习过程中如果你有疑问或者你的经验想要分享给大家可以添加我的微信,我拉你进技术交流群。