2021年12月

转自: 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

制作 bootanimation.zip

  1. 准备好 part0 等文件夹 和 desc.txt. desc.txt 中最后一行一定是空行。
  2. 选中所有 part 文件夹 和 desc.txt,后右键压缩,选择存储和 zip 格式。

注意,一定是选中所有文件之后压缩,而不是在 bootanimation 这个文件夹上压缩,否则压缩文件中会多出一层文件夹。系统启动的时候,动画阶段会黑屏几秒,然后直接跳到桌面。 还有 desc.txt 中最后一定要是空行,否则也会出问题。

验证 动画包是否正确。

  1. adb root, adb disable-verity, adb reboot
  2. adb root, adb remount
  3. adb shell ls /system/media 确保 system 文件夹下面有 media,如果没有,那么 adb shell mkdir /system/media
  4. adb push bootanimation.zip /system/media/ 确认 push 正常。
  5. adb reboot 检查是否替换完成。

增加文件

vendor/qcom/proprietary/qrdplus/Extension/apps/BootAnimation 文件夹下面增加相应的压缩包和编译文件.

.
└── apps
    └── BootAnimation
        ├── Android.mk
        ├── bootanimation.zip    
        └── shutdownanimation.zip

bootanimation.zip 开机动画,shutdownanimation.zip 关机动画。

Android.mk

 LOCAL_PATH := $(call my-dir)
$(warning '------------------------------------abcxyz---------------------------------------')
$(shell mkdir -p $(TARGET_OUT)/media)
$(warning $(TARGET_OUT))
$(warning '------------------------------------abcxyz---------------------------------------')
$(shell cp -r $(LOCAL_PATH)/bootanimation.zip  $(TARGET_OUT)/media/bootanimation.zip)
$(shell cp -r $(LOCAL_PATH)/shutdownanimation.zip  $(TARGET_OUT)/media/shutdownanimation.zip)
$(shell cp -r $(LOCAL_PATH)/*.wav  $(TARGET_OUT)/media)

检查是否生效

查看 out/target/product/msm8937_32/system/media 下面是否有相应的动画压缩包。

参考:

https://blog.csdn.net/myvest/article/details/50856199
https://blog.csdn.net/qq_37858386/article/details/120365883
https://blog.csdn.net/luoshengyang/article/details/7691321
安卓手机开机动画bootanimation.zip文件制作以及注意事项
https://blog.csdn.net/zhaoqi2617/article/details/70170387

增加编译信息

LOCAL_PATH := $(call my-dir)
$(warning '------------------------------------abcxyz---------------------------------------')
...

编译

make  2>&1 | tee xyz.log

这样相关的信息,就会打印到 xyz.log 这个文件里面了,在这个文件里面搜索 abcxyz 就比较方便能看到是否编译了。

转自: https://blog.csdn.net/dapangzao/article/details/74949541

本文讲述对MPAndroidChart的使用,大部分是从其文档中摘录过来的。版本3.0.2

一、MPAndroidChart

概述

MPAndroidChart 是一款专门用于Android绘制图表的库,相当强大,当然也有IOS的版本。GitHub上地址:Git-MPAndroidChart 。 其特点如下:

  • 支持8中不同图表类型
  • 支持轴上的缩放
  • 可拖动、平移
  • 可定制轴
  • 可突出选中的值(瞄准点及弹出pop)
  • 定制图例
  • 动画显示
  • 其他

下面来详细介绍其使用,涉及到的MPAndroidChart名称都用MP简称来代替。

二、基本使用

1.添加依赖

在project的build.gradle中添加依赖:

allprojects {
repositories {
maven { url “https://jitpack.io” }
}
}

在app的build.gradle中添加依赖:

dependencies {
compile ‘com.github.PhilJay:MPAndroidChart:v3.0.2’
}

2.布局

在布局文件中使用需要的图表,并在代码中获取实例。

<com.github.mikephil.charting.charts.LineChart
    android:id="@+id/chart"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

3.添加数据

首先将数据集合转换成MP需要的数据集合,然后创建DataSet,DataSet保存某个数据集(比如某条曲线),可以定制需要的样式,比如曲线颜色,图例等。最后,添加数据集到LineData中,LineData存放所有的数据,也可以定制样式。

YourData[] dataObjects = ...;
List<Entry> entries = new ArrayList<Entry>();
for (YourData data : dataObjects) {
    entries.add(new Entry(data.getValueX(), data.getValueY()));
}
LineDataSet dataSet = new LineDataSet(entries, "Lable");
dataSet.setColor(...);
...
LineData lineData = new LineData(dataSet);
chart.setData(lineData);
chart.invalidate();

这里要根据不同的表格使用不同的实体类,比如,LineChart使用Entry类,BarChart使用BarEntry类等等。

- 阅读剩余部分 -

转自: https://blog.csdn.net/qqyanjiang/article/details/51442120

目录 一步一步教你写股票走势图——分时图一(概述) 一步一步教你写股票走势图——分时图二(自定义xy轴) 一步一步教你写股票走势图——分时图三(对齐图表、自定义柱状图高亮) 一步一步教你写股票走势图——分时图四(高亮联动) 一步一步教你写股票走势图——分时图五(自定义标记) 一步一步教你写股票走势图——K线图一(概述) 一步一步教你写股票走势图——K线图二(图表联动) 一步一步教你写股票走势图——K线图三(添加均线) 一步一步教你写股票走势图——K线图四(高亮联动一) 一步一步教你写股票走势图——K线图五(高亮联动二) 一步一步教你写股票走势图——商业版

demo更新地址 https://github.com/AndroidJiang/StockChart

因为公司的项目需求,最近不得不研究下股票走势图,经过自己的学习和筛选,考虑到自己自定义图表库水平有限,最后选择[MpAndroidChart],项目源码将会在开发完毕后放到github上,欢迎star,(https://github.com/PhilJay/MPAndroidChart)图表库来实现股票走势图,本项目用的是v2.2.5。 股票走势图大致有两种:分时图,K线图。

- 阅读剩余部分 -