17.优化 - matrix-battery-canary 分析1

  在matrix-battery-canary模块中,没有一条清晰的主线可以走到底,它的结构类似与一个个的小功能组装起来,小功能之间互不影响。它的一些功能的话有流量监控、Wifi监控、WakeLock监控、任务监控、定位监控、设备监控等等。

  分析的话就从给定的 Simple 开始分析。

  • 1.配置
    在 Simple 的 Application 中首先对 BatteryMonitorPlugin 配置了一些参数
    public static BatteryMonitorPlugin createMonitor() {
        if (sBatteryConfig != null) {
            throw new IllegalStateException("Duplicated init!");
        }

        sBatteryConfig = new BatteryMonitorConfig.Builder()
                // Thread Activities Monitor
                .enable(JiffiesMonitorFeature.class)  // Task 1
                .enableStatPidProc(true)
                .greyJiffiesTime(3 * 1000L)
                .enableBackgroundMode(false)
                .backgroundLoopCheckTime(30 * 60 * 1000L)
                .enableForegroundMode(true)
                .foregroundLoopCheckTime(20 * 60 * 1000L)
                .setBgThreadWatchingLimit(5000)
                .setBgThreadWatchingLimit(8000)

                // App & Device Status Monitor For Better Invalid Battery Activities Configure
                .setOverHeatCount(1024)
                .enable(DeviceStatMonitorFeature.class)  // Task 2
                .enable(AppStatMonitorFeature.class)  // Task 3
                .setSceneSupplier(new Callable<String>() {
                    @Override
                    public String call() {
                        return "Current AppScene";
                    }
                })

                // AMS Activities Monitor:
                // alarm/wakelock watch
                .enableAmsHook(true)  // Task 4
                .enable(AlarmMonitorFeature.class)  // Task 5
                .enable(WakeLockMonitorFeature.class)  // Task 6
                .wakelockTimeout(2 * 60 * 1000L)
                .wakelockWarnCount(3)
                .addWakeLockWhiteList("Ignore WakeLock TAG1")
                .addWakeLockWhiteList("Ignore WakeLock TAG2")
                // scanning watch (wifi/gps/bluetooth)
                .enable(WifiMonitorFeature.class)  // Task 7
                .enable(LocationMonitorFeature.class)  // Task 8
                .enable(BlueToothMonitorFeature.class)  // Task 9
                // .enable(NotificationMonitorFeature.class)  // Task 10

                // Lab Feature:
                // network monitor
                // looper task monitor
                .enable(TrafficMonitorFeature.class)  // Task 11
                .enable(LooperTaskMonitorFeature.class)  // Task 12
                .addLooperWatchList("main")
                .useThreadClock(false)
                .enableAggressive(true)

                // Monitor Callback
                .setCallback(new BatteryStatsListener())
                .build();

        return new BatteryMonitorPlugin(sBatteryConfig);
    }

matrix-battery-canary模块功能也主要是由注释中的 Task n 组成的。

  • 2.初始化和启动
        // 实例化 BatteryMonitorPlugin
       Plugin plugin = Matrix.with().getPluginByClass(BatteryMonitorPlugin.class);
       if (!plugin.isPluginStarted()) {
           if (!BatteryEventDelegate.isInit()) {
               BatteryEventDelegate.init(this.getApplication());
           }

           MatrixLog.i(TAG, "plugin-battery start");
           // 启动子任务开始监控
           plugin.start();
       }
public class BatteryMonitorPlugin extends Plugin {
    public BatteryMonitorPlugin(BatteryMonitorConfig config) {
        // 逻辑都在 BatteryMonitorCore 中,config 就是上面的配置
        mDelegate = new BatteryMonitorCore(config);
        MatrixLog.i(TAG, "setUp battery monitor plugin with configs: " + config);
    }
    @Override
    public void init(Application app, PluginListener listener) {
        super.init(app, listener);
        if (!mDelegate.getConfig().isBuiltinForegroundNotifyEnabled) {
            AppActiveMatrixDelegate.INSTANCE.removeListener(this);
        }
    }

    @Override
    public String getTag() {
        return "BatteryMonitorPlugin";
    }

    @Override
    public void start() {
        super.start();
        // 开始监控
        mDelegate.start();
    }

    @Override
    public void stop() {
        super.stop();
        // 开始监控
        mDelegate.stop();
    }
    @Override
    public void onForeground(boolean isForeground) {
        mDelegate.onForeground(isForeground);
    }

}
public class BatteryMonitorCore {

    private static final String TAG = "Matrix.battery.BatteryMonitorCore";

    private class BackgroundLoopCheckTask implements Runnable {
        int round = 0;
        @Override
        public void run() {
            round++;
            MatrixLog.i(TAG, "#onBackgroundLoopCheck, round = " + round);
            if (!isForeground()) {
                synchronized (BatteryMonitorCore.class) {
                    for (MonitorFeature plugin : mConfig.features) {
                        plugin.onBackgroundCheck(mBgLooperMillis * round);
                    }
                }
            }
            if (!isForeground()) {
                mHandler.postDelayed(this, mBgLooperMillis);
            }
        }
    }

    @SuppressLint("VisibleForTests")
    public BatteryMonitorCore(BatteryMonitorConfig config) {
        mConfig = config;
        // 给每一个小任务配置数据
        //  config.features 即上面配置的 Task1、Task2  也就是 JiffiesMonitorFeature、DeviceStatMonitorFeature 等
        for (MonitorFeature plugin : config.features) {
            plugin.configure(this);
        }
    }

    public void start() {
        synchronized (BatteryMonitorCore.class) {
            if (!mTurnOn) {
                //  config.features 即上面配置的 Task1、Task2  也就是 JiffiesMonitorFeature、DeviceStatMonitorFeature 等
                for (MonitorFeature plugin : mConfig.features) {
                    // 开始监控
                    plugin.onTurnOn();
                }
                mTurnOn = true;
            }
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mWorkerTid = Process.myTid();
                }
            });

            if (BatteryEventDelegate.isInit()) {
                // 通过广播来监听系统的 屏幕状态(息屏、亮屏),电池状态(充电、不充电),发生状态更改时会通知观察者们
                BatteryEventDelegate.getInstance().attach(this).startListening();
            }
        }
    }

    public void stop() {
        synchronized (BatteryMonitorCore.class) {
            if (mTurnOn) {
                mHandler.removeCallbacksAndMessages(null);
                for (MonitorFeature plugin : mConfig.features) {
                    // 开始监控
                    plugin.onTurnOff();
                }
                mTurnOn = false;
            }
        }
    }

    @WorkerThread
    @Nullable
    public TaskJiffiesSnapshot configureMonitorConsuming() {
        if (Looper.myLooper() == Looper.getMainLooper() || Looper.myLooper() == mHandler.getLooper()) {
            throw new IllegalStateException("'#configureMonitorConsuming' should work within worker thread except matrix thread!");
        }

        if (mWorkerTid > 0) {
            MatrixLog.i(TAG, "#configureMonitorConsuming, tid = " + mWorkerTid);
            TaskJiffiesSnapshot snapshot = createSnapshot(mWorkerTid);  // app phone 是否在前后台   mWorkerTid 的信息(运行时间等 /proc/pid/task/tid/... )
            if (snapshot != null) {
                if (mLastInternalSnapshot != null) {
                    Delta<TaskJiffiesSnapshot> delta = snapshot.diff(mLastInternalSnapshot);
                    getConfig().callback.onReportInternalJiffies(delta);  //比较二次 snapshot 的信息,是不是在充电,前后台等信息
                }
                mLastInternalSnapshot = snapshot;
                return snapshot;
            }
        }
        return null;
    }

    public void onForeground(boolean isForeground) {
        if (!Matrix.isInstalled()) {
            MatrixLog.e(TAG, "Matrix was not installed yet, just ignore the event");
            return;
        }
        mAppForeground = isForeground;

        if (BatteryEventDelegate.isInit()) {
            BatteryEventDelegate.getInstance().onForeground(isForeground);
        }
      
        if (!isForeground) { // app 运行在后台
            // back:
            // 1. remove all checks
            mHandler.removeCallbacksAndMessages(null);

            // 2. start background jiffies check
            Message message = Message.obtain(mHandler);
            message.what = MSG_ID_JIFFIES_START;
            mHandler.sendMessageDelayed(message, mMonitorDelayMillis);

            // 3. start background loop check task
            if (mBackgroundModeEnabled) {
                if (mBgLooperTask != null) {
                    mHandler.removeCallbacks(mBgLooperTask);
                    mBgLooperTask = null;
                }
                mBgLooperTask = new BackgroundLoopCheckTask();
                // mBgLooperTask 某些 task 需要 app 在后台是也监控其数据如 AppStatMonitorFeature 、WakeLockMonitorFeature
                mHandler.postDelayed(mBgLooperTask, mBgLooperMillis);
            }

        } else if (!mHandler.hasMessages(MSG_ID_JIFFIES_START)) { // message.what = MSG_ID_JIFFIES_END 时进入,即下方的 message 没有执行完时。
            // fore:
            // 1. remove background loop task
            if (mBgLooperTask != null) {
                mHandler.removeCallbacks(mBgLooperTask);
                mBgLooperTask = null;
            }

            // 2. finish background jiffies check
            Message message = Message.obtain(mHandler);
            message.what = MSG_ID_JIFFIES_END;
            mHandler.sendMessageAtFrontOfQueue(message);

            // 3. start foreground jiffies loop check
            if (mForegroundModeEnabled && mFgLooperTask != null) {
                mHandler.removeCallbacks(mFgLooperTask);
                mFgLooperTask.lastWhat = MSG_ID_JIFFIES_START;
                mHandler.post(mFgLooperTask);
            }
        }

        for (MonitorFeature plugin : mConfig.features) {
            plugin.onForeground(isForeground);
        }
    }
    // 获取电池温度
    public int getCurrentBatteryTemperature(Context context) {
        try {
            return BatteryCanaryUtil.getBatteryTemperature(context);  //电池温度
        } catch (Throwable e) {
            MatrixLog.printErrStackTrace(TAG, e, "#currentBatteryTemperature error");
            return 0;
        }
    }


    @Nullable
    // 获取手机的设备信息
    protected TaskJiffiesSnapshot createSnapshot(int tid) {
        TaskJiffiesSnapshot snapshot = new TaskJiffiesSnapshot();
        snapshot.tid = tid;
        snapshot.appStat = BatteryCanaryUtil.getAppStat(getContext(), isForeground());  // 设备是否在前台 后台服务 后台
        snapshot.devStat = BatteryCanaryUtil.getDeviceStat(getContext());  // 设备是否在 充电 熄屏 省电模式
        try {
            Callable<String> supplier = getConfig().onSceneSupplier;
            snapshot.scene = supplier == null ? "" : supplier.call();
        } catch (Exception ignored) {
            snapshot.scene = "";
        }
         // app 进程即线程状态,通过读 /proc/pid/stat 和  /proc/pid/task/tid/stat 文件里面的信息,
         // 主要是得到 app 运行的进程、线程名,app 运行时和 app 内线程的用户时间、系统时间、等待的系统时间和用户时间
        ProcStatUtil.ProcStat stat = ProcStatUtil.of(Process.myPid(), tid); 
        if (stat == null) {
            return null;
        }
        snapshot.jiffies = DigitEntry.of(stat.getJiffies());
        snapshot.name = stat.comm;
        return snapshot;
    }
}

  • 小知识点:
  1. /proc/pid/stat :pid 进程的信息
  2. /proc/pid/task/ :pid 进程中所有的 tid 线程 id
  3. /proc/pid/task/tid/stat :pid 进程的 tid 线程的信息
  4. /proc/pid/maps:pid 进程的 mmap 信息
  5. ...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容