JasonWang's Blog

SELinux在Android中的应用

SELinux(Security Enhanced Linux)是Linux下的安全控制机制, 为进程访问系统资源提供了访问控制(access control)策略. 早期, Linux基于用户身份/用户组的DAC(Discretionary Access Control作为访问控制策略: 每个进程都有所属的UID, 每个文件都有所属的UID/GID以及文件模式(读写执行等), 一个进程是否可以访问某个文件就是基于UID/GID/文件模式来管理的.换句话说,只要某个资源序属于该用于或该用户组, 则该用户对该资源具有绝对控制权力, 这样一旦用户获得了root权限, 那么整个系统就成了肉鸡. 可见, DAC的安全控制策略比较粗放.

SELinux最初是由美国Utah大学与NSA(National Security Agency)的安全小组研究出来的安全框架FLASK演变而来, 后被合入到Linux 2.6版本.相较于DAC, SELinux采用的是更细粒度的MAC(Mandatory Access Control).对于DAC而言, 资源的权限是由每个用户自己控制的, 而MAC则将所有的权限收拢, 由一个统一的管理者(SELinux)统一来分配所有的资源权限, 如果访问者没有事先分配到某个资源的权限, 则不会允许访问.这样即使是root用户也要收到安全策略的约束. Android在4.3开始引入SELinux, 到了5.0版本之后, 则开始全面支持了.

如何在Android Studio中添加自定义framework.jar?

这两天有一个新的功能需求要实现, 要在Android原生代码的Settings(代码目录android/frameworks/base/core/java/android/provider)数据库添加一个新的数据项, 一个系统应用(独立于Android系统源码编译)需要引用该数据项. 那么, 怎么将新的数据项引用到系统应用中了? <! – more –>

备注: 以下所有的示例都基于Android Studio 3.2/操作系统Ubuntu 18.04.1

首先, 在Android源码中修改完成后, 执行本地编译, 在/android/out目录下, 找到编译产生的新的framework模块的jar包:

1
2
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes-full-debug.jar

Android netd工作原理详解

NETD是Android一个专门管理网络链接, 路由/带宽/防火墙策略以及iptables的系统Daemon进程, 其在Anroid系统启动时加载:

1
2
3
4
5
6
7
8

service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet

HAL binder工作流程-以RILJ/RILD通信为例

Telephony(RIL Java,以下简称RILJ)与RILD(RIL Daemon)的通信在Android OO8.0以前都是基于socket通信,而Android 8.0则是基于HAL binder进行IPC的数据交换。有关RILJ与RILD的工作原理可以参考之前的两篇文章:Android RIL概述以及RILD详解。这篇文章主要分析RILJ与RILD是如何通过HAL Binder进行通信。

RILJ与RILD的通信,服务端是RILD,客户端是RILJ。对于RILD而言,其对应的HAL接口是/android/hardware/interfaces/radio/1.0/IRadio.hal:

深入Android HAL binder

HAL binder是Android O(8.0)专门用于HAL(Hardware Abstract Layer)层(native)进程与其clients之间的通信机制(clients可以是native进程,也可以是Java Framework进程)。 HAL binder替代了早先使用的socket通信,其kernel层实际是基于原有的binder驱动,但为了配合Client与Server之间的数据传输,需要使用特定的中间层HIDL来进行接口与数据的转换。那么,相对之前的HAL通信方式(socket),基于HIDL的HAL通信有什么优势了?从系统架构的角度,HIDL为客户端与服务端提供了清晰的接口;从效率的角度,binder IPC实际在传输数据上只有一次拷贝,而socket实际传输需要两次数据拷贝。

目前Android有两种类型的HAL:

  • binder化的HAL: 利用HIDL(HAL interface Definition Language)来描述HAL接口,Framework层与HAL层通过binder IPC的方式进行通信;如下的HAL模块都是利用binder IPC来进行通信的:

    • android.hardware.biometrics.fingerprint@2.1
    • android.hardware.configstore@1.0
    • android.hardware.dumpstate@1.0
    • android.hardware.graphics.allocator@2.0
    • android.hardware.radio@1.0
    • android.hardware.usb@1.0
    • android.hardware.wifi@1.0
    • android.hardware.wifi.supplicant@1.0
  • 直通式HAL: 基于HIDL或者传统HAL方式来实现,在这种模式下,Framework层与HAL层的通信可以通过IPC的方式进行,也可以使用共享内存的方式在同一个进程内进行(passthrough,直通)。目前有如下两个HAL模块使用直通式方式进行通信:

    • android.hardware.graphics.mapper@1.0
    • android.hardware.renderscript@1.0
如何用JobScheduler进行任务调度

Android从5.0开始添加了一个任何调度服务JobSchedulerService,APP可以通过该服务进行各种任务的调度,如定时任务,与服务器同步资源,下载特定信息等。由于JobScheduler通过收集各个应用的调度任务,采用批处理的方式,允许多个任务同时运行,可以让设备具有更长的睡眠时间, 从而延长了电池使用。这篇文章,主要从应用与原理两个方面讲述分析JobScheduler

Android 动画

Android为开发者提供了强大的动画功能,常见的有属性动画(property animation)、视觉动画(view anmiation)以及可绘制对象动画(Drawable Animation),属性动画可以用于任何对象(视图对象或者非视图对象)的任何属性,而视觉动画则只能用于可视对象的某些属性,如颜色,大小,以及旋转等;可绘制对象动画利用一系列Drawable资源创建连续的帧动画。

如何在Android中查看进程状态

在Android开发调试过程中,常需要使用ps指令用于获取当前系统进程的快照信息(如果想要获取进程动态信息,则需要使用top命令)。通过ADB SHELL连接上手机后,输入adb shell命令进入shell控制台, 输入ps即可查看当前系统所有进程信息:

ps all process

Android进程Crash处理流程

之前的一篇文章,讲到了应用程序无响应(ANR)时Android的处理逻辑。这篇文章,就来分析下应用进程发生崩溃(Crash)时,Android是如何处理的?总的说来,Android主要有两大类Crash:

  • Java(JVM)层: 应用程序发生运行时错误(如空指针,浮点运算错误,数据索引超出界限)或者系统进程崩溃(长时间无响应);
  • Native层: native进程或者kernel发生运行时错误;
Android中的任务管理

Activity是Android负责与用户交互的实体。一个应用一般由多个Activity组成;一个Activity不仅可以打开应用内的Activity,也可以打开其他应用内的Activity,比如通过一个名为android.intent.action.VIEW的Intent事件可以打开浏览器;通过android.intent.action.DIAL可以向CALL发送拨号请求。一系列的Activity组合在一起(完成某个特定的“任务“)构成了一个任务(一个后进先出的队列,被称为back stack),而多个任务又构成了一个任务栈(后台可以有多个任务栈,但系统如需恢复内存,则会杀死部分应用,清空部分任务,以释放内存,因此长时间后应用状态会丢失)。以下图为例,图中的back stack一开始只有一个Activity1;接着在Activity1中启动Activity2,此时Activity2位于队列的顶部,而Activity1位于栈底(Activity1处于Stop状态),而Activity2又启动一个Activity3,同样,Activity3压入栈顶。如果此时通过回退键(Back)用户离开Activity3,则Activity3从栈中清除,被系统销毁,而Activity2则恢复到可见状态(resume)。