安装 ffmpeg

  1. sudo apt-get update
  2. sudo apt install ffmpeg

检查视频

使用 ffplay xyz.mp4 看下视频能不能播放。 使用 ffmpeg -i xyz.mp4 查看视频长宽等信息。

参考: https://www.cnblogs.com/renhui/p/8458802.html

转换视频角度

ffmpeg -i pc-v.mp4 -vf "transpose=1" ./out.mp4 可以让视频旋转 90度。

参考: ffmpeg实现视频的翻转与旋转(ffmpeg4.2.2)
https://www.cnblogs.com/architectforest/p/12818543.html

转换视频分辨率

ffmpeg -i out.mp4 -vf scale=720:1280 out_1.mp4 让视频分辨率转换为 720 x 1280.

参考: ffmpeg 命令行改变视频分辨率
https://www.cnblogs.com/nanqiang/p/12103307.html
ffmpeg-修改分辨率
https://blog.csdn.net/weixin_38556197/article/details/108594866
ffmpeg修改视频文件的分辨率
https://www.cnblogs.com/lcxiao/p/11509132.html

把视频转换为图片集

ffmpeg -i ../out_1.mp4 -r 30 -f image2 %05d.jpg 把视频转换为 5位数字序号的图片集。

参考: ffmpeg将视频转换成图片
https://blog.csdn.net/lxx4610/article/details/107813385
ffmpeg将mp4视频转换成多张jpg图片
https://blog.csdn.net/danmeng8068/article/details/96430660
ffmpeg批量将视频转为单帧图片shell脚本
https://zhuanlan.zhihu.com/p/31637663

转自: https://blog.csdn.net/vagrant2005/article/details/6561795

Ubuntu 终端下默认的编辑器为 nano。比如输入命令“crontab -e”就会打开 nano。不过我们在学会使用 Vim 以后可能就不愿意在使用 nano 了。那么怎么才能直接就调用 Vim 编辑器来编辑呢?只需要修改一个配置我们就可以做到。操作步骤如下:

内容来自Linuxren.net

  打开一个终端,在其中输入如下命令: copyright Linuxren.net

    $ sudo update-alternatives –config editor copyright Linuxren.net

  然后在返回的对话中选择第 4 项 vim.basic 。或者还可以直接执行这个命令: 内容来自Linuxren.net

    echo export EDITOR=/usr/bin/vim >> ~/.bashrc
内容来自Linuxren.net

  来实现我们的需求。 本文来自Linuxren.net

转自: https://blog.csdn.net/qq_37858386/article/details/103834675

Android APP:检测实体按键事件

一、检测点击按键事件一般不对手机上的输入按键进行处理,直接由系统按照默认情况操作。

当然有时为了改善用户体验,需要让应用拦截按键事件,并进行额外处理。 要想监控按键事件,首先得知道每个按键的编码,这样才能根据不同的编码值进行相应的处理。监听器OnKeyListener只会检测控制键,不会检测文本键。实际测试发现HOME、SWICH、POWER普通的app是接收不到事件的,这几个事件在framew里面处理了。

二、部分控制键KEYCODE

三、测试代码

1、android_studio_app\keyeventdemo\app\src\main\java\com\example\keyeventdemo\MainActivity.java

    package com.example.keyeventdemo;

    import android.os.Bundle;
    import android.os.Handler;
    import android.support.v7.app.AppCompatActivity;
    import android.view.KeyEvent;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.TextView;
    public class MainActivity extends AppCompatActivity {
        private TextView key_result;
        private String desc = "";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            key_result = (TextView) findViewById(R.id.key_result);
        }
      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            key_result = (TextView) findViewById(R.id.key_result);
        }

       @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            desc = String.format("%sphysical key coce is %d", desc, keyCode);
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                desc = String.format("%s, KEYCODE_BACK", desc);
            } else if (keyCode == KeyEvent.KEYCODE_MENU) {
                desc = String.format("%s, KEYCODE_MENU", desc);
            } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
                desc = String.format("%s, KEYCODE_VOLUME_UP", desc);
            } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                desc = String.format("%s, KEYCODE_VOLUME_DOWN", desc);
            }else  {
                desc = String.format("%s, KEYCODE_VOLUME is unknown", desc);
            }
            desc = desc + "\n";
            key_result.setText(desc);
            //返回true表示不再响应系统动作,返回false表示继续响应系统动作
            return true;
          // return  false;
        }
    }

2、布局文件 activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="5dp">

        <TextView
            android:id="@+id/tv_hard"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center"
            android:text="please press the physics button"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/key_result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="16sp" />

    </LinearLayout>

- 阅读剩余部分 -

永久关闭SELinux
https://zhuanlan.zhihu.com/p/336648934

android+关闭selinux权限问题,记录Android开发中SELINUX权限问题-Go语言中文社区
https://blog.csdn.net/weixin_39600704/article/details/117757795

Android程序报错: 权限问题java.io.FileNotFoundException: ……:open failed: EACCES (Permission denied)
https://blog.csdn.net/tm_6666/article/details/106792314?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-2.highlightwordscore&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-2.highlightwordscore

操作sys/device下文件节点的三种方法
https://blog.csdn.net/tanliyin/article/details/72723229?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-9.highlightwordscore&spm=1001.2101.3001.4242.6

读取设备节点/sys/class/XX :Android java.io.FileNotFoundException: open failed: EACCES (Permission denied)
https://blog.csdn.net/wds1181977/article/details/54967110

充电指示灯控制中SELinux权限问题
https://blog.csdn.net/mickeymousemei123/article/details/99828287

LED节点访问增加selinux权限记录
https://blog.csdn.net/wangwei6227/article/details/86648876

Selinux SeAndroid理解
https://blog.csdn.net/bsxiaomage/article/details/51126826

SELinux权限问题解决方法
https://blog.csdn.net/w2064004678/article/details/105515244/

记录Android开发中SELINUX权限问题
https://blog.csdn.net/maowendi/article/details/105564908

android:sharedUserId="android.uid.system" 的使用
https://blog.csdn.net/m0_38094058/article/details/82628731

关于android:sharedUserId="android.uid.system" 的使用
https://blog.csdn.net/MYBOYER/article/details/104902159

selinux常见neverallow项解决方法与常用命令
https://blog.csdn.net/k663514387/article/details/107983037

Android P系统编译报错SELinux违反Neverallow
https://blog.csdn.net/Sunxiaolin2016/article/details/91435362

[Android Framework]Android 11 SELinux avc权限解决方法
http://www.zyiz.net/tech/detail-259152.html

Android SELiunx 权限添加
https://blog.51cto.com/u_15127678/2800306

深刻理解SELinux SEAndroid
https://www.shangmayuan.com/a/d7ccd609100e479fad0952d6.html

Neverallow failures occurred Error while expanding policy in AOSP10
https://discuss.96boards.org/t/neverallow-failures-occurred-error-while-expanding-policy-in-aosp10/9712

Need some Guide with a Android SELinux Build Error
https://stackoverflow.com/questions/58956629/need-some-guide-with-a-android-selinux-build-error

SELINUX安全访问机制,配置
https://www.codenong.com/cs110875925/

【Android笔记】Android应用层读取驱动设备节点
https://www.jianshu.com/p/e4a8549a903c

selinux 问题集锦
https://blog.csdn.net/chenpuo/article/details/116456987

linux sysfs文件系统(三)属性文件读写原理分析
https://blog.csdn.net/oqqYuJi12345678/article/details/101849978

Android 上层应用读写设备节点
https://blog.csdn.net/huhuayouxu/article/details/53783799?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242.1

Android app如何正确读写系统sys设备节点
https://blog.csdn.net/u014341735/article/details/51244258

Selinux机制介绍与添加流程
https://blog.csdn.net/hjlgs/article/details/98958141
android 开发串口中遇到的权限问题 (个人笔记)
https://blog.csdn.net/only_you_zj/article/details/80098192 Android串口设备热插拔,ttyACM、ttyUSB权限修改
https://blog.csdn.net/u013595260/article/details/119496169
android _5.1 _串口权限
https://blog.csdn.net/izhetu/article/details/52311450
Android 串口相关权限问题
https://blog.csdn.net/qq_39734379/article/details/80525389
android读写串口的权限问题
https://blog.csdn.net/dddxxxx/article/details/53635966

深入理解SELinux SEAndroid(第一部分)
https://blog.csdn.net/innost/article/details/19299937
SELinux/SEAndroid 实例简述(一) 基础概念
https://blog.csdn.net/shell812/article/details/54930027
SELinux/SEAndroid 实例简述(二) TE语言规则
https://blog.csdn.net/shell812/article/details/54930246
SELinux/SEAndroid 实例简述(三)实例看SELinux/SEAndroid
https://blog.csdn.net/shell812/article/details/58596377
【selinux】selinux加prop,hal层读取
https://blog.csdn.net/qq_38091632/article/details/113831585

转自: https://blog.csdn.net/vviccc/article/details/108806893

1 原理

在init启动时就直接设置selinux_is_enforcing强制返回为false。这样 开机启动后 执行

$getenforce

操作时 获取到的是 Permissive,即 SELinux 关闭状态。

2 修改方案(Android O)

修改文件为:system/core/init/init.cpp,修改内容如下:

    @@ -571,7 +571,7 @@ static void selinux_init_all_handles(void)
     }

     enum selinux_enforcing_status { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
    -
    +#if 0
     static selinux_enforcing_status selinux_status_from_cmdline() {
         selinux_enforcing_status status = SELINUX_ENFORCING;

    @@ -583,13 +583,17 @@ static selinux_enforcing_status selinux_status_from_cmdline() {

         return status;
     }
    +#endif

     static bool selinux_is_enforcing(void)
     {
    +   return false;
    +#if 0
         if (ALLOW_PERMISSIVE_SELINUX) {
             return selinux_status_from_cmdline() == SELINUX_ENFORCING;
         }
         return true;
    +#endif
     }

     static int audit_callback(void *data, security_class_t /*cls*/, char *buf, size_t len) {

3 修改方案(Android Q)

修改文件为:system/core/init/selinux.cpp,修改内容如下:

     selabel_handle* sehandle = nullptr;

     enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
    -
    +#if 0
     EnforcingStatus StatusFromCmdline() {
         EnforcingStatus status = SELINUX_ENFORCING;

    @@ -95,12 +95,15 @@ EnforcingStatus StatusFromCmdline() {

         return status;
     }
    -
    +#endif
     bool IsEnforcing() {
    +#if 0
         if (ALLOW_PERMISSIVE_SELINUX) {
             return StatusFromCmdline() == SELINUX_ENFORCING;
         }
         return true;
    +#endif
    +    return false;
     }

     // Forks, executes the provided program in the child, and waits for the completion in the parent.

转自: https://note.youdao.com/ynoteshare/index.html?id=a5e6662dc0b4a2c0d929fdcf6bdea975&type=note&_time=1638928207538

验证是否是权限问题。

1.机器首先需要有root权限,执行setenforce 0,执行完getenforce显示Permissive就成功了; 2.修改代码 system/core/init/init.c

bool is_enforcing = selinux_is_enforcing();
+is_enforcing=false;
INFO("SELinux: security_setenforce(%d)\n", is_enforcing);  

先模块编译system/core/init/,然后再编译bootimage

如果以上处理完成后,问题得到解决,则说明是Selinux权限限制导致的该问题;

项目处理:

<38>[   22.872478] type=1400 audit(1325376041.960:3): avc: denied { read write } for pid=585 comm="system_server" name="au_interrupt" dev="tmpfs" ino=11449 scontext=u:r:system_server:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
<38>[   22.896195] type=1400 audit(1325376041.960:4): avc: denied { open } for pid=585 comm="system_server" path="/dev/au_interrupt" dev="tmpfs" ino=11449 scontext=u:r:system_server:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
<6>[   23.009953] lowmemorykiller: lowmem_shrink: convert oom_adj to oom_score_adj:

1.使用adb shell进入/dev/au_interrupt,执行ls -Z查看此设备的属性设置,此时显示是u:object_r:device:s0 ,对此device进行重新定义;

device\intel\baytrail\sepolicy\file_contexts-->/dev/au_interrupt                 u:object_r:au_interrupt_device:s0
device\intel\baytrail\sepolicy\device.te-->type au_interrupt_device, dev_type;

编译后全部升级,再次进入/dev/下查看ls -Z属性,此时应显示为 u:object_r:au_interrupt_device:s0; (restorecon /dev/au_interrupt 重新加载属性,然后ls -Z;也可以将此命令写入rc文件)

2.线程名称是system_server,所以进入system_server.te对其进行权限赋值操作;

allow system_server au_interrupt_device:chr_file {read write open};

如一行LOG:

<5>[ 17.285600].(0)[503:idmap]type=1400 audit(1356999072.320:202): avc: denied {create } for pid=503 comm="idmap" name="overlays.list" scontext=u:r:zygote:s0
tcontext=u:object_r:resource_cache_data_file:s0 tclass=file

即表明idmap 这个process, 使用zygote 的source context, 访问/data/resource_cache 目录,并创建文件时,被SELinux 拒绝访问。

为了规避这种权限放大情况, 我们需要细化访问目标(Object) 的SELinux Label, 做到按需申请.

通常会由三步构成 3.1 定义相关的SELinux type. 比如上述案例, 在 device/mediatek/common/sepolicy/device.te 添加

type tfa9897_device, dev_type;

3.2 绑定文件与SELinux type. 比如上述案例, 在 device/mediatek/common/sepolicy/file_contexts 添加

/dev/tfa9897(/.*)? u:object_r:tfa9897_device:s0

3.3 添加对应process/domain 的访问权限. 比如上述案例, 在 device/mediatek/common/sepolicy/mediaserver.te 添加

allow mediaserver tfa9897_device:chr_file { open read write };

- 阅读剩余部分 -

转自: https://blog.csdn.net/jydzm/article/details/105864194?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

通过对/sys/class/leds/brightness节点写数据来驱动LED灯打开或关闭。

adb shell
echo 125 > /sys/class/leds/brightness (打开LED灯,1-255,值越大,LED越亮)
echo 0 > /sys/class/leds/brightness (关闭LED灯)

以上是通过adb 操作的,接下来是在APP应用中驱动LED灯打开和关闭方法:

方法1:

public void cmdLedOpen() {
    String cmd = "/system/bin/busybox " + "echo 240 >/sys/class/leds/brightness " + "\n";
    try {
        Process exeEcho = Runtime.getRuntime().exec("sh");
        exeEcho.getOutputStream().write(cmd.getBytes());
        exeEcho.getOutputStream().flush();
        Log.d(TAG, " " + cmd);
    } catch (Exception e) {
        Log.d(TAG, "cmdRelayOpen faild");
    }
}

方法2:

public void openLed(){
    try {
        BufferedWriter bw = new BufferedWriter(new FileWriter("/sys/class/leds/brightness"));
        bw.write("250");
        bw.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

转自: https://blog.csdn.net/u010753159/article/details/51356331?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-7-51356331.nonecase&utm_term=android%20%E9%AB%98%E9%80%9A%E7%9A%84%E5%BC%80%E6%9C%BA%E5%8A%A8%E7%94%BB

在上篇文章《Android5.1开机画面显示工作流程分析》中,详细分析了Android开机动画显示的工作流程。其中提到了每个开机动画压缩文件中必须包含一个描述文件desc.txt,该文件用来描述开机动画具体是怎么样显示的。这篇文章就对desc.txt进行一个详细的解读。

1 desc.txt文件格式分析

desc.txt文件由若干行组成,每一行代表一种描述。下面以一个具体的例子为例,具体说明

    480 640 20
    p 1 0 folder1
    p 2 20 folder2
    c 0 0 folder3
    c 1 0 folder4

第1行用来描述开机动画在屏幕显示的大小及速度。具体为:开机动画的宽度为480个像素,高度为640个像素,显示频率为每秒20帧,即每帧显示1/20秒。

下面的每一行代表一个片段,显示的时候会按照顺序从上到下依次显示。第1个字符为片段类型,有'c'和'p'两种,两者的区别后面会结合代码说明。

第2个数字为该片段重复显示的次数,如果为‘0’,表示会无限重复显示;第3个数字为两次显示之间的间隔,单位为第一行中定义的每帧显示的时间;第4个字符串为该片段所在的文件夹,一个片段可以由多个png图片组成,都存放在folder文件夹中。

“p 1 0 folder1”代表该片段显示1次,与下一个片段间隔0s,该片段的显示图片路径为bootanimation.zip/folder1。

“p 2 20 folder2”代表该片段显示2次,且两次之间显示的间隔为20(1/20)=1s,与下一个片段间隔20(1/20)=1s,该片段的显示图片路径为bootanimation.zip/folder2。

“c 0 0 folder3”代表该片段无限循环显示,且两次显示的间隔为0s,与下一个片段间隔0s,该片段的显示图路径为bootanimation.zip/folder3。

“c 1 10 folder4”代表该片段显示1次,显示后暂停10*(1/20)=0.5s,该片段的显示图路径为bootanimation.zip/folder4。

2 "p"片段和“c”片段的区别

在早期Android版本中只有“p”片段,且movie()中的显示代码如下:

    for (int i=0 ; i<pcount && !exitPending() ; i++) {  
            const Animation::Part& part(animation.parts[i]);  
            const size_t fcount = part.frames.size();  
            glBindTexture(GL_TEXTURE_2D, 0);  

            for (int r=0 ; !part.count || r<part.count ; r++) {  
                for (int j=0 ; j<fcount && !exitPending(); j++) {  
                    const Animation::Frame& frame(part.frames[j]);  

                .......

        .....
    }

里面的主要参数和函数说吗如下:

pcount---显示片段的数量,比如上面的例子,pcount=4

p.count---该片段的重复显示次数。

fcount---该片段中png图片的数量 exitPending()---如果SurfaceFlinger服务通知bootanimation停止显示动画,则该函数返回值为true,否则为false。

第一个for循环用于顺序显示所有片段,第二个for循环用于重复显示该片段,第三个for循环用于顺序显示该片段中所有的png图片。

分析代码,可知:若exitPending()返回值为true,即SurfaceFlinger服务要求bootanimation停止显示动画,则不管当前显示到哪个片段或png图片,都会导致退出for循环,从而停止开机动画的显示。

在Android5.1中,加入了“c”片段。对与以"c"标识的片段,即使exitPending()返回值为true,也会继续显示。

我们分析一下源码,首先看一下movie()中解析desc.txt的代码:

        // Parse the description file  
        for (;;) {  
            ...... 
            if (sscanf(l, "%d %d %d %d", &width, &height, &fps, &flg) >= 3) {  
                animation.width = width;  
                animation.height = height;  
                animation.fps = fps;  
            }  
            else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) {  
                Animation::Part part;  
                part.playUntilComplete = pathType == 'c';  
                part.count = count;  
                part.pause = pause;  
                part.path = path;  
                part.audioFile = NULL;  
                if (!parseColor(color, part.backgroundColor)) {  
                    ALOGE("> invalid color '#%s'", color);  
                    part.backgroundColor[0] = 0.0f;  
                    part.backgroundColor[1] = 0.0f;  
                    part.backgroundColor[2] = 0.0f;  
                }  
                animation.parts.add(part);  
            }  

            s = ++endl;  
        }

可以看到,如果pathType==‘c’,part.playUntilComplete等于true,否则为false。接着,看一下显示代码:

    for (size_t i=0 ; i<pcount ; i++) {  
            const Animation::Part& part(animation.parts[i]);  
            const size_t fcount = part.frames.size();  
            glBindTexture(GL_TEXTURE_2D, 0);  

            for (int r=0 ; !part.count || r<part.count ; r++) {  
                // Exit any non playuntil complete parts immediately  
                if(exitPending() && !part.playUntilComplete)  
                    break;  

                ......
                for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {  

            ......

                    checkExit();  
                }  

                usleep(part.pause * ns2us(frameDuration));  

                // For infinite parts, we've now played them at least once, so perhaps exit  
                if(exitPending() && !part.count)  
                    break;  
            }  

            ......  
        } 

可以看到,如果exitPending()返回值为true且part.playUntilComplete=false,则会break。即:当SurfaceFlinger服务要求bootanimation停止显示动画时,以‘p’标识的片段会停止,而以'c'标识的片段会继续显示。这就是两者之间的主要区别。

这里有个问题:重复循环显示的'c'标识片段,会不受任何约束的一直显示下去,这显然是不合适的。 于是在第二个for循环体最后,有如下代码:

    // For infinite parts, we've now played them at least once, so perhaps exit  
                if(exitPending() && !part.count)  
                    break; 

意思是,如果检测到SurfaceFlinger服务要求bootanimation停止显示,且该片段的显示次数为'0',即重复循环显示,则会break停止显示。

我猜想"c"标识的意思是continue,即:即使SurfaceFlinger要求bootanimation停止动画,bootanimation也不会立刻停止动画,它会等c标识片段都显示完毕后,再停止。

这样,我们可以利用'c'和'p'片段的区别,设计出更灵活的开机动画。

转自: https://blog.csdn.net/u010218230/article/details/80007819?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1.fixedcolumn&spm=1001.2101.3001.4242.2

应用层中,一般都能够读取设备节点。对于写节点这个操作,需要更高的root权限。

示例: 设备节点:

private static final String LED_RED_TRIGGER = "sys/class/leds/red/on_off";

写节点:

    private void setLedOnOff(String path, String value) {
        try {
            BufferedWriter bufWriter = null;
            bufWriter = new BufferedWriter(new FileWriter(path));
            bufWriter.write(value + "");
            bufWriter.close();
            Log.d(TAG, "write setLedOnOff: " + value);
        } catch (IOException e) {
            Log.e(TAG,"erro= "+ Log.getStackTraceString(e));
        }
    }

读节点:

    private boolean isLedOn(String path){
        try {
            FileReader fr = new FileReader(path);
            BufferedReader br = new BufferedReader(fr);
            String readString = null;
        String valueString = null;
        while ((readString = br.readLine())!=null){
                if(readString == null)break;
                valueString = readString;
            }
            br.close();
            return valueString != null && valueString.equals("1");//此处1表示灯亮,0表示灯灭
        } catch (IOException e) {
           Log.e(TAG,"erro= "+ Log.getStackTraceString(e));
        }
        return false;
    }

打开更多信息

adb shell echo 8 > proc/sys/kernel/printk

抓取 log 到文件

adb logcat -v time -b all > logcatlog.txt

查看按键是否上报

adb shell
getevent -l

获取按键更多 log

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 中,把 PhoneWindowManager 这个类开始的 DEBUG_ 相应的选项全部开启,然后抓 log,会有更多的信息。 在 logcatlog.txt 中搜索 keycode 能够看到相应的按键信息。

配置以太网

ifconfig eth0 192.168.42.10 up
ndc network create 100
ndc network interface add 100 eth0
ip route add  default  dev eth0 table eth0
ndc network default set 100 

串口调试

su 进入 root 模式,然后就可以使用各种命令了。

获取 配置信息

cat proc/cmdline 可以获取到详细的信息。类似:

PS C:\Users\Administrator\Downloads> adb shell cat proc/cmdline
sched_enable_hmp=1 console=ttyMSM0,115200,n8 androidboot.console=ttyMSM0 androidboot.hardware=qcom user_debug=30 msm_rtb.filter=0x237 ehci-hcd.park=3 androidboot.bootdevice=7824900.sdhci lpm_levels.sleep_disabled=1 earlycon=msm_hsl_uart,0x78B0000 vmalloc=300M androidboot.usbconfigfs=true loop.max_part=7 buildvariant=userdebug androidboot.emmc=true androidboot.verifiedbootstate=orange androidboot.keymaster=1 dm="1 vroot none ro 1,0 6192024 verity 1 PARTUUID=7e631c69-e9c2-c3a5-4546-cce1a015dd9e PARTUUID=7e631c69-e9c2-c3a5-4546-cce1a015dd9e 4096 4096 774003 774003 sha1 2784ab9d836408d49146c1652a46d2475ced3b5c ff0a52cb0d14e1706741d069fd806262a53cc6eb 10 ignore_zero_blocks ignore_zero_blocks use_fec_from_device PARTUUID=7e631c69-e9c2-c3a5-4546-cce1a015dd9e fec_roots 2 fec_blocks 780099 fec_start 780099" root=/dev/dm-0 androidboot.vbmeta.device=PARTUUID=7b85f276-e2ea-7cec-b973-4fe4bafd7fb0 androidboot.vbmeta.avb_version=1.0 androidboot.vbmeta.device_state=unlocked androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=4160 androidboot.vbmeta.digest=1b4ac7cea500c90d3e98094f85b9bbef5c2f0cec330efd8ff9be7ddc6919cf9f androidboot.veritymode=eio androidboot.serialno=e7ba90a1 androidboot.baseband=msm mdss_mdp.panel=1:dsi:0:qcom,mdss_dsi_ili9881c_720p_video:1:none:cfg:single_dsi skip_initramfs rootwait ro init=/init androidboot.dtbo_idx=23 androidboot.dtb_idx=5

参考

android系列:第三篇android调试常用工具:模拟按键输入,修改分辨率,获得按键消息
https://blog.csdn.net/radianceblau/article/details/75221368