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

Android Java 系统服务框架

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

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

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

Vibrator服务提供的控制手机振动的接口,应用可以调用 Vibrator 的接口来让手机产生振动,达到提醒用户的目的。
从源码(frameworks/base/core/java/android/os/Vibrator.java)中可以看到 Vibrator 是一个抽象类,常用的接口如下:

    /*
    * 是否有振动功能
    */
    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);
    }

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

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

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

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

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


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;
}


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

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

其数据通过 registerService 方法插入:

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);
}

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

static {





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



}

这里传入了一个匿名对象,内部方法返回了一个 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);
        }
    }
}

在构造函数中有我们熟悉的 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);
}



除了 AIDL 生成的代理端,还需要对应的服务端类,这个类是 VibratorService,需要自己实现:

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





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




}

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

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

// 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();
}

从上面的分析,我们可以总结出 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 {
     //......
    }
    
  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 系统服务 中我们添加了一个 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,
            //......
    }    

实现一个抽象类 JavaHello:

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




public abstract class JavaHello {
    abstract void sayhello();
	abstract int sayhello_to(String name);
}

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

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;
    }

}

接着在 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 Vibrator createService(ContextImpl ctx) {
            return new SystemJavaHello();
        }});
}

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

com.yuandaima

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

source build/envsetup.sh

lunch  rice14-eng
make update-api
make -j32
emulator

然后编译 App 使用的 Jar 包:

source build/envsetup.sh

lunch rice14-eng
# Android10 及以前
make framework
# Android11 及以后
#make framework-minus-apex

编译完成后,我们在 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()
        
    }
}



接着修改 app/build.gradle:

dependencies {
    compileOnly files('framework/framework.jar')
    //.......
}


最后在 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");
    }
}

接着添加 selinux 配置:

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

untrusted_app.te

allow untrusted_app JavaHelloServiceType:service_manager find;

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

参考资料

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYxfUuf2' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片