前置知识
1.Binder相关 - AIDL
binder
在android
中主要充当跨进程通信桥梁的角色,为C/S
架构,如app
中的startactivity
方法,首先app
(客户端)会向ASM
(服务端)请求一个AMS
的本地代理,即ActivityManagerNative
,之后app
与AMS
的通信就通过本地代理来实现
AIDL
是一种简单化写binder
通信的方法。可以理解为原来写binder
通信很难,而通过AIDL
这种方式来写的话会很方便
Simple:原来的AIDL
类
interface IInterface {
void action(int a);
}
编译之后的产物
public interface IInterface extends android.os.IInterface {
// 远端服务,服务端
public static abstract class Stub extends android.os.Binder implements IInterface {
// 获取服务,先查看服务与获取服务的进程是不是同一个,为同一个的话直接返回,不是的话就返回一个服务的代理对象
public static IInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof IInterface))) {
return ((IInterface) iin);
}
return new IInterface.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
// 具体的通信过程,
// 1.客户端按照规定格式和顺序写入,
// 2.服务端按照规定格式和顺序读出并执行客户端要求执行的方法
// 3.服务端将返回结果按照规定格式和顺序写入
// 4.客户端按照规定格式和顺序读取出结果,通信完成
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_action: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
this.aa(_arg0);
reply.writeNoException();
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
// 远程服务的代理类,客户端与该类通信等同于与远程服务通信
private static class Proxy implements IInterface {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void action(int a) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(aa);
boolean _status = mRemote.transact(Stub.TRANSACTION_action, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
}
- 总结通信步骤(以上面
AIDL
为例):- 1.在
app
里面获取远程服务的代理对象,即new IInterface.Stub.Proxy(obj)
- 2.在
Proxy
中action
方法_data
写入数据,_reply
读出结果 - 3.
stub
,数据写入到onTransact
方法读出,匹配标识符执行相应方法并向客户端写回数据
- 1.在
获取系统服务的部分代码解析(Android10.0)
以startactivity方法为例
startactivity();
...
ActivityTaskManager.getService().startActivity(...);
// ActivityTaskManager.java
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
// Singleton.java
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
// ServiceManager.java
@UnsupportedAppUsage
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
// 前面请求过,缓存起来
return service;
} else {
// 获取远程服务
return Binder.allowBlocking(rawGetService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
- 获取系统服务流程总结:系统服务是在
ServiceManager.java
类中的getService
被获取,在其方法中如果sCache
中有被获取的代理对象则直接返回,没有就 new 一个后缓存起来。
matrix-battery-canary hook分析
1. AlarmMonitorFeature
该类的启动结束监控是由onTurnOn
与onTurnOff
方法控制
public void onTurnOn() {
super.onTurnOn();
if (mCore.getConfig().isAmsHookEnabled) {
mListener = new AlarmManagerServiceHooker.IListener() {
@Override
public void onAlarmSet(int type, long triggerAtMillis, long windowMillis, long intervalMillis, int flags, PendingIntent operation, AlarmManager.OnAlarmListener onAlarmListener) {
String stack = "";
if (mCore.getConfig().isStatAsSample) {
// 抛出异常得到 “at android.app.AlarmManager” 开头的异常信息行并拼接
stack = BatteryCanaryUtil.polishStack(Log.getStackTraceString(new Throwable()), "at android.app.AlarmManager");
}
AlarmRecord alarmRecord = new AlarmRecord(type, triggerAtMillis, windowMillis, intervalMillis, flags, stack);
MatrixLog.i(TAG, "#onAlarmSet, target = " + alarmRecord);
if (operation != null || onAlarmListener != null) {
int traceKey = operation != null ? operation.hashCode() : onAlarmListener.hashCode();
mAlarmTracing.onSet(traceKey, alarmRecord);
}
}
@Override
public void onAlarmRemove(PendingIntent operation, AlarmManager.OnAlarmListener onAlarmListener) {
if (operation != null || onAlarmListener != null) {
int traceKey = operation != null ? operation.hashCode() : onAlarmListener.hashCode();
mAlarmTracing.onRemove(traceKey);
}
}
};
AlarmManagerServiceHooker.addListener(mListener);
}
}
// AlarmManagerServiceHooker.java
private static SystemServiceBinderHooker sHookHelper = new SystemServiceBinderHooker(Context.ALARM_SERVICE, "android.app.IAlarmManager", sHookCallback);
private static List<IListener> sListeners = new ArrayList<>();
public synchronized static void addListener(IListener listener) {
if (listener == null) {
return;
}
if (sListeners.contains(listener)) {
return;
}
sListeners.add(listener);
checkHook();
}
private static void checkHook() {
if (sTryHook) {
return;
}
if (sListeners.isEmpty()) {
return;
}
boolean hookRet = sHookHelper.doHook();
MatrixLog.i(TAG, "checkHook hookRet:%b", hookRet);
sTryHook = true;
}
-
SystemServiceBinderHooker.java
之前执行过 private static SystemServiceBinderHooker sHookHelper = new SystemServiceBinderHooker(Context.ALARM_SERVICE, "android.app.IAlarmManager", sHookCallback);
public class SystemServiceBinderHooker {
private static final String TAG = "Matrix.battery.SystemServiceBinderHooker";
public interface HookCallback {
void onServiceMethodInvoke(Method method, Object[] args);
@Nullable Object onServiceMethodIntercept(Object receiver, Method method, Object[] args) throws Throwable;
}
private final String mServiceName;
private final String mServiceClass;
private final HookCallback mHookCallback;
@Nullable private IBinder mOriginServiceBinder;
@Nullable private IBinder mDelegateServiceBinder;
public SystemServiceBinderHooker(final String serviceName, final String serviceClass, final HookCallback hookCallback) {
mServiceName = serviceName;
mServiceClass = serviceClass;
mHookCallback = hookCallback;
}
@SuppressWarnings({"PrivateApi", "unchecked", "rawtypes"})
public boolean doHook() {
MatrixLog.i(TAG, "doHook: serviceName:%s, serviceClsName:%s", mServiceName, mServiceClass);
try {
// 反射构造出了 IAlarmManager 的代理对象
BinderProxyHandler binderProxyHandler = new BinderProxyHandler(mServiceName, mServiceClass, mHookCallback);
IBinder delegateBinder = binderProxyHandler.createProxyBinder();
// 将代理对象放到 ServiceManager 的 sCache 容器中,这样当下次 getService 时如果有相应的服务则直接返回,这里为直接返回我们自己反射构造的对象
Class<?> serviceManagerCls = Class.forName("android.os.ServiceManager");
Field cacheField = serviceManagerCls.getDeclaredField("sCache");
cacheField.setAccessible(true);
Map<String, IBinder> cache = (Map) cacheField.get(null);
cache.put(mServiceName, delegateBinder);
mDelegateServiceBinder = delegateBinder;
mOriginServiceBinder = binderProxyHandler.getOriginBinder();
return true;
} catch (Throwable e) {
MatrixLog.e(TAG, "#doHook exp: " + e.getLocalizedMessage());
}
return false;
}
@SuppressWarnings({"PrivateApi", "unchecked", "rawtypes"})
public boolean doUnHook() {
if (mOriginServiceBinder == null) {
MatrixLog.w(TAG, "#doUnHook mOriginServiceBinder null");
return false;
}
if (mDelegateServiceBinder == null) {
MatrixLog.w(TAG, "#doUnHook mDelegateServiceBinder null");
return false;
}
try {
// 通过反射执行 ServiceManager::getService 拿到 IAlarmManager 对象,优先从 ServiceManager 中的 sCache 中取
IBinder currentBinder = BinderProxyHandler.getCurrentBinder(mServiceName);
if (mDelegateServiceBinder != currentBinder) {
MatrixLog.w(TAG, "#doUnHook mDelegateServiceBinder != currentBinder");
return false;
}
// 放回没有被动态代理过的对象
Class<?> serviceManagerCls = Class.forName("android.os.ServiceManager");
Field cacheField = serviceManagerCls.getDeclaredField("sCache");
cacheField.setAccessible(true);
Map<String, IBinder> cache = (Map) cacheField.get(null);
cache.put(mServiceName, mOriginServiceBinder);
return true;
} catch (Throwable e) {
MatrixLog.e(TAG, "#doUnHook exp: " + e.getLocalizedMessage());
}
return false;
}
static final class BinderProxyHandler implements InvocationHandler {
private final IBinder mOriginBinder;
private final Object mServiceManagerProxy;
BinderProxyHandler(String serviceName, String serviceClass, HookCallback callback) throws Exception {
// 通过反射执行 ServiceManager::getService 拿到 IAlarmManager 对象
mOriginBinder = getCurrentBinder(serviceName);
// 通过反射执行 IAlarmManager$Stub 对象的 asInterface 方法,拿到 IAlarmManager 这个远程服务对象的本地代理
// 并通过动态代理 IAlarmManager 这个接口,将其执行的方法通过 callback 回调出去
mServiceManagerProxy = createServiceManagerProxy(serviceClass, mOriginBinder, callback);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 原来 queryLocalInterface 方法一般都是返回空,但是我们在构造函数中先反射构造出了其代理对象,所以可以直接返回
// ServiceManager::getService 之后需要返回一个远程服务的本地代理,会先执行其 queryLocalInterface 这个方法,这个方法不为空则直接返回其代理,
// 为空则执行对应的 XXXManager$Stub::asInterface 方法返回一个程服务的本地代理对象,但是在构造函数中我们直接反射执行了 XXXManager$Stub::asInterface 该方法,拿到了返回对象
if ("queryLocalInterface".equals(method.getName())) {
return mServiceManagerProxy;
}
return method.invoke(mOriginBinder, args);
}
public IBinder getOriginBinder() {
return mOriginBinder;
}
@SuppressWarnings({"PrivateApi"})
// 动态代理 IBinder 这个接口,当前发起 ServiceManager::getService 这个请求之后,开始执行 queryLocalInterface 这个方法时,将构造函数中的 mServiceManagerProxy 返回回去
public IBinder createProxyBinder() throws Exception {
Class<?> serviceManagerCls = Class.forName("android.os.ServiceManager");
ClassLoader classLoader = serviceManagerCls.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("Can not get ClassLoader of " + serviceManagerCls.getName());
}
return (IBinder) Proxy.newProxyInstance(
classLoader,
new Class<?>[]{IBinder.class},
this
);
}
@SuppressWarnings({"PrivateApi"})
// 通过反射执行 ServiceManager::getService 拿到 IAlarmManager 对象
static IBinder getCurrentBinder(String serviceName) throws Exception {
Class<?> serviceManagerCls = Class.forName("android.os.ServiceManager");
Method getService = serviceManagerCls.getDeclaredMethod("getService", String.class);
return (IBinder) getService.invoke(null, serviceName);
}
@SuppressWarnings({"PrivateApi"})
private static Object createServiceManagerProxy(String serviceClassName, IBinder originBinder, final HookCallback callback) throws Exception {
Class<?> serviceManagerCls = Class.forName(serviceClassName);
// 通过反射执行 IAlarmManager$Stub 对象的 asInterface 方法,拿到 IAlarmManager 这个远程服务对象的本地代理
Class<?> serviceManagerStubCls = Class.forName(serviceClassName + "$Stub"); // android.app.IAlarmManager$Stub
ClassLoader classLoader = serviceManagerStubCls.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("get service manager ClassLoader fail!");
}
Method asInterfaceMethod = serviceManagerStubCls.getDeclaredMethod("asInterface", IBinder.class);
final Object originManagerService = asInterfaceMethod.invoke(null, originBinder);
// 通过动态代理 IAlarmManager 这个接口,将其执行的方法通过 callback 回调出去
return Proxy.newProxyInstance(classLoader,
new Class[]{IBinder.class, IInterface.class, serviceManagerCls},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (callback != null) {
callback.onServiceMethodInvoke(method, args);
Object result = callback.onServiceMethodIntercept(originManagerService, method, args);
if (result != null) {
return result;
}
}
return method.invoke(originManagerService, args);
}
}
);
}
}
}
// 在 IAlarmManager 被动态代理之后,其方法执行都会被会回调到 sHookCallback 这里来,回调的方法有
// 9.0 中
// void set(String callingPackage, int type, long triggerAtTime, long windowLength,
// long interval, int flags, in PendingIntent operation, in IAlarmListener listener,
// String listenerTag, in WorkSource workSource, in AlarmManager.AlarmClockInfo alarmClock);
// boolean setTime(long millis);
// void setTimeZone(String zone);
// void remove(in PendingIntent operation, in IAlarmListener listener);
// long getNextWakeFromIdleTime();
// AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
// long currentNetworkTimeMillis();
private static SystemServiceBinderHooker.HookCallback sHookCallback = new SystemServiceBinderHooker.HookCallback() {
@Override
public void onServiceMethodInvoke(Method method, Object[] args) {
MatrixLog.v(TAG, "onServiceMethodInvoke: method name %s", method.getName());
// 根据不同情况分发记录
dispatchListeners(method, args);
}
@Nullable
@Override
public Object onServiceMethodIntercept(Object receiver, Method method, Object[] args) {
return null;
}
};
private static void dispatchListeners(Method method, Object[] args) {
if (method.getName().equals("set")
//jb-release ics-mr0-release
|| method.getName().equals("setRepeating") || method.getName().equals("setInexactRepeating")) {
dispatchSet(args);
} else if (method.getName().equals("remove")) {
dispatchCancel(args);
}
}
private static void dispatchSet(Object[] args) {
// 根据参数个数拼接,每个版本的参数有可能不一样
SetArgs setArgs = SetArgsCompatible.createSetArgs(args);
if (setArgs == null) {
MatrixLog.w(TAG, "dispatchSet setArgs null");
return;
}
synchronized (AlarmManagerServiceHooker.class) {
for (int i = 0; i < sListeners.size(); i++) {
sListeners.get(i).onAlarmSet(setArgs.type, setArgs.triggerAtMillis, setArgs.windowMillis,
setArgs.intervalMillis, setArgs.flags, setArgs.operation, setArgs.onAlarmListener);
}
}
}
private static void dispatchCancel(Object[] args) {
CancelArgs cancelArgs = CancelArgsCompatible.createCancelArgs(args);
if (cancelArgs == null) {
MatrixLog.w(TAG, "dispatchCancel cancelArgs null");
return;
}
synchronized (AlarmManagerServiceHooker.class) {
for (int i = 0; i < sListeners.size(); i++) {
sListeners.get(i).onAlarmRemove(cancelArgs.operation, cancelArgs.onAlarmListener);
}
}
}
// 而 sListeners 中有最初在 AlarmMonitorFeature 类中的 onTurn 方法中放入的监听对象,最终会执行
public void onTurnOn() {
super.onTurnOn();
if (mCore.getConfig().isAmsHookEnabled) {
mListener = new AlarmManagerServiceHooker.IListener() {
@Override
public void onAlarmSet(int type, long triggerAtMillis, long windowMillis, long intervalMillis, int flags, PendingIntent operation, AlarmManager.OnAlarmListener onAlarmListener) {
String stack = "";
if (mCore.getConfig().isStatAsSample) {
// 通过抛出异常得到堆栈并记录, “at android.app.AlarmManager” 开头的异常信息行并拼接
stack = BatteryCanaryUtil.polishStack(Log.getStackTraceString(new Throwable()), "at android.app.AlarmManager");
}
AlarmRecord alarmRecord = new AlarmRecord(type, triggerAtMillis, windowMillis, intervalMillis, flags, stack);
MatrixLog.i(TAG, "#onAlarmSet, target = " + alarmRecord);
if (operation != null || onAlarmListener != null) {
int traceKey = operation != null ? operation.hashCode() : onAlarmListener.hashCode();
mAlarmTracing.onSet(traceKey, alarmRecord);
}
}
@Override
public void onAlarmRemove(PendingIntent operation, AlarmManager.OnAlarmListener onAlarmListener) {
if (operation != null || onAlarmListener != null) {
int traceKey = operation != null ? operation.hashCode() : onAlarmListener.hashCode();
mAlarmTracing.onRemove(traceKey);
}
}
};
AlarmManagerServiceHooker.addListener(mListener);
}
}
- 总结:闹钟的监控是基于动态代理闹钟服务
android.app.IAlarmManager
,记录其执行的方法。 - 闹钟监控的步骤:
- 1.反射构造闹钟服务
android.app.IAlarmManager
的本地代理,(通过执行android.app.IAlarmManager$Stub::asInterface
) - 2.动态代理
android.app.IAlarmManager
接口,当其执行方法时就记录下来并回调出去 - 3.反射提前设置
ServiceManager
中sCache
容器中的服务代理对象,当其调用getService
时直接返回自己设置的服务代理对象
- 1.反射构造闹钟服务
2. WakeLockMonitorFeature
该类监控的是IPowerManager
的acquireWakeLock
和releaseWakeLock
方法,和AlarmMonitorFeature
实现几乎一样。
-
补充
WakeLock
知识- 1.
WakeLock
可以保持 CPU 处于唤醒状态。当app息屏一段时间之后原本 CPU 就减少运行或者休眠了,使用WakeLock
机制可以使 app 息屏之后 CPU 处于运用状态 - 2.使用
<uses-permission android:name="android.permission.WAKE_LOCK" /> PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); // PowerManager.PARTIAL_WAKE_LOCK 标记 cpu开启 屏幕键盘关闭(有别的标志位可选) WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"WakelockTag"); wakeLock.acquire(); wakeLock.release();
- 1.
3.其他Feature
其他的Feature实现原理都和AlarmMonitorFeature几乎一致,都是反射出自己的系统服务本地代理并通过动态代理来记录相关函数的调用。
-
1.WifiMonitorFeature
监控的是
IWifiManager
的startScan
和getScanResults
方法 -
2.LocationMonitorFeature
监控的是
ILocationManager
的requestLocationUpdates
方法 -
3.BlueToothMonitorFeatur
监控的是
IBluetoothManager
的registerAdapter
和getBluetoothGatt
(registerScanner
startScan
startScanForIntent
)方法 -
4.NotificationMonitorFeature
监控的是
INotificationManager
的createNotificationChannels
和enqueueNotificationWithTag
方法