Android5.1 Framework分析----如何在SystemServer中新增系統服務
阿新 • • 發佈:2019-01-26
本文以mtk android5.1為研究物件。
Android的系統服務都是託管給ServiceManager管理的,我們可以自定義一個自己的服務,並將其新增到ServiceManager中,本文以新增一個Tts語音服務為例,供應用層呼叫。
1、首先,在frameworks/base/core/java/android/app中新建一個aidl檔案 ITtsManager.aidl,內容如下:
package android.app; interface ITtsManager { int speak(String message, String from); int stop(); }
2、將此aidl檔案加入編譯列表frameworks/base/Android.mk:
LOCAL_SRC_FILES += \
....
core/java/android/app/ITtsManager.aidl \
....
3、在frameworks/base/services/core/java/com/android/server/tts路徑下(路徑可以自己改變)新建一個TtsManagerService.java類,該類繼承了TtsManager.Stub,
}}package com.android.server.tts; import android.content.Context; import android.speech.tts.TtsEngines; import android.speech.tts.TextToSpeech; import android.os.Handler; import android.util.Log; import android.app.ITtsManager; public final class TtsManagerService extends ITtsManager.Stub { private static final String TAG = "TtsManagerService"; final Context mContext; private final TextToSpeech mTts; public TtsManagerService(Context context) { Log.d(TAG, "Tts init complete"); } @Override public int speak(String message, String from) { //TODO: return 0; } @Override public int stop() {<pre name="code" class="java"> //TODO: return 0;
4、還得在frameworks/base/core/java/android/app建立一個管理器類TtsManager.java,
package android.os; import android.content.Context; public class TtsManager { final ITtsManager mService; final Context mContext; public TtsManager(Context context, ITtsManager service) { mContext = context; mService = service; } public int speak(String message, String from) { try { return mService.speak(message, from); } catch (RemoteException e) { e.printStackTrace(); return -1; } } public int stop() { try { return mService.stop(); } catch (RemoteException e) { e.printStackTrace(); return -1; } } }
5、為了讓應用層可以使用getSystemService介面獲得服務,現在需要在ContextImpl.java的static程式碼塊將TtsManager建立起來,
/// M: comment @{ add TtsManagerService by Lee
if ("1".equals(SystemProperties.get("ro.qxt.tts.support"))) {
registerService("qxttts", new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService("qxttts"); //注意:qxttts 是服務名稱
return new TtsManager(ctx, ITtsManager.Stub.asInterface(b));
} });
}
/// @}
6、現在可以將這個服務加入到ServiceManager中了,
try {
Slog.i(TAG, "Tts Manager");
ServiceManager.addService("qxttts", new TtsManagerService(context)); //服務名稱qxttts與上面對應
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Tts Manager", e);
}
7、然後你可以在某個app的activity上獲得這個服務,
((TtsManager)getSystemService("qxttts")).speak("測試用語", "activity");
編譯(先用update-api命令更新sdk),將相應模組push到手機上。。。
現在你可能會出現app啟動報錯的提示。。錯誤類似於speak方法處出現空指標,這是服務沒起來,出現類似如下錯誤,
ServiceManager( 232): add_service('qxttts',45) uid=1000 - PERMISSION DENIED
這是因為SELinux Policy限制,新加一個系統服務,你得先在device/mediatek/common/sepolicy/service_contexts註冊你的服務,
#Lee add begin
qxttts u:object_r:system_server_service:s0
#Lee add end
此處是vendor自己加的檔案,android原生的服務在external/sepolicy/service_contexts中註冊,external/sepolicy/service.te定義了各種型別如system_server_service。
重新編譯,可以驗證了。。。
未完待續,有不對的地方,請指正。