android shell hello world,Android Framework 之HelloWorld(三)
本來是要寫一個linux驅動,用于控制led燈的,但考慮到nanopc-T4的內核已經幫我們配置好設備樹,已經可以利用/sys/class/gpio操作gpio了,所以沒必要再造輪子了!
在shell里,可以利用下面的命令控制Led燈的亮與滅:
#導出GPIO0_A0管腳
echo 32 > /sys/class/gpio/export
#讓GPIO0_A0管腳作為輸出使用
echo?out > /sys/class/gpio/gpio32/direction
#GPIO0_A0輸出高電平
echo 1?> /sys/class/gpio/gpio32/value
#GPIO0_A0輸出低電平
echo 0 > /sys/class/gpio/gpio32/value
接上串口或者adb shell進去shell終端,先來看下export的用戶和組:
nanopc-t4:/ $ ls -l /sys/class/gpio/
total 0
--w--w---- 1 root system 4096 2020-08-22 04:50 export
lrwxrwxrwx 1 root root 0 2020-08-22 07:48 gpio156 -> ../../devices/platform/pinctrl/gpio/gpio156
lrwxrwxrwx 1 root root 0 2020-08-22 07:48 gpiochip0 -> ../../devices/platform/pinctrl/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 2020-08-22 07:48 gpiochip128 -> ../../devices/platform/pinctrl/gpio/gpiochip128
lrwxrwxrwx 1 root root 0 2020-08-22 07:48 gpiochip32 -> ../../devices/platform/pinctrl/gpio/gpiochip32
lrwxrwxrwx 1 root root 0 2020-08-22 07:48 gpiochip64 -> ../../devices/platform/pinctrl/gpio/gpiochip64
lrwxrwxrwx 1 root root 0 2020-08-22 07:48 gpiochip96 -> ../../devices/platform/pinctrl/gpio/gpiochip96
--w--w---- 1 root system 4096 2020-08-22 04:50 unexport
可以看出,export是普通文件,擁有者具有“寫”權限,組內其他成員具有“寫”權限,其他用戶則沒有任何權限,export屬于root用戶,所屬組為system。
android8.1定義了很多用戶,我們可以在shell里使用“ps -ef”,隨機截取了幾個就有root,shell,system、u0_a59等用戶了。
#隨機截取了幾個
$ps -ef
...
webview_zygote 660 1 0 04:50:44 ? 00:00:00 webview_zygote32
radio 689 363 0 04:50:44 ? 00:00:00 com.android.phone
system 1120 363 0 04:50:48 ? 00:00:00 android.rockchip.update.service
root 3694 1 0 05:08:17 ? 00:00:03 adbd --root_seclabel=u:r:su:s0
root 13893 3694 0 07:45:05 136:0 00:00:00 logcat -v long -v epoch
u0_a59 13962 363 1 07:45:22 ? 00:00:02 com.demo.helloworld
shell 14478 14087 36 07:53:04 ttyFIQ0 00:00:00 ps -ef
...
所以我們要操作/sys/class/gpio/export,至少也要將app提升至system用戶權限,apk在安裝時,會根據(jù)AndroidManifest.xml的android:sharedUserId="android.uid.system"屬性進行分配用戶權限,查了一些資料,如果要讓app具有system權限,有兩種方法,一是將app放進android源碼上使用mm DEX_PREOPT_DEFAULT=nostripping編譯,還有就是使用簽名,我們這里使用簽名的方式:
先設置AndroidManifest.xml的android:sharedUserId="android.uid.system"屬性
在編譯android源碼后,在此處得到如下文件:
./build/make/target/product/security/platform.pk8
./build/make/target/product/security/platform.x509.pem
每次編譯android源碼這兩個文件都不變,可以拷貝出來使用。
而signapk.jar則存在于這兩個地方:
./out/host/linux-x86/framework/signapk.jar和./prebuilts/sdk/tools/lib/signapk.jar,這兩個signapk.jar的區(qū)別我不清楚,不過猜測使用前者會好一點,畢竟是編譯輸出的。
把上面的三個文件拷貝出來,如果使用./out/host/linux-x86/framework/signapk.jar,則使用如下命令生成簽名后的apk安裝包:
java -Djava.library.path=rk3399-android-8.1/out/host/linux-x86/lib64 -jar signapk.jar platform.x509.pem platform.pk8 app-debug.apk system.apk
如果使用./prebuilts/sdk/tools/lib/signapk.jar,則使用如下命令生成簽名后的apk安裝包:
java -Djava.library.path=../rk3399-android-8.1/prebuilts/sdk/tools/linux/lib64/ -jar signapk.jar platform.x509.pem platform.pk8 app-debug.apk system.apk
我在ibledctrl.so里加入WriteFileValue()函數(shù)用于操作gpio:
#include
#include
static int WriteFileValue(const char *pPath, char *pValue, int len)
{
int fd = -1;
if(!pPath || !pValue)
{
return -1;
}
PRINT_DEBUG("open %s value = %s, len = %d", pPath, pValue, len);
fd = open(pPath, O_RDWR);
if (fd < 0)
{
PRINT_DEBUG("open %s error: %d,%s", pPath, fd, strerror(errno));
return fd;
}
if (len != write(fd, pValue, len))
{
PRINT_DEBUG("write error: %d,%s", fd, strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}
jint LedInit(JNIEnv *env, jobject cls)
{
PRINT_DEBUG("Entry LedInit ...");
char *export = "32";
char *direction = "out";
WriteFileValue("/sys/class/gpio/export", export, strlen(export)+1);
WriteFileValue("/sys/class/gpio/gpio32/direction", direction, strlen(direction)+1);
return 0;
}
可惜的是,即使app以system用戶運行也沒權限操控/sys/class/gpio/export,使用chown system:system /sys/class/gpio/export使之處于同一“owner”也不夠權限。可能是SElinux的權限管理問題,android源碼中允許對某些驅動文件節(jié)點進行更細化的權限管理,這塊我還需要好好學習。因為我使用下面的命令"whoami”或者“dumpsys activity top”獲取到當前界面所處用戶確實是system用戶了,這說明使用簽名的方式提升到system權限是沒問題的:
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
private void Run(String cmd)
{
try {
Process process = Runtime.getRuntime().exec("sh"); //su
// 獲取輸出流
OutputStream outputStream = process.getOutputStream();
InputStream is = process.getInputStream();
InputStream es = process.getErrorStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeBytes(cmd);
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
int code = process.waitFor();
Log.d("TAG", "Run:\"" + cmd +"\", "+"process.waitFor() = " + code);
String line;
BufferedReader br;
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while ((line = br.readLine()) != null) {
Log.d("TAG", line);
}
br = new BufferedReader(new InputStreamReader(es, "UTF-8"));
while ((line = br.readLine()) != null) {
Log.e("TAG", line);
}
} catch (Throwable t) {
Log.e("TAG", "Throwable = " + t.getMessage());
t.printStackTrace();
}
}
...
...
Run("whoami"); //獲取當前進程是屬于哪個用戶
//或者在shell中使用dumpsys
我發(fā)現(xiàn)如果在root用戶下預先運行chmod 777 /sys/class/gpio/export和chown system:system /sys/class/gpio/export命令后,再重啟app,就能操控led燈了,這我就不理解了。
如你所見,這個HelloWorld是失敗的,沒能達到要求,同時在android的權限管理方面沒能解釋清楚!
來源:oschina
鏈接:https://my.oschina.net/u/4345458/blog/4525802
總結
以上是生活随笔為你收集整理的android shell hello world,Android Framework 之HelloWorld(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android miui9.0改装条例,
- 下一篇: 语音聊天室 html,聊天室 - HTM