Android进阶-Command Line Tools-2

四、dumpsys

dumpsys是一款在Android设备上运行并提供有关系统服务信息的工具。您可以从adb命令行调用dumpsys以获取连接设备上运行的所有系统服务的诊断输出。此输出通常比您想要的更冗长,因此请使用下面介绍的命令行选项来获取仅用于您感兴趣的系统服务的输出。本页还介绍了如何使用dumpsys来完成常见任务,例如检查输入, RAM,电池或网络诊断

常用的dumpsys的使用语法如下:

 adb shell dumpsys [-t timeout] [--help | -l | --skip services | service [arguments] | -c | -h]

得到你的连接设备上所有系统服务的诊断输出,简单的运行adb shell dumpsys.然而这个输出信息比你想要的多得多,为了管理输出,你可以在命令中添加指定的服务,例如下面的命令,提供输出组件的系统数据,例如:触摸屏幕或者内置键盘。

adb shell dumpsys input

你可以使用dumpsys得到完整的系统服务,使用如下命令:

adb shell dumpsys -l


Command line options

当使用dumpsys下面的表列表命令选项是可以获得的:

Option Description
-t timeout 以 秒为单位,指定超时周期,如果未指定,默认是10s
--help 打印 dumpsys 工具的帮助文本.
-l dumpsys一起使用列出完整的系统服务.
--skip services 指定你不想包含的 services输出.
service [arguments] 指定你想要的 service输出. 一些服务大概有 arguments选项. 你可以学习关于这个选项arguments通过使用service的 -h选项 , 演示如下:
adb shell dumpsys procstats -h 
-c当指定某些服务,增加这个选项以机器友好的格式输出数据
-h
对于某些服务看以帮助文本和额外的选项信息 检测input诊断 指定input服务,如下所示,dumps 系统输入设备的状态,如触摸屏幕,内置键盘,输入事件的处理
adb shell dumpsys input

这个输出的变化依赖连接设备的Android版本,下面的部分描述了您通常看到的信息类型。

Event hub state

下面的示例是你可能在检测Event hub state可能看到的输入信息

INPUT MANAGER (dumpsys input)

Event Hub State:
  BuiltInKeyboardId: -2
  Devices:
    -1: Virtual
      Classes: 0x40000023
      Path: 
      Descriptor: a718a782d34bc767f4689c232d64d527998ea7fd
      Location:
      ControllerNumber: 0
      UniqueId: 
      Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000
      KeyLayoutFile: /system/usr/keylayout/Generic.kl
      KeyCharacterMapFile: /system/usr/keychars/Virtual.kcm
      ConfigurationFile:
      HaveKeyboardLayoutOverlay: false
    1: msm8974-taiko-mtp-snd-card Headset Jack
      Classes: 0x00000080
      Path: /dev/input/event5
      Descriptor: c8e3782483b4837ead6602e20483c46ff801112c
      Location: ALSA
      ControllerNumber: 0
      UniqueId:
      Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000
      KeyLayoutFile:
      KeyCharacterMapFile:
      ConfigurationFile:
      HaveKeyboardLayoutOverlay: false
    2: msm8974-taiko-mtp-snd-card Button Jack
      Classes: 0x00000001
      Path: /dev/input/event4
      Descriptor: 96fe62b244c555351ec576b282232e787fb42bab
      Location: ALSA
      ControllerNumber: 0
      UniqueId:
      Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000
      KeyLayoutFile: /system/usr/keylayout/msm8974-taiko-mtp-snd-card_Button_Jack.kl
      KeyCharacterMapFile: /system/usr/keychars/msm8974-taiko-mtp-snd-card_Button_Jack.kcm
      ConfigurationFile:
      HaveKeyboardLayoutOverlay: false
    3: hs_detect
      Classes: 0x00000081
      Path: /dev/input/event3
      Descriptor: 485d69228e24f5e46da1598745890b214130dbc4
      Location:
      ControllerNumber: 0
      UniqueId:
      Identifier: bus=0x0000, vendor=0x0001, product=0x0001, version=0x0001
      KeyLayoutFile: /system/usr/keylayout/hs_detect.kl
      KeyCharacterMapFile: /system/usr/keychars/hs_detect.kcm
      ConfigurationFile:
      HaveKeyboardLayoutOverlay: false
...

Input reader state
InputReader负责从内核解码输入事件。它的状态转储显示了关于每个输入设备的配置信息,以及最近发生的状态变化,比如按键或触摸屏幕上的触摸。

下面的示例展示了触摸屏的输出。请注意该设备的分辨率和所使用的校准参数的信息

Input Reader State
...
  Device 6: Melfas MMSxxx Touchscreen
      IsExternal: false
      Sources: 0x00001002
      KeyboardType: 0
      Motion Ranges:
        X: source=0x00001002, min=0.000, max=719.001, flat=0.000, fuzz=0.999
        Y: source=0x00001002, min=0.000, max=1279.001, flat=0.000, fuzz=0.999
        PRESSURE: source=0x00001002, min=0.000, max=1.000, flat=0.000, fuzz=0.000
        SIZE: source=0x00001002, min=0.000, max=1.000, flat=0.000, fuzz=0.000
        TOUCH_MAJOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000
        TOUCH_MINOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000
        TOOL_MAJOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000
        TOOL_MINOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000
      Touch Input Mapper:
        Parameters:
          GestureMode: spots
          DeviceType: touchScreen
          AssociatedDisplay: id=0, isExternal=false
          OrientationAware: true
        Raw Touch Axes:
          X: min=0, max=720, flat=0, fuzz=0, resolution=0
          Y: min=0, max=1280, flat=0, fuzz=0, resolution=0
          Pressure: min=0, max=255, flat=0, fuzz=0, resolution=0
          TouchMajor: min=0, max=30, flat=0, fuzz=0, resolution=0
          TouchMinor: unknown range
          ToolMajor: unknown range
          ToolMinor: unknown range
          Orientation: unknown range
          Distance: unknown range
          TiltX: unknown range
          TiltY: unknown range
          TrackingId: min=0, max=65535, flat=0, fuzz=0, resolution=0
          Slot: min=0, max=9, flat=0, fuzz=0, resolution=0
        Calibration:
          touch.size.calibration: diameter
          touch.size.scale: 10.000
          touch.size.bias: 0.000
          touch.size.isSummed: false
          touch.pressure.calibration: amplitude
          touch.pressure.scale: 0.005
          touch.orientation.calibration: none
          touch.distance.calibration: none
        SurfaceWidth: 720px
        SurfaceHeight: 1280px
        SurfaceOrientation: 0
        Translation and Scaling Factors:
          XScale: 0.999
          YScale: 0.999
          XPrecision: 1.001
          YPrecision: 1.001
          GeometricScale: 0.999
          PressureScale: 0.005
          SizeScale: 0.033
          OrientationCenter: 0.000
          OrientationScale: 0.000
          DistanceScale: 0.000
          HaveTilt: false
          TiltXCenter: 0.000
          TiltXScale: 0.000
          TiltYCenter: 0.000
          TiltYScale: 0.000
        Last Button S     
ate: 0x00000000
        Last Raw Touch: pointerCount=0
        Last Cooked Touch: pointerCount=0

在输入读取器状态转储的末尾,有一些关于全局配置参数的信息,比如tap interval

Configuration:
  ExcludedDeviceNames: []
  VirtualKeyQuietTime: 0.0ms
  PointerVelocityControlParameters: scale=1.000, lowThreshold=500.000, highThreshold=3000.000, acceleration=3.000
  WheelVelocityControlParameters: scale=1.000, lowThreshold=15.000, highThreshold=50.000, acceleration=4.000
  PointerGesture:
    Enabled: true
    QuietInterval: 100.0ms
    DragMinSwitchSpeed: 50.0px/s
    TapInterval: 150.0ms
    TapDragInterval: 300.0ms
    TapSlop: 20.0px
    MultitouchSettleInterval: 100.0ms
    MultitouchMinDistance: 15.0px
    SwipeTransitionAngleCosine: 0.3
    SwipeMaxWidthRatio: 0.2
    MovementSpeedRatio: 0.8
    ZoomSpeedRatio: 0.3

Input dispatcher state
InputDispatcher 的责任是负责发送input事件到应用程序,如下输出所示,
它的状态转储显示了被触碰的窗口的信息、输入队列的状态、ANR是否正在进行中,等等。

Input Dispatcher State:
  DispatchEnabled: 1
  DispatchFrozen: 0
  FocusedApplication: <null>
  FocusedWindow: name='Window{3fb06dc3 u0 StatusBar}'
  TouchStates: <no displays touched>
  Windows:
    0: name='Window{357bbbfe u0 SearchPanel}', displayId=0, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x01820100, type=0x000007e8, layer=211000, frame=[0,0][1080,1920], scale=1.000000, touchableRegion=[0,0][1080,1920], inputFeatures=0x00000000, ownerPid=22674, ownerUid=10020, dispatchingTimeout=5000.000ms
    1: name='Window{3b14c0ca u0 NavigationBar}', displayId=0, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x01840068, type=0x000007e3, layer=201000, frame=[0,1776][1080,1920], scale=1.000000, touchableRegion=[0,1776][1080,1920], inputFeatures=0x00000000, ownerPid=22674, ownerUid=10020, dispatchingTimeout=5000.000ms
    2: name='Window{2c7e849c u0 com.vito.lux}', displayId=0, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x0089031a, type=0x000007d6, layer=191000, frame=[-495,-147][1575,1923], scale=1.000000, touchableRegion=[-495,-147][1575,1923], inputFeatures=0x00000000, ownerPid=4697, ownerUid=10084, dispatchingTimeout=5000.000ms
    ...
  MonitoringChannels:
    0: 'WindowManager (server)'
  RecentQueue: length=10
    MotionEvent(deviceId=4, source=0x00001002, action=2, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, displayId=0, pointers=[0: (335.0, 1465.0)]), policyFlags=0x62000000, age=217264.0ms
    MotionEvent(deviceId=4, source=0x00001002, action=1, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, displayId=0, pointers=[0: (335.0, 1465.0)]), policyFlags=0x62000000, age=217255.7ms
    MotionEvent(deviceId=4, source=0x00001002, action=0, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, displayId=0, pointers=[0: (330.0, 1283.0)]), policyFlags=0x62000000, age=216805.0ms
    ...
  PendingEvent: <none>
  InboundQueue: <empty>
  ReplacedKeys: <empty>
  Connections:
    0: channelName='WindowManager (server)', windowName='monitor', status=NORMAL, monitor=true, inputPublisherBlocked=false
      OutboundQueue: <empty>
      WaitQueue: <empty>
    1: channelName='278c1d65 KeyguardScrim (server)', windowName='Window{278c1d65 u0 KeyguardScrim}', status=NORMAL, monitor=false, inputPublisherBlocked=false
      OutboundQueue: <empty>
      WaitQueue: <empty>
    2: channelName='357bbbfe SearchPanel (server)', windowName='Window{357bbbfe u0 SearchPanel}', status=NORMAL, monitor=false, inputPublisherBlocked=false
      OutboundQueue: <empty>
      WaitQueue: <empty>
    ...
  AppSwitch: not pending
    7: channelName='2280455f com.google.android.gm/com.google.android.gm.ConversationListActivityGmail (server)', windowName='Window{2280455f u0 com.google.android.gm/com.google.android.gm.ConversationListActivityGmail}', status=NORMAL, monitor=false, inputPublisherBlocked=false
      OutboundQueue: <empty>
      WaitQueue: <empty>
    8: channelName='1a7be08a com.android.systemui/com.android.systemui.recents.RecentsActivity (server)', windowName='Window{1a7be08a u0 com.android.systemui/com.android.systemui.recents.RecentsActivity EXITING}', status=NORMAL, monitor=false, inputPublisherBlocked=false
      OutboundQueue: <empty>
      WaitQueue: <empty>
    9: channelName='3b14c0ca NavigationBar (server)', windowName='Window{3b14c0ca u0 NavigationBar}', status=NORMAL, monitor=false, inputPublisherBlocked=false
      OutboundQueue: <empty>
      WaitQueue: <empty>
    ...
  Configuration:
    KeyRepeatDelay: 50.0ms
    KeyRepeatTimeout: 500.0ms

下面是检查输入服务的各种输出时要考虑的事项列表:

Event hub state:

  • 所有你期待的input设备都存在
  • 每个输入设备都有一个适当的键布局文件、键字符映射文件和输入设备配置文件。如果文件丢失或包含语法错误,那么它们将不会被加载
  • 每个输入设备都被正确分类。Classes 字段与EventHub.h中的flag一致,
    比如INPUT_DEVICE_CLASS_TOUCH_MT
  • BuiltInKeyboardId 要正确,如果这个设备没有内置键盘,这个id值一定要是-2,否则,它应该是内置键盘的id
  • 如果您观察到,BuiltInKeyboardId不是-2,但它应该是,那么您将丢失一个关键字符映射文件,用于特定的函数键盘。特殊功能键盘设备应该有key字符映射文件,其中只包含行类型SPECIAL_FUNCTION (这就是我们在上面提到的文件tuna-gpio-keykad.kcm中的内容。

Input reader state:

  • 所有你期待的设备都存在
  • 每一个Input设备配置正确,尤其,检查触摸屏幕和joystick坐标轴是否正确。

Input dispatcher state:

  • 所有你期待的设备都存在
  • 在触碰触摸屏并同时运行dumpsys之后,TouchStates 行正确地标识了您所接触到的窗口

五、apksigner

apksigner 工具是sdk build工具24.0.3才有的,或者更高版本,允许你签名apk和在所有的Android平台版本认证成功。这个页面显示了这个工具的简短指南,和不同命令行的选项支持参考。看更加完整的使用apksigner工具签名apk,请看 Sign your app

警告: 如果您使用`apksigner`签署APK并对APK进行进一步更改,APK的签名将无效。因此,在签署APK之前,您必须使用`zipalign`等工具。.

Usage


Sign an APK
使用apksigner签名apk的语法如下:

apksigner sign --ks keystore.jks |
  --key key.pk8 --cert cert.x509.pem
  [signer_options] app-name.apk

当你使用apksigner工具签名时,你必须提供私钥和证书。你可以通过两种不同的方法包含这些:

  • 指定KeyStore文件,使用 --ks 选项
  • 指定私钥文件和证书,分别使用--key and --cert 选项。私钥文件必须使用PKCS #8格式,认证文件必须使用X.509格式

通常,您只使用一个签署者签署APK。如果您需要使用多个签署者签署APK,那么使用 --next-signer选项将一般选项集分离出来,以应用于每个签名者:

apksigner sign [signer_1_options] --next-signer [signer_2_options] app-name.apk

验证APK的签名
确认APK的签名将在受支持的平台上成功验证的语法如下:

apksigner verify [options] app-name.apk

Options


下面的列表包括apk签署工具支持的每个命令的选项集

Sign command

General options
下面的选项指定基本的设置应用于签名:

--out <apk-filename>
你想保存签名文件的位置。如果没有明确指定,apk在当前命令行所在目录签名。

–min-sdk-version <integer>
apksigner使用的最低的Android框架API级别来确认APK的签名将被验证。更高的值允许该工具在签署应用时使用更强的安全参数,但将APK的可用性限制在运行最新版本Android的设备上。默认情况下,apksigner 从应用的清单文件中使用minSdkVersion属性的值。

–max-sdk-version <integer>
apksigner使用的最高的Android框架API级别来确认APK的签名将被验证。默认的,这个工具尽可能使用最好的API等级。

–v1-signing-enabled <true | false>
决定apksigner 是否使用传统的基于jar的签名方案来签署给定的APK包。默认情况下,该工具使用–max-sdk-version –min-sdk-version的值来决定何时应用这个签名方案。

–v2-signing-enabled <true | false>
决定 apksigner 是否使用 APK Signature Scheme v2 来签署给定的apk包。默认情况下,该工具使用–max-sdk-version –min-sdk-version的值来决定何时应用这个签名方案。

-v, --verbose
使用详细的输出模式

Per-signer options

下面的选项指定特殊签名者的配置,这不是必须的,如果你签名你的apk仅仅使用一个签署者

–next-signer <signer-options>
为每一个签署者指定不同的常用选项

–v1-signer-name <basename>
为当前签名者提供JAR-based签名的文件的基本名称。默认情况下,apksigner使用KeyStore 的密钥别名或该签名者的密钥文件的basename。

秘钥和认证选项

下面的选项指定签名者的私钥和认证:
–ks <filename>
签名者的私钥和证书链属于给定的Java-based 的KeyStore文件中。如果filename被设置为“NONE”,包含钥匙和证书的密钥库不需要指定的文件,这是PKCS #11密钥存储库的情况。

–ks-key-alias <alias>
在KeyStore中代表签名者的私钥和证书数据的别名。如果与签名者关联的密钥存储库包含多个密钥,则必须指定该选项。

–ks-pass <input-format>
KeyStore 的密码包含私钥和认证,你必须提供一个密码打开KeyStore 。apksigner 支持以下格式:

  • pass:<password>:与apksigner sign命令的其余部分一起提供的密码
  • env:<name>:密码存储在给定的环境变量中
  • file:<filename> :密码在给定文件中为单行存储
  • stdin :密码在标准的输出流作为一个单行,这是-ks-pass. 默认的行为

注意:如果您在同一个文件中包含多个密码,请在单独的行中指定它们。apksigner 工具根据您指定签署者的顺序将密码与APK的签署者联系起来。如果您为一个签名者提供了两个密码,那么apksigner 将第一个密码解释为KeyStore 密码,第二个密码作为密钥密码。

–ks-type <algorithm>
Type或者algorithm 与KeyStore的私钥和证书相关联。默认情况下,apksigner 使用在安全属性文件中keystore.type 常量作为type.

–ks-provider-name <name>
在请求签署者的KeyStore实现时使用JCA提供的名称。默认情况下,apksigner 使用的是最高优先级的提供者。

–ks-provider-class <class-name>
在请求签署者的KeyStore实现时使用JCA提供者的完整类名。这个选项作为--ks-provider-name 的另一种选择,默认情况下,apksigner 使用由--ks-provider-name选项指定的提供者。

–ks-provider-arg <value>
字符串value作为JCA 提供的类的构造的参数。类本身定义在--ks-provider-class 选项。默认的,使用类的空参数构造

–key <filename>
包含签名者的私钥的文件名称。这个文件必须是PKCS #8 DER格式,如果这个key是password-protected,apksigner 使用标准的输入提示密码,除非你使用--key-pass 选项指定不同的输入格式

–cert <filename>
包含签名者的认证链的文件名。这个文件必须是 X.509 PEM or DER格式。

Verify command

–print-certs
显示apk签名证书的信息

–min-sdk-version <integer>
apksigner 使用的最低的Android框架API级别,以确认APK的签名将被验证。当签名app时更高的值允许这个工具使用更强的安全等级参数,但是限制app运行在更多的设备上。默认的,apksigner 使用apk清单文件minSdkVersion 属性的值。

–max-sdk-version <integer>
apksigner使用的最高的Android框架API级别来确认APK的签名将被验证。默认情况下,该工具使用最高的API级别。

-v, --verbose
使用详细的输出模式

-Werr
将警告视为错误。

Examples


Sign an APK

仅仅使用release.jks签名apk:

apksigner sign --ks release.jks app.apk

签名一个apk使用私钥和证书,保存在单独的文件:

apksigner sign --key release.pk8 --cert release.x509.pem app.apk

签名一个apk使用两个keystore:

apksigner sign --ks first-release-key.jks --next-signer --ks second-release-key.jks app.apk

验证一个apk的签名

检查APK的签名是否会在APK支持的所有Android平台上被确认为有效:

apksigner verify app.apk

检查APK的签名是否在Android 4.0.3(API级15)和更高版本中被确认为有效:

apksigner verify --min-sdk-version 15 app.apk

六、zipalign

zipalign是一个对其工具,为Android apk文件提供了重要的优化。这样做的目的是为了确保所有未压缩的数据都以特定的对齐方式开始,相对于文件的开始。具体地说,它会导致APK中的所有未压缩数据,比如图像或原始文件,在4字节边界上对齐。这允许直接使用mmap()访问所有部分,即使它们包含有对齐限制的二进制数据。这样做的好处是减少了运行应用程序时消耗的RAM数量

这个工具应用总是在你的apk分发到用户手中时被使用。Android编译工具为你处理它,AndroidStudio自动使用zipalign帮你对齐。

您必须在应用程序构建过程的两个特定点之一使用zipalign,这取决于您使用的是哪种应用程序签名工具:

  • 如果你使用 apksignerzipalign
    必须在apk签名之前使用,如果您使用apksigner签署APK,并对APK进行进一步更改,则其签名无效。
  • 如果你使用**jarsigner**,必须在签署APK之后使用zipalign

Usage


对齐infile.apk保存至outfile.apk

zipalign [-f] [-v] <alignment> infile.apk outfile.apk

确认existing.apk的对齐

zipalign -c -v <alignment> existing.apk

<alignment>是一个定义字节对齐边界的整体,这必须始终是4(提供32位对齐),否则它实际上什么也不做。

Flags:

  • -f : 覆盖已经存在的outfile.zip
  • -v : 详细输出
  • -p : outfile.zip应该为infile.zip中的所有共享对象文件使用相同的页面对齐方式。、
  • -c : 确认给定文件的对齐
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有头发的猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值