溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么實(shí)現(xiàn)System Services

發(fā)布時(shí)間:2021-06-12 11:07:37 來(lái)源:億速云 閱讀:301 作者:小新 欄目:編程語(yǔ)言

這篇文章給大家分享的是有關(guān)怎么實(shí)現(xiàn)System Services的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

System Service 是如何寫的?

應(yīng)用調(diào)用

 DisplayManager dm = getSystemService(DisplayManager.class);
 dm.setTemporaryBrightness(0.0f);
 Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 0);

看下 getSystemService 方法,在 Context 類里。

Context#getSystemService

public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) {
    // Because subclasses may override getSystemService(String) we cannot
    // perform a lookup by class alone.  We must first map the class to its
    // service name then invoke the string-based method.
    String serviceName = getSystemServiceName(serviceClass);
    return serviceName != null ? (T)getSystemService(serviceName) : null;
}

public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass);

ContextImpl#getSystemService

@Override
public String getSystemServiceName(Class<?> serviceClass) {
    return SystemServiceRegistry.getSystemServiceName(serviceClass);
}

繼續(xù)跟 SystemServiceRegistry.getSystemServiceName。

SystemServiceRegistry#getSystemServiceName

public static String getSystemServiceName(Class<?> serviceClass) {
    if (serviceClass == null) {
        return null;
    }
    final String serviceName = SYSTEM_SERVICE_NAMES.get(serviceClass);
    if (sEnableServiceNotFoundWtf && serviceName == null) {
        // This should be a caller bug.
        Slog.wtf(TAG, "Unknown manager requested: " + serviceClass.getCanonicalName());
    }
    return serviceName;
}

什么時(shí)候 registerService 的?

public final class SystemServiceRegistry {
    static {
        registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
        new CachedServiceFetcher<DisplayManager>() {
            @Override
            public DisplayManager createService(ContextImpl ctx) {
                return new DisplayManager(ctx.getOuterContext());
            }
        });
    }
}
private static <T> void registerService(@NonNull String serviceName,
        @NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}

結(jié)合上面的分析代碼可以知道 getSystemService(DisplayManager.class)得到的是一個(gè) DisplayManager 的實(shí)例。

接下來(lái)看 dm.setTemporaryBrightness 方法。

DisplayManager#setTemporaryBrightness

public void setTemporaryBrightness(float brightness) {
    mGlobal.setTemporaryBrightness(brightness);
}

mGlobal 是 DisplayManagerGlobal 對(duì)象。

DisplayManagerGlobal#setTemporaryBrightness

private final IDisplayManager mDm;

private DisplayManagerGlobal(IDisplayManager dm) {
    mDm = dm;
}

public static DisplayManagerGlobal getInstance() {
    synchronized (DisplayManagerGlobal.class) {
        if (sInstance == null) {
            IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
            if (b != null) {
                sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
            }
        }
        return sInstance;
    }
}
public void setTemporaryBrightness(float brightness) {
    try {
        mDm.setTemporaryBrightness(brightness);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

mDm 是 IDisplayManager 對(duì)象,初始化在IDisplayManager.Stub.asInterface(ServiceManager.getService(Context.DISPLAY_SERVICE)),看到 IDisplayManager 是一個(gè) aidl 文件:frameworks/base/core/java/android/hardware/display/IDisplayManager.aidl,AIDL (Android Interface Definition Language) 是 Android 中的接口定義文件,為系統(tǒng)提供了一種簡(jiǎn)單跨進(jìn)程通信方法,先不管 AIDL。

IDisplayManager

IDisplayManager 定義了包括 setTemporaryBrightness 的幾個(gè)接口。

interface IDisplayManager {
    //……
    void registerCallback(in IDisplayManagerCallback callback);

    // Requires CONFIGURE_WIFI_DISPLAY permission.
    // The process must have previously registered a callback.
    void startWifiDisplayScan();

    // Requires CONFIGURE_WIFI_DISPLAY permission.
    void stopWifiDisplayScan();

    // Requires CONFIGURE_WIFI_DISPLAY permission.
    void connectWifiDisplay(String address);

    // No permissions required.
    void disconnectWifiDisplay();

    // Temporarily sets the display brightness.
    void setTemporaryBrightness(float brightness);
    //……
}

IDisplayManager 只是接口,需要找下哪里實(shí)現(xiàn)了它,搜索是在 BinderService,BinderService 是 DisplayManagerService 內(nèi)部類。

final class BinderService extends IDisplayManager.Stub {
    @Override // Binder call
    public void setTemporaryBrightness(float brightness) {
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
                "Permission required to set the display's brightness");
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mSyncRoot) {
                mDisplayPowerController.setTemporaryBrightness(brightness);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }
}

mDisplayPowerController.setTemporaryBrightness(brightness)后面經(jīng)過(guò)一系列調(diào)用會(huì)到 LightsService#setLight_native,通過(guò) JNI 調(diào)用到 native 層,調(diào)用底層進(jìn)行背光調(diào)節(jié),關(guān)于背光調(diào)節(jié)后面文章再細(xì)講。

SystemServer

DisplayManagerService 是繼承了 SystemService,DisplayManagerService 是怎么注冊(cè)為系統(tǒng)服務(wù)的呢?在 SystemServer 里面:

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    t.traceBegin("StartDisplayManager");
    //開(kāi)啟DisplayManagerService
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    t.traceEnd();
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    //通知服務(wù)系統(tǒng)啟動(dòng)完成
    t.traceBegin("MakeDisplayManagerServiceReady");
    try {
        // TODO: use boot phase and communicate these flags some other way
        mDisplayManagerService.systemReady(safeMode, mOnlyCore);
    } catch (Throwable e) {
        reportWtf("making Display Manager Service ready", e);
    }
    t.traceEnd();
}

看完 DisplayManagerService 是怎么寫的,不妨模仿寫個(gè)。 所謂看著代碼,感覺(jué)還是挺簡(jiǎn)單的,實(shí)際操作起來(lái),各種編譯報(bào)錯(cuò)……

如何寫個(gè) System Service

先上圖:

怎么實(shí)現(xiàn)System Services

1.編寫 AIDL 文件

新建 frameworks/base/core/java/android/hardware/wuxiaolong/IWuXiaolongManager.aidl,內(nèi)容如下:

package android.hardware.wuxiaolong;
/** @hide */
interface IWuXiaolongManager {

    String getName();
}

2.Context 定義變量

在 Context 里定義一個(gè)代表 wuxiaolong 服務(wù)的字符串 frameworks/base/core/java/android/content/Context.java

public static final String WUXIAOLONG_SERVICE = "wuxiaolong";

3.編寫系統(tǒng)服務(wù)

frameworks/base/services/core/java/com/android/server/wuxiaolong/WuXiaolongManagerService.java

package com.android.server.wuxiaolong;

import android.content.Context;
import android.hardware.wuxiaolong.IWuXiaolongManager;

public class WuXiaolongManagerService extends IWuXiaolongManager.Stub {
    private final Context mContext;

    public WuXiaolongManagerService(Context context) {
        super();
        mContext = context;
    }

    @Override
    public String getName() {
        String name = "WuXiaolong..";
        return name;
    }
}

4.注冊(cè)系統(tǒng)服務(wù)

frameworks/base/services/java/com/android/server/SystemServer.java

import com.android.server.wuxiaolong.WuXiaolongManagerService;
private void startOtherServices() {
    // 部分代碼省略...
    try {
        android.util.Log.d("wxl","SystemServer WuXiaolongManagerService");
        ServiceManager.addService(Context.WUXIAOLONG_SERVICE, new WuXiaolongManagerService(context));
    } catch (Throwable e) {
        reportWtf("starting WuXiaolongManagerService", e);
    }
    // 部分代碼省略...
}

5.編寫 Manager 類

frameworks/base/core/java/android/hardware/wuxiaolong/WuXiaolongManager.java

package android.hardware.wuxiaolong;

import android.os.IBinder;
import android.os.ServiceManager;
import android.hardware.wuxiaolong.IWuXiaolongManager;
import android.content.Context;
import android.os.RemoteException;
import android.compat.annotation.UnsupportedAppUsage;
import android.annotation.Nullable;
import android.os.ServiceManager.ServiceNotFoundException;
import android.annotation.SystemService;

@SystemService(Context.WUXIAOLONG_SERVICE)
public class WuXiaolongManager {
    private static WuXiaolongManager sInstance;
    private final IWuXiaolongManager mService;
    private Context mContext;

    /**
     * @hide
     */
    public WuXiaolongManager(IWuXiaolongManager iWuXiaolongManager) {
        mService = iWuXiaolongManager;
    }

    /**
     * Gets an instance of the WuXiaolong manager.
     *
     * @return The WuXiaolong manager instance.
     * @hide
     */
    @UnsupportedAppUsage
    public static WuXiaolongManager getInstance() {
        android.util.Log.d("wxl", "WuXiaolongManager getInstance");
        synchronized (WuXiaolongManager.class) {
            if (sInstance == null) {

                try {
                    IBinder b = ServiceManager.getServiceOrThrow(Context.WUXIAOLONG_SERVICE);
                    sInstance = new WuXiaolongManager(IWuXiaolongManager.Stub
                            .asInterface(ServiceManager.getServiceOrThrow(Context.WUXIAOLONG_SERVICE)));
                } catch (ServiceNotFoundException e) {
                    throw new IllegalStateException(e);
                }

            }
            return sInstance;
        }
    }

    @Nullable
    public String getName() {
        android.util.Log.d("wxl", "WuXiaolongManager getName");
        try {
            return mService.getName();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

6.注冊(cè) Manager

frameworks/base/core/java/android/app/SystemServiceRegistry.java

import android.hardware.wuxiaolong.WuXiaolongManager;
static {
    registerService(Context.WUXIAOLONG_SERVICE, WuXiaolongManager.class,
            new CachedServiceFetcher<WuXiaolongManager>() {
                @Override
                public WuXiaolongManager createService(ContextImpl ctx)
                        throws ServiceNotFoundException {
                    android.util.Log.d("wxl","SystemServiceRegistry registerService");
                    return WuXiaolongManager.getInstance();
                }});
}

7.應(yīng)用調(diào)用

WuXiaolongManager mWuXiaolongManager = (WuXiaolongManager)mContext.getSystemService(Context.WUXIAOLONG_SERVICE);
android.util.Log.d("wxl","Name="+ mWuXiaolongManager.getName());

8.解決報(bào)錯(cuò)

編譯報(bào)錯(cuò)
  • 報(bào)錯(cuò) 1:

******************************
You have tried to change the API from what has been previously approved.

To make these errors go away, you have two choices:
   1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)
      to the new methods, etc. shown in the above diff.

   2. You can update current.txt and/or removed.txt by executing the following command:
         make api-stubs-docs-non-updatable-update-current-api

      To submit the revised current.txt to the main Android repository,
      you will need approval.
******************************

需要執(zhí)行 make update-api,更新接口,會(huì)多出來(lái):

frameworks/base/api/current.txt

diff --git a/api/current.txt b/api/current.txt
index 6b1a96c..0779378 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -10256,6 +10256,7 @@ package android.content {
     field public static final String WIFI_RTT_RANGING_SERVICE = "wifirtt";
     field public static final String WIFI_SERVICE = "wifi";
     field public static final String WINDOW_SERVICE = "window";
+    field public static final String WUXIAOLONG_SERVICE = "wuxiaolong";
   }

   public class ContextWrapper extends android.content.Context {
@@ -18318,6 +18319,14 @@ package android.hardware.usb {

 }

+package android.hardware.wuxiaolong {
+
+  public class WuXiaolongManager {
+    method @Nullable public String getName();
+  }
+
+}
+
 package android.icu.lang {

frameworks/base/non-updatable-api/current.txt

diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index adf1bb5..e738c02 100755
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -10256,6 +10256,7 @@ package android.content {
     field public static final String WIFI_RTT_RANGING_SERVICE = "wifirtt";
     field public static final String WIFI_SERVICE = "wifi";
     field public static final String WINDOW_SERVICE = "window";
+    field public static final String WUXIAOLONG_SERVICE = "wuxiaolong";
   }

   public class ContextWrapper extends android.content.Context {
@@ -18318,6 +18319,14 @@ package android.hardware.usb {

 }

+package android.hardware.wuxiaolong {
+
+  public class WuXiaolongManager {
+    method @Nullable public String getName();
+  }
+
+}
+
 package android.icu.lang {
  • 報(bào)錯(cuò) 2:

[0mManagers must always be obtained from Context; no direct constructors [ManagerConstructor]

編寫 Manager 類需寫成單例。

  • 報(bào)錯(cuò) 3:

Missing nullability on method `getName` return [MissingNullability]

getName 方法加上@Nullable注解。

運(yùn)行報(bào)錯(cuò)
04-08 15:41:38.798   297   297 E SELinux : avc:  denied  { find } for pid=12717 uid=1000 name=wuxiaolong scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=1
04-08 15:41:38.802 12717 12758 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: PowerManagerService
04-08 15:41:38.802 12717 12758 E AndroidRuntime: java.lang.IllegalStateException: android.os.ServiceManager$ServiceNotFoundException: No service published for: wuxiaolong
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.hardware.wuxiaolong.WuXiaolongManager.getInstance(WuXiaolongManager.java:47)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.app.SystemServiceRegistry$27.createService(SystemServiceRegistry.java:497)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.app.SystemServiceRegistry$27.createService(SystemServiceRegistry.java:493)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.app.SystemServiceRegistry$CachedServiceFetcher.getService(SystemServiceRegistry.java:1760)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.app.SystemServiceRegistry.getSystemService(SystemServiceRegistry.java:1440)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.app.ContextImpl.getSystemService(ContextImpl.java:1921)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at com.android.server.display.DisplayPowerController.updatePowerState(DisplayPowerController.java:1191)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at com.android.server.display.DisplayPowerController.access$700(DisplayPowerController.java:92)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at com.android.server.display.DisplayPowerController$DisplayControllerHandler.handleMessage(DisplayPowerController.java:2074)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:223)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.os.HandlerThread.run(HandlerThread.java:67)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at com.android.server.ServiceThread.run(ServiceThread.java:44)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: Caused by: android.os.ServiceManager$ServiceNotFoundException: No service published for: wuxiaolong
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.os.ServiceManager.getServiceOrThrow(ServiceManager.java:153)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	at android.hardware.wuxiaolong.WuXiaolongManager.getInstance(WuXiaolongManager.java:40)
04-08 15:41:38.802 12717 12758 E AndroidRuntime: 	... 12 more

這里是缺少 SELinux 權(quán)限,可執(zhí)行:

adb shell
setenforce 0 (臨時(shí)禁用掉SELinux)
getenforce  (得到結(jié)果為Permissive)

臨時(shí)禁用掉 SELinux,功能就正常了,關(guān)于 SELinux 這里不說(shuō)了,后面有機(jī)會(huì)寫篇 SELinux 文章。

最后 Log 打印如下:

Line 832: 04-08 16:08:55.290 17649 17690 D wxl     : SystemServiceRegistry registerService
Line 833: 04-08 16:08:55.290 17649 17690 D wxl     : WuXiaolongManager getInstance
Line 835: 04-08 16:08:55.292 17649 17690 D wxl     : WuXiaolongManager getName
Line 836: 04-08 16:08:55.293 17649 17690 D wxl     : Name=WuXiaolong..

感謝各位的閱讀!關(guān)于“怎么實(shí)現(xiàn)System Services”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI