本文基于Android 13的framework层添加系统接口,为应用层提供读写函数、以及执行命令!
添加接口
frameworks/base/core/java/android/app/IDevices.aidl
1 2 3 4 5 6 7 8 9 10
| package android.app; interface IDevices { String readFile(String path); void writeFile(String path,String data); String shellExec(String cmd); }
|
添加系统服务的Manager
frameworks/base/core/java/android/app/DevicesManager.java
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
| package android.app;
import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import android.util.Slog;
@SystemService(Context.DEVICES_SERVICE) public class DevicesManager { Context mContext; IDevices mService;
public DevicesManager(Context context,IDevices service){ if(service==null){ Slog.e("DevicesManager","Construct service is null"); } mContext = context; mService = service; }
public String shellExec(String cmd){ if(mService != null){ try{ Slog.e("DevicesManager","shellExec"); return mService.shellExec(cmd); }catch(RemoteException e){ Slog.e("DevicesManager","RemoteException "+e); } }else{ Slog.e("DevicesManager","mService is null"); } return ""; }
public String readFile(String path){ if(mService != null){ try{ Slog.e("DevicesManager","readFile"); return mService.readFile(path); }catch(RemoteException e){ Slog.e("DevicesManager","RemoteException "+e); } }else{ Slog.e("DevicesManager","mService is null"); } return ""; }
public void writeFile(String path,String data){ if(mService != null){ try{ Slog.e("DevicesManager","writeFile"); mService.writeFile(path,data); }catch(RemoteException e){ Slog.e("DevicesManager","RemoteException "+e); } }else{ Slog.e("DevicesManager","mService is null"); } }
}
|
添加系统服务,实现aidl文件的接口
frameworks/base/services/core/java/com/android/server/DevicesService.java
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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
| package com.android.server;
import android.app.IDevices; import android.content.Context; import android.os.Build; import android.util.Log; import android.util.Slog; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import libcore.io.IoUtils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.RandomAccessFile; import android.util.Base64; public class DevicesService extends IDevices.Stub { private Context mContext; private String TAG="DevicesService"; public DevicesService(Context context){ super(); mContext = context; Slog.d(TAG,"Construct"); } @Override public String shellExec(String cmd){ Runtime mRuntime = Runtime.getRuntime(); try { Slog.d(TAG,"shellExec data:"+cmd); Process mProcess = mRuntime.exec(cmd); BufferedReader mReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); StringBuffer mRespBuff = new StringBuffer(); char[] buff = new char[1024]; int ch = 0; while ((ch = mReader.read(buff)) != -1) { mRespBuff.append(buff, 0, ch); } mReader.close(); return mRespBuff.toString(); } catch (IOException e) { e.printStackTrace(); Slog.d(TAG,"shellExec err:"+e.getMessage()); } return ""; } public static void writeTxtToFile(String strcontent, String filePath) { String strFilePath = filePath; String strContent = strcontent + "\n"; try { File file = new File(strFilePath); makeFilePath(file.getParent(),file.getName()); if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } RandomAccessFile raf = new RandomAccessFile(file, "rwd"); raf.setLength(0); long writePosition = raf.getFilePointer(); raf.seek(writePosition); raf.write(strContent.getBytes()); raf.close(); } catch (Exception e) { Log.d("DevicesService","Error on write File:" + e); } } public static File makeFilePath(String filePath, String fileName) { File file = null; makeRootDirectory(filePath); try { file = new File(filePath +"/"+ fileName); if (!file.exists()) { file.createNewFile(); } } catch (Exception e) { e.printStackTrace(); } return file; } public static void makeRootDirectory(String filePath) { File file = null; try { Log.d("FileHelper", "makeRootDirectory "+filePath); file = new File(filePath); if (!file.exists()) { boolean isok= file.mkdir(); Log.d("FileHelper", "makeRootDirectory "+filePath+" "+isok); } } catch (Exception e) { Log.d("DevicesService", e+""); } } public static String readFileAll(String path) { File file = new File(path); StringBuilder sb=new StringBuilder(); if (file != null && file.exists()) { InputStream inputStream = null; BufferedReader bufferedReader = null; try { inputStream = new FileInputStream(file); bufferedReader = new BufferedReader(new InputStreamReader( inputStream)); String outData; while((outData=bufferedReader.readLine())!=null){ sb.append(outData+"\n"); } } catch (Throwable t) { } finally { try { if (bufferedReader != null) { bufferedReader.close(); } } catch (Exception e) { e.printStackTrace(); } try { if (inputStream != null) { inputStream.close(); } } catch (Exception e) { e.printStackTrace(); } } } return sb.toString(); } @Override public String readFile(String path){ return readFileAll(path); } @Override public void writeFile(String path,String data){ writeTxtToFile(data,path); } }
|
添加服务名称
frameworks/base/core/java/android/content/Context.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @StringDef(suffix = { "_SERVICE" }, value = { POWER_SERVICE, /*add_longzhiye*/++ DEVICES_SERVICE, //@hide: POWER_STATS_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE, ACCOUNT_SERVICE, ACTIVITY_SERVICE, ALARM_SERVICE, public static final String POWER_SERVICE = "power"; ++public static final String DEVICES_SERVICE = "devices";
|
将实现的服务注册到系统中去
frameworks/base/core/java/android/app/SystemServiceRegistry.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| registerService(Context.SEARCH_SERVICE, SearchManager.class, new CachedServiceFetcher<SearchManager>() { @Override public SearchManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new SearchManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }});
registerService(Context.DEVICES_SERVICE,DevicesManager.class, new CachedServiceFetcher<DevicesManager>(){ @Override public DevicesManager createService(ContextImpl ctx){ IBinder b = ServiceManager.getService(Context.DEVICES_SERVICE); return new DevicesManager(ctx,IDevices.Stub.asInterface(b)); } });
registerService(Context.SENSOR_SERVICE, SensorManager.class, new CachedServiceFetcher<SensorManager>() { @Override public SensorManager createService(ContextImpl ctx) { return new SystemSensorManager(ctx.getOuterContext(), ctx.mMainThread.getHandler().getLooper()); }});
|
将注册的服务设置成开机启动服务
frameworks/base/services/java/com/android/server/SystemServer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| t.traceBegin("StartTelephonyRegistry"); telephonyRegistry = new TelephonyRegistry( context, new TelephonyRegistry.ConfigurationProvider()); ServiceManager.addService("telephony.registry", telephonyRegistry); t.traceEnd();
t.traceBegin("StartDevicesService"); try{ ServiceManager.addService(Context.DEVICES_SERVICE,new DevicesService(context)); } catch(Throwable e){ Slog.e("DevicesService","Failed to start DevicesService Service "+e); } t.traceEnd();
|
让lint检查忽略掉自己的模块
注(Android 11 以后谷歌强制开启lint检查,lint检查不过编译会报错)
frameworks/base/Android.bp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| metalava_framework_docs_args = "" + "--api-lint-ignore-prefix android.app. " + "--api-lint-ignore-prefix android.icu. " + "--api-lint-ignore-prefix java. " + "--api-lint-ignore-prefix junit. " + "--api-lint-ignore-prefix org. " + "--error NoSettingsProvider " + "--error UnhiddenSystemApi " + "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " + "--hide BroadcastBehavior " + "--hide CallbackInterface " + "--hide DeprecationMismatch " + "--hide HiddenSuperclass " + "--hide HiddenTypeParameter " + "--hide MissingPermission " + "--hide-package android.audio.policy.configuration.V7_0 " + "--hide-package com.android.server " + "--hide RequiresPermission " + "--hide SdkConstant " + "--hide Todo " + "--hide Typo " + "--hide UnavailableSymbol " + "--manifest $(location core/res/AndroidManifest.xml) "
|
编译源码 更新api接口
检查服务是否开启
将编译好的rom 刷入手机,查看sevice list
这里可以看到我们的服务 已经启动了:
服务名称:79 devices: [android.app.IDevices]
1 2 3 4 5 6 7 8 9 10
| longzhiye@longzhiye-laptop:~$ adb shell coral:/ 60 companiondevice: [android.companion.ICompanionDeviceManager] 75 device_identifiers: [android.os.IDeviceIdentifiersPolicyService] 76 device_policy: [android.app.admin.IDevicePolicyManager] 77 device_state: [android.hardware.devicestate.IDeviceStateManager] 78 deviceidle: [android.os.IDeviceIdleController] 79 devices: [android.app.IDevices] 251 virtualdevice: [android.companion.virtual.IVirtualDeviceManager] coral:/
|
调用测试
应用层项目中引入aidl
1 2 3 4 5 6 7 8 9 10
| package android.app;
interface IDevices { String shellExec(String cmd); String readFile(String path); void writeFile(String path,String data); }
|

调用测试:

本文链接:
http://longzhiye.top/2023/11/04/2023-11-04/