Android adb 命令查询service相关介绍
一、前言
adb查询系统中的service用什么命令?
很多人会说是service list | grep XXXService
但是你会发现四大组件的service并不能这样查询到,
四大组件的Service查询,需要用dumpsys activity services | grep XXXService
两种Service查询有啥区别吗?需要什么命令可以杀死这个Service。
本文讲解一些adb查询和控制Service相关的知识;
这些知识不一定马上有用,但是分析问题有时候会用到,有兴趣的可以收藏看看。
二、adb命令控制service
1、查询系统服务 service list
127|console:/ # service list
Found 177 services:
0 DockObserver: []
1 SkgSystemUI: [com.debug.SystemUI.IMainService]
2 SurfaceFlinger: [android.ui.ISurfaceComposer]
3 accessibility: [android.view.accessibility.IAccessibilityManager]
4 account: [android.accounts.IAccountManager]
5 activity: [android.app.IActivityManager]
6 activity_task: [android.app.IActivityTaskManager]
7 adb: [android.debug.IAdbManager]
8 alarm: [android.app.IAlarmManager]
9 android.hardware.power.IPower/default: [android.hardware.power.IPower]
10 android.os.UpdateEngineService: [android.os.IUpdateEngine]
...
每行信息表示一个服务,其中:
第一个数字是服务的ID。
第二个字段是服务名称。
第三个字段是服务所属的应用类名。
这样你就可以看到设备上有哪些系统服务。
过滤某些wifi相关的系统Service示例:
console:/ # service list | grep wifi
41 android.hardware.wifi.IWifi/default: [android.hardware.wifi.IWifi]
285 wifi: [android.net.wifi.IWifiManager]
286 wifinl80211: [android.net.wifi.nl80211.IWificond]
287 wifip2p: [android.net.wifi.p2p.IWifiP2pManager]
288 wifiscanner: [android.net.wifi.IWifiScanner]
console:/ #
这些系统服务为什么要添加到里面?是哪里定义的?如何添加到service里面的? 后面有具体介绍。
2、查询四大组件的服务 dumpsys activity services
只能查询到正在运行中的服务
过滤蓝牙opp 相关Service示例:
console:/ # dumpsys activity services | grep -i bluetooth
console:/ # //蓝牙相关服务太多了, 这里就不一一罗列了。
console:/ #dumpsys activity services | grep -i opp
* ServiceRecord{86cdea6 u0 com.android.bluetooth/.opp.BluetoothOppService}
intent={cmp=com.android.bluetooth/.opp.BluetoothOppService}
infoAllowStartForeground=[callingPackage: com.android.bluetooth; callingUid: 1002; uidState: PER ; uidBFSL: [BFSL];
intent: Intent { cmp=com.android.bluetooth/.opp.BluetoothOppService (has extras) }; code:PROC_STATE_PERSISTENT;
tempAllowListReason:<9403dcc android.bluetooth.adapter.action.STATE_CHANGED/u-1,reasonCode:BLUETOOTH_BROADCAST,duration:10000,callingUid:1000>;
targetSdkVersion:34; callerTargetSdkVersion:34; startForegroundCount:0; bindFromPackage:null: isBindService:false]
console:/ #
console:/ #
console:/ # dumpsys activity services | grep -i wifi //wifi相关的服务不是以wifi命名的,所以无法查找到
1|console:/ #
上面可以看到蓝牙传输相关的opp服务,只有蓝牙打开的情况才能查询到这个服务。
从上面的信息大致可以看到,这个服务的Java类的包名和具体服务类名。
还有个isBindService 信息,大部分的Service都是false,即使有的被绑定的Service也是有的显示false,还不清楚具体原因。
后续就可以通过包名+类型拉起这个服务或者停止这个服务。
3、杀死四大组件的服务 am stop-service 包名/.类名
系统服务是无法杀死的,她其实就是一种提供接口的形式。
而四大组件的服务如果是运行状态的,是可以杀死的。
console:/ #
console:/ # am stop-server aa
Unknown command: stop-server
255|console:/ # am stop-service aa //(1)随便啥一个服务名,发现是错误的,提示该服务未运行
Stopping service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=aa }
Service not stopped: was not running.
255|console:/ #
255|console:/ # //(2)杀死蓝牙opp服务,提示Service stopped 表示成功
am stop-service com.android.bluetooth/.opp.BluetoothOppService
Stopping service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.bluetooth/.opp.BluetoothOppService }
Service stopped
255|console:/ # dumpsys activity services | grep -i opp
1|console:/ # //(3)重新查询蓝牙opp服务,发现找不到了,说明已经停止了
4、启动四大组件的服务:am start-service 包名/.类名
console:/ # am start-service aa //(1)随便拉起啥一个服务名,提示该未发现该服务
Starting service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=aa }
Error: Not found; no service started.
255|console:/ # //(2)拉起蓝牙opp服务,提示Starting service:XXX 表示成功
1|console:/ #am start-service com.android.bluetooth/.opp.BluetoothOppService
Starting service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.bluetooth/.opp.BluetoothOppService }
console:/ # //(3)重新查询蓝牙opp服务,有找到了,说明已经启动服务了
console:/ # dumpsys activity services | grep -i opp
* ServiceRecord{730de10 u0 com.android.bluetooth/.opp.BluetoothOppService}
intent={act=android.intent.action.MAIN
cat=[android.intent.category.LAUNCHER] cmp=com.android.bluetooth/.opp.BluetoothOppService}...
console:/ #
不暴露的Service也是可以使用 am start-service 拉起吗?
比如,下面的服务定义示例;
<service android:name="com.debug.settings.service.ScheduleService"
android:exported="false"/>
测试了一下,是可以使用am start-service 命令拉起的。
估计是adb拥有系统权限,系统类或者系统应用可以拉起未暴露的Service。
也有些系统服务做了限制,无法正常拉起的。一般是判断权限或者intent数据。
三、其他
1、service list 相关问题
(1)系统服务如何添加到 service
其实 service list 的 这些服务是ServiceManager手动添加的
ServiceManager.addService(SERVICE_XXXNAME, mBinder);
其中 SystemServer.java 就有很多系统服务是添加到 ServiceManager 管理的。
要调用addService方法,必须是系统类或者系统应用才有权限。
addService 具体实现是在底层代码实现的。
(2)为啥要添加到
这种系统服务无法并不是真正的四大组件的服务,而是一个基于AIDL的接口类。
class XXXManager extends IXXXService.Stub
获取到对应的 mBinder 后,就可以调用IXXXService里面的接口实现。
所以SystemServer添加Service就是为了被其他类以binder的形式进行调用。
binder 的调用不仅仅局限于Java代码,还可以用在cpp代码,虽然我不清楚cpp代码是如何调用binder的。
(3)service list的实现
service list 返回的数据实现是在cpp代码:
/frameworks/native/cmds/service/service.cpp
binder其实是底层逻辑,这里不展开介绍。
有兴趣的可以看看:
https://blog.csdn.net/a572423926/article/details/126551079
(4)Service接口类添加到service代码
SystemServer中的大部分系统服务都是以 XXXManager extends IXXXService.Stub的形式定义后,添加对应的binder(XXXManager 对象)到service中。
(1)比如添加NetworkManagementService 添加到ServiceManager部分示例代码:
frameworks/base/services/java/com/android/server/SystemServer.java
t.traceBegin("StartNetworkManagementService");
try {
networkManagement = NetworkManagementService.create(context);
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
} catch (Throwable e) {
reportWtf("starting NetworkManagement Service", e);
}
t.traceEnd();
NetworkManagementService 的部分代码:
public class NetworkManagementService extends INetworkManagementService.Stub {
//静态方法,返回的是对象本身,是一个binder对象
static NetworkManagementService create(Context context, Dependencies deps)
throws InterruptedException {
final NetworkManagementService service =
new NetworkManagementService(context, deps);
if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
if (DBG) Slog.d(TAG, "Connecting native netd service");
service.connectNativeNetdService();
if (DBG) Slog.d(TAG, "Connected");
return service;
}
}
但是也一些系统服务是非常规方式添加binder的:
(2)另外一种形式添加系统服务到ServiceManager
class TestManager {
IMainService.Stub mBinder = new IMainService.Stub() {
@Override
public IBinder queryBinder(String binderType) throws RemoteException {
IBinder binder = XXX...;
return binder;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Log.d(TAG, "vivid-> onStartCommand..addService");
ServiceManager.addService(MYDEBUG_SERVICE, mBinder);//添加该接口服务到service
} catch (SecurityException e) {
e.printStackTrace();
}
return START_STICKY;
}
}
一些自定义的系统服务类就是这样条件到ServiceManager的
2、Java代码中拉起Service和停止Service
// (1)创建一个Intent对象,指定要停止的Service
Intent intent = new Intent(context, YourService.class);
// 停止Service
context.stopService(intent);
// (2)创建一个Intent对象,指定要启动的Service
Intent intent = new Intent(context, YourService.class);
// 启动Service
context.startService(intent);
//(3)bindService 拉起Service
Context.bindService(Intent, ServiceConnection, int)
上面的代码普通应用就可以使用。
遍历系统中的Service,查找某个Service 的应用进行停止
ActivityManager manager = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if ("com.yourpackage.MyService".equals(service.service.getClassName())) {
manager.killBackgroundProcesses(service.service.getPackageName());
break;
}
}
停止需要权限:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
这个权限只有系统应用才能申请到。
3、四大组件service启动和停止 adb 命令的源码
源码位置:
framework/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
am 主要命令相关代码:
@Override
public int onCommand(String cmd) {
if (cmd == null) {
return handleDefaultCommands(cmd);
}
final PrintWriter pw = getOutPrintWriter();
try {
switch (cmd) {
case "start":
case "start-activity":
return runStartActivity(pw);
case "startservice":
case "start-service":
return runStartService(pw, false);
case "startforegroundservice":
case "startfgservice":
case "start-foreground-service":
case "start-fg-service":
return runStartService(pw, true);
case "stopservice":
case "stop-service":
return runStopService(pw);
case "broadcast":
return runSendBroadcast(pw);
。。。
final IActivityManager mInterface;
//开启服务实现
int runStartService(PrintWriter pw, boolean asForeground) throws RemoteException {
final PrintWriter err = getErrPrintWriter();
Intent intent;
try {
intent = makeIntent(UserHandle.USER_CURRENT);
} catch (URISyntaxException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (mUserId == UserHandle.USER_ALL) {
err.println("Error: Can't start activity with user 'all'");
return -1;
}
pw.println("Starting service: " + intent);
pw.flush();
//** startService **实现和返回情况
ComponentName cn = mInterface.startService(null, intent, intent.getType(),
asForeground, SHELL_PACKAGE_NAME, null, mUserId);
if (cn == null) {
err.println("Error: Not found; no service started.");
return -1;
} else if (cn.getPackageName().equals("!")) {
err.println("Error: Requires permission " + cn.getClassName());
return -1;
} else if (cn.getPackageName().equals("!!")) {
err.println("Error: " + cn.getClassName());
return -1;
} else if (cn.getPackageName().equals("?")) {
err.println("Error: " + cn.getClassName());
return -1;
}
return 0;
}
通过上面的代码可以看到:
启动服务使用 startservice 和 start-service 都是可以的;
停止服务使用 stopservice 和 stop-service 都是可以的;
所以在不同文章看到这两种方式的命令启动或者停止服务不要大惊小怪。
从上面 onCommand 方法可以看到,服务启动,Activity启动,广播发送都是有adb命令控制的;
adb 命令的 am XXX 最终实现也是通过IActivityManager 接口类调用到具体实现的,和Java代码调拉起服务或者Activity后续实现是一样的。