前回はアプリ起動時に実行されるActivityから順に処理を追っていたが、プログラムがデコンパイルしたソースということもあり順に追っていくのは大変そうなのでアプローチを変えてみる。
/proc/以下や /sys/以下のハードウェア情報にアクセスしてると予想できるのでソースファイルの入ったフォルダで文字列検索
$ grep -R "/proc/" ../../PerfMon-v1.21-java/sources/eu/chainfire/perfmon/
../../PerfMon-v1.21-java/sources/eu/chainfire/perfmon/ac.java: BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/stat"));
../../PerfMon-v1.21-java/sources/eu/chainfire/perfmon/ac.java: StringTokenizer stringTokenizer = new StringTokenizer(new BufferedReader(new FileReader(String.format("/proc/%d/stat", new Object[]{Integer.valueOf(iArr[i5])}))).readLine());
../../PerfMon-v1.21-java/sources/eu/chainfire/perfmon/ac.java: BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/net/dev"));
ac.javaだけヒットした。このファイルを開いてみた。
for (int i = 0; i < 256; i++) {
if (new File("/sys/devices/system/cpu/cpu" + String.valueOf(i)).exists() && i + 1 > this.a) {
this.a = i + 1;
}
}
まずはコンストラクタにあるこのコード。/sys/devices/system/cpu/下にあるcpu0,cpu1,cpu2...というフォルダを数えることでコア数を数えている。
![]() |
Android10でのPerfMon |
コア数を数えることはできているようだ。
BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/stat"));
for (String readLine = bufferedReader.readLine(); readLine != null; readLine = bufferedReader.readLine()) {
if (readLine.startsWith("cpu")) {
次にこのコード。/proc/statの中身を読んでそれぞれの数値を抽出してる部分である。
ファイルの中身を読むbuffereReaderをsudo cat /proc/statの出力ストリームに変えればよさそうである。
while (i <= this.a) {
try {
agVarArr[i].j = a(String.format("/sys/devices/system/cpu/%s/cpufreq/scaling_min_freq", new Object[]{agVarArr[i].a}), 0);
if (agVarArr[i].j == 0) {
agVarArr[i].j = a(String.format("/sys/devices/system/cpu/%s/cpufreq/cpuinfo_min_freq", new Object[]{agVarArr[i].a}), 0);
}
agVarArr[i].k = a(String.format("/sys/devices/system/cpu/%s/cpufreq/scaling_cur_freq", new Object[]{agVarArr[i].a}), 0);
if (agVarArr[i].k == 0) {
agVarArr[i].k = a(String.format("/sys/devices/system/cpu/%s/cpufreq/cpuinfo_cur_freq", new Object[]{agVarArr[i].a}), 0);
}
agVarArr[i].l = a(String.format("/sys/devices/system/cpu/%s/cpufreq/scaling_max_freq", new Object[]{agVarArr[i].a}), 0);
if (agVarArr[i].l == 0) {
agVarArr[i].l = a(String.format("/sys/devices/system/cpu/%s/cpufreq/cpuinfo_max_freq", new Object[]{agVarArr[i].a}), 0);
}
agVarArr[0].j = Math.max(agVarArr[0].j, agVarArr[i].j);
agVarArr[0].k = Math.max(agVarArr[0].k, agVarArr[i].k);
agVarArr[0].l = Math.max(agVarArr[0].l, agVarArr[i].l);
i++;
} catch (Exception e3) {
}
}
/sys/devices/system/cpu/cpu[0-9]/cpufreq/は各コアの動作クロックの情報がある。a()という関数にかけてるのでa()を見てみる。
private int a(String str, int i) {
try {
return Integer.parseInt(new BufferedReader(new FileReader(str)).readLine(), 10);
} catch (Exception e2) {
return i;
}
}
/proc/statを読む部分と同じである。この部分もsuを使えば良さそうである。
Patch
実際にsuを使ったコードを書いてみる
public static BufferedReader sudoCat(String filename){
Process p;
BufferedReader reader;
try {
p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes("cat "+filename+"\n");
os.writeBytes("exit\n");
os.flush();
p.waitFor();
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
reader = new BufferedReader(new StringReader("error"));
}
return reader;
}
このsudoCatメソッドをFileReaderの代わりに使えば良さそう。
さて、変更を加えたこのソースをビルドしたいのだがAndroidStudioのプロジェクトとして開くにはフォルダの構造が違いすぎる。apkのフォルダ構造をAndroidStudioのプロジェクトとして開くプラグインもコンバーターのようなツールも私の知る限りでは存在しない。
なのでapktoolを使う方が楽である。smaliで先ほど書いたsudoCatを書き、FileReaderが使われているところに置換する。ちなみにsmaliとはdalvikバイトコードのアセンブリである。
5行程度だったa()メソッドはsmaliでは以下のようになる。
.method private a(Ljava/lang/String;I)I
.locals 2
:try_start_0
new-instance v0, Ljava/io/BufferedReader;
new-instance v1, Ljava/io/FileReader;
invoke-direct {v1, p1}, Ljava/io/FileReader;->(Ljava/lang/String;)V
invoke-direct {v0, v1}, Ljava/io/BufferedReader;->(Ljava/io/Reader;)V
invoke-virtual {v0}, Ljava/io/BufferedReader;->readLine()Ljava/lang/String;
move-result-object v0
const/16 v1, 0xa
invoke-static {v0, v1}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;I)I
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
move-result p2
:goto_0
return p2
:catch_0
move-exception v0
goto :goto_0
.end method
続く
No comments:
Post a Comment