android中dumpsys函数介绍与使用

本文深入解析了dumpsys命令的使用方法及原理,展示了如何通过该命令获取Android系统中运行的服务信息。文章通过具体示例介绍了不同服务的dump输出,并探讨了服务注册与dump权限等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dumpsys是系统中重要的函数,我们来看看它如何使用,都能dump出来一些什么东西


首先我们来看看dumpsys的源码,在4.1中,它在framework/native目录下面

frameworks/native/cmds/dumpsys/dumpsys.cpp

if (argc == 1) {
	services = sm->listServices();
	services.sort(sort_func);
	args.add(String16("-a"));
} else {
	services.add(String16(argv[1]));
	for (int i=2; i<argc; i++) {
		args.add(String16(argv[i]));
	}
}

const size_t N = services.size();

if (N > 1) {
	// first print a list of the current services
	aout << "Currently running services:" << endl;

	for (size_t i=0; i<N; i++) {
		sp<IBinder> service = sm->checkService(services[i]);
		if (service != NULL) {
			aout << "  " << services[i] << endl;
		}
	}
}

for (size_t i=0; i<N; i++) {
	sp<IBinder> service = sm->checkService(services[i]);
	if (service != NULL) {
		if (N > 1) {//dump多个Service时,Service信息之间的分隔
			aout << "------------------------------------------------------------"
					"-------------------" << endl;
			aout << "DUMP OF SERVICE " << services[i] << ":" << endl;
		}
		int err = service->dump(STDOUT_FILENO, args);
		if (err != 0) {
			aerr << "Error dumping service info: (" << strerror(err)
					<< ") " << services[i] << endl;
		}
	} else {
		aerr << "Can't find service: " << services[i] << endl;
	}
}

我只会java,上面的代码还是留给大家自己阅读吧,我就不详细解释了……

如果参数个数=1,则在ServiceManager中查找注册的Service

否则查找指定的Service,并且将剩余参数传给Serivce



如果执行dumpsys命令,那么将会dump所有Service,每个Service之间会分隔开

如果dumpsys一个没有注册的Service,那么则提示找不到Service,比如:

# dumpsys adb                                                   

Can't find service: adb




那么我们到底都可以dump一些什么呢?

其实最简单的办法就是执行dumpsys,看看其结果,下面是我手机中执行的结果(HTCg14)

# dumpsys
Currently running services:
  DeviceManager3LM
  Encryption3LMService
  HtcAppUsageStatsService
  SurfaceFlinger
  accessibility
  account
  activity
  alarm
  appwidget
  audio
  backup
  battery
  batteryinfo
  bluetooth
  bluetooth_a2dp
  bluetooth_hid
  bt_fm_management
  clipboard
  connectivity
  content
  country_detector
  cpuinfo
  device_policy
  devicestoragemonitor
  diskstats
  display
  drm.drmManager
  dropbox
  entropy
  gfxinfo
  hardware
  htc_checkin
  htchardware
  htctelephony
  htctelephonyinternal
  input_method
  iphonesubinfo
  isms
  location
  media.audio_flinger
  media.audio_policy
  media.camera
  media.player
  meminfo
  mount
  netpolicy
  netstats
  network_management
  notification
  package
  permission
  phone
  power
  samplingprofiler
  search
  secfirewall
  secloader
  sensorservice
  simphonebook
  sip
  statusbar
  stub_activity
  stub_audio
  stub_iphonesubinfo
  stub_isms
  stub_location
  stub_phone
  stub_telephony.registry
  telephony.registry
  textservices
  throttle
  uimode
  usagestats
  usb
  usbnet
  userbehavior
  vibrator
  wallpaper
  wifi
  wifip2p
  window
-------------------------------------------------------------------------------
DUMP OF SERVICE DeviceManager3LM:
-------------------------------------------------------------------------------
DUMP OF SERVICE Encryption3LMService:

由于dump service的log实在太长,我就截取了最前面的“Currently running services”和两个Service的dump信息

为什么DeviceManager3LM和Encryption3LMService后面没有内容?这和Service的内部实现有关,也许它只是写了一个空的dump函数,也许有什么其他条件。

这个问题一会再说,我们先看看这些Service都是在哪注册的

其中大部分Service都是在SystemServer中的main函数里注册的,它调用了一个叫init2的函数

public static final void init2() {
    Slog.i(TAG, "Entered the Android system server!");
    Thread thr = new ServerThread();
    thr.setName("android.server.ServerThread");
    thr.start();
}

init2非常简单,所有任务都交给新线程ServerThread来处理


在ServerThread的run函数中,注册了系统大部分的Service,有兴趣的同学可以看看这部分代码

这部分代码有点长(大概800行),因为它一直重复这建立各种Service,然后注册,输出log

比如下面的WifiP2pService

try {
    Slog.i(TAG, "Wi-Fi P2pService");
    wifiP2p = new WifiP2pService(context);
    ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p);
} catch (Throwable e) {
    reportWtf("starting Wi-Fi P2pService", e);
}

其中WIFI_P2P_SERVICE就是服务的名字

public static final String WIFI_P2P_SERVICE = "wifip2p";



当执行dumpsys wifip2p的时候,并没有任何输出,为什么呢?我们看看WifiP2pService的代码

@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
            != PackageManager.PERMISSION_GRANTED) {
        pw.println("Permission Denial: can't dump WifiP2pService from from pid="
                + Binder.getCallingPid()
                + ", uid=" + Binder.getCallingUid());
        return;
    }
}

现在似乎可以理解为什么dumpsys wifip2p的时候没有输出了



我们再来看一个简单的例子

# dumpsys diskstats

Latency: 5ms [512B Data Write]

Data-Free: 362888K / 1161104K total = 31% free

Cache-Free: 116756K / 120900K total = 96% free

System-Free: 133036K / 806284K total = 16% free

ServiceManager.addService("diskstats", new DiskStatsService(context));
这回大家知道去哪看源码了吧,下面是DiskStatsService的dump函数
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    ……
    reportFreeSpace(Environment.getDataDirectory(), "Data", pw);
    reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
    reportFreeSpace(new File("/system"), "System", pw);
}
 
private void reportFreeSpace(File path, String name, PrintWriter pw) {
    try {
        StatFs statfs = new StatFs(path.getPath());
        long bsize = statfs.getBlockSize();
        long avail = statfs.getAvailableBlocks();
        long total = statfs.getBlockCount();
        if (bsize <= 0 || total <= 0) {
            throw new IllegalArgumentException(
                    "Invalid stat: bsize=" + bsize + " avail=" + avail + " total=" + total);
        }

        pw.print(name);
        pw.print("-Free: ");
        pw.print(avail * bsize / 1024);
        pw.print("K / ");
        pw.print(total * bsize / 1024);
        pw.print("K total = ");
        pw.print(avail * 100 / total);
        pw.println("% free");
    } catch (IllegalArgumentException e) {
        pw.print(name);
        pw.print("-Error: ");
        pw.println(e.toString());
        return;
    }
}
大家肯定还对其他的Service感兴趣,比如 notification!
之前我的一篇关于android安全的文章提到过用dumpsys  notification能作些什么







转贴请保留以下链接

本人blog地址

http://su1216.iteye.com/

http://blog.youkuaiyun.com/su1216/


<think>嗯,用户这次问的是Android15中IEvsEnumeratorStatusCallback.aidl的deviceStatusChanged函数,需要结合之前讨论过的EVS框架内容来回答。先回顾一下上下文:之前详细解释过IEvsEnumerator的几个新增函数,特别是registerStatusCallback这个注册监听的接口。现在用户问的正是回调接口中的核心函数deviceStatusChanged。用户可能正在开发基于EVS的驾驶辅助应用,特别关注硬件状态实时通知机制。从ta连续追问系统级接口的行为看,应该是系统层开发者或车机系统集成商。deviceStatusChanged函数本质上是个多用途的状态广播通道。需要重点说明三点:一是支持多设备类型的状态聚合(摄像头/显示器/超声波),二是硬件异常时的故障转移触发机制,三是实际使用时的性能陷阱。特别注意要强调权限管理:涉及摄像头状态监听需要CAMERA权限,而显示状态需要EVS专属权限。用户如果忽视这点,调试时会遇到权限拒绝的坑。之前引用过的CameraDeviceClient代码(引用[1])可以关联说明——就像cameraservice的flush操作需要状态同步那样,EVS的状态回调同样依赖跨进程通信的稳定性。那个binder状态图的序列可以优化下:客户端注销回调后服务端应该有资源回收动作。另外可以补充一个实际案例,比如当检测到摄像头硬件故障(状态变UNSUPPORTED)时自动切换到备用的环视摄像头。最后生成的问题要偏向实际开发场景:配置变更处理、跨进程资源释放、真实故障转移案例等。用户明显更关注工业实践而非理论说明。</think> 在 Android 15 的 EVS 框架中,`IEvsEnumeratorStatusCallback.aidl` 中的 **`deviceStatusChanged`** 函数是硬件状态实时监听的核心回调接口,其功能设计如下: --- ### **`deviceStatusChanged(String deviceId, int newState)`** #### ▶ **核心功能** 通过注册的状态回调接口 **被动接收** 指定设备的运行时状态变更事件,实现硬件状态动态感知[^1]。 #### ▶ **参数详解** ```java void deviceStatusChanged( in String deviceId, // 目标设备ID (e.g. "camera/ultrasonic_array/display") in int newState // 设备最新状态码 ); ``` - **`deviceId`** - **类型**:字符串 - **格式**:遵循 EVS 设备命名规范 ``` <设备类型>_<硬件类型>_<索引号> // 示例:"camera_front_0", "display_primary", "ultrasonic_array_0" ``` - **设备类型分类**: | 前缀 | 设备类型 | 示例 ID | |---------------|---------------|----------------------| | `camera_` | 摄像头 | `camera_rear_1` | | `display_` | 显示屏 | `display_secondary` | | `ultrasonic_` | 超声波传感器 | `ultrasonic_array_2` | - **`newState`** - **类型**:整型(状态枚举值) - **关键状态码**: ```java // Camera 状态(部分示例) STATUS_AVAILABLE = 0; // 设备可用 STATUS_IN_USE = 1; // 被占用(例如被其他进程) STATUS_UNAVAILABLE = 2; // 设备异常(如断开连接) STATUS_UNSUPPORTED = 3; // 硬件不支持请求的操作 // Display 状态(部分示例) STATE_VISIBLE = 10; // 显示中 STATE_NOT_VISIBLE = 11; // 隐藏或休眠 ``` #### ▶ **典型使用场景** 1. **摄像头故障转移** 当检测到主摄像头状态变为 `STATUS_UNAVAILABLE` 时,自动切换至备用摄像头: ```java void deviceStatusChanged(String deviceId, int newState) { if (deviceId.equals("camera_main") && newState == STATUS_UNAVAILABLE) { // 自动切换到备用摄像头 mEvsSession = mEnumerator.openCamera("camera_backup"); } } ``` 2. **超声波传感器异常告警** 检测超声波阵列失效并触发安全机制: ```java void deviceStatusChanged(String deviceId, int newState) { if (deviceId.startsWith("ultrasonic_") && newState == STATUS_UNSUPPORTED) { mVehicleController.triggerEmergencyStop(); // 触发车辆紧急制动 } } ``` 3. **显示状态同步** 实时跟踪显示屏休眠状态以优化渲染逻辑: ```java void deviceStatusChanged(String deviceId, int newState) { if (deviceId.equals("display_dashboard") && newState == STATE_NOT_VISIBLE) { mRenderer.stopRendering(); // 停止UI渲染节省资源 } } ``` --- #### ▶ **完整使用流程** 1. **注册回调** 通过 `IEvsEnumerator.registerStatusCallback()` 绑定监听: ```java // 实现回调接口 IEvsEnumeratorStatusCallback mCallback = new IEvsEnumeratorStatusCallback.Stub() { @Override void deviceStatusChanged(String deviceId, int newState) { // 处理状态变更 } }; // 注册到 EVS 服务 mEnumerator.registerStatusCallback(mCallback); ``` 2. **资源释放** 使用完毕后注销回调避免内存泄漏: ```java mEnumerator.unregisterStatusCallback(mCallback); ``` --- #### ▶ **权限要求** - **摄像头状态监听**:需声明 `android.permission.CAMERA` - **超声波状态监听**:需声明 `android.hardware.evs.permission.ACCESS_ULTRASONICS` - **显示状态监听**:需声明 `android.hardware.evs.permission.CONTROL_DISPLAY` --- ### **底层实现逻辑** 状态变更事件通过 EVS 服务端的 **硬件抽象层 (HAL)** 触发: 1. HAL 层检测物理设备状态变化(如 USB 摄像头断开) 2. 通过 `binder` 跨进程通知 `EvsEnumeratorService` 3. 服务端遍历已注册的客户端回调队列 4. 调用 `deviceStatusChanged()` 推送事件至客户端 ```mermaid sequenceDiagram participant HAL as 硬件抽象层 participant Service as EvsEnumeratorService participant Client as 客户端应用 HAL->>Service: 物理设备状态变更 Service->>Service: 遍历注册的客户端 Service->>Client: deviceStatusChanged(deviceId, newState) Client->>Client: 执行故障转移/告警 ``` --- ### **调试技巧** 1. **强制触发状态变更** 使用 `adb shell` 模拟设备断开: ```bash adb shell dumpsys evs suspend camera_rear_0 # 强制挂起摄像头 adb shell dumpsys evs resume camera_rear_0 # 恢复设备 ``` 2. **跟踪回调事件** 通过 `Perfetto` 抓取事件时序流: ```bash adb shell perfetto -o /data/misc/perfetto/trace_file.pftrace -t 10s \ --config :android.evs,android.binder ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值