瑞芯微Rockchip开发者社区
直播中

申换换

7年用户 1529经验值
私信 关注
[问答]

求助apk要怎么使用基于rk3288 Android的硬件访问框架呢

上一篇写了一个oled驱动,那么现在有一个问题:apk要怎么使用这个硬件,这里就需要提供一个硬件服务,apk通过这个服务就可以操作到硬件了。
基于rk3288 Android5.1
Android的硬件访问框架
1、loadLibrary 加载硬件
2、JNIOnload 注册本地方法
分别调用各个硬件的函数来注册本地方法
{
LED
振动器
串口
}
3、SystemServer对每一个硬件:构造Service、addService
4、APP怎么使用?
获得服务:getService
使用服务:执行Service方法
具体步骤:
1、实现JNI和HAL文件
对于oeld,写一个com_android_server_NoyaManager.cpp,注册一个JNI本地方法,在hal_oled.c文件里面调用:open,read,write。
   static const JNINativeMethod methods[] = {
    {"native_oled_close", "()V", (void *)oled_close},
    {"native_oled_init", "()I", (void *)oled_init},
    {"native_oled_clear", "()I", (void *)oled_clear},
    {"native_oled_display", "(IILjava/lang/String;)I", (void *)oled_display},
    };
    int register_android_server_NoyaManager(JNIEnv *env)
    {
        return jniRegisterNativeMethods(env, "com/android/server/noya/NoyaManagerServiceImpl",
                methods, NELEM(methods));
    }
2、修改onload.cpp,让他调用com_android_server_NoyaManager.cpp实现的函数
int register_android_server_NoyaManager(JNIEnv *env);
1
3、修改SystemServer.java:
mSystemServiceManager.startService(”noya_service“);
4、 NoyaManagerServiceImpl.java 、 NoyaManagerService.java:实现本地方法
在NoyaManagerService里面new一个NoyaManagerServiceImpl对象,以后就通过这个对象操作oled
public final class NoyaManagerService extends SystemService {
    private static final String TAG = "NoyaManagerService";
    final NoyaManagerServiceImpl mImpl;
    public NoyaManagerService(Context context) {
        super(context);
        mImpl = new NoyaManagerServiceImpl(context);
    }
    @Override
    public void onStart() {
        Log.i(TAG, "Registering service " + Context.NOYA_SERVICE);
        publishBinderService(Context.NOYA_SERVICE, mImpl);
    }
    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            mImpl.start();
        }
    }
}
服务的具体实现类部分
public class NoyaManagerServiceImpl extends INoyaManager.Stub {
    private static final String TAG = "NoyaManagerServiceImpl";
public int oled_init() throws android.os.RemoteException
{
return native_oled_init();
}
public int oled_clear(int page) throws android.os.RemoteException
{
return native_oled_clear();
}
public int oled_display(int page, int col, java.lang.String str) throws android.os.RemoteException
{
return native_oled_display(page, col, str);
}
public void oled_close() throws android.os.RemoteException
{
native_oled_close();
}
public static native int native_oled_init();
public static native int native_oled_clear();
public static native int native_oled_display(int page, int col, java.lang.String str);
public static native void native_oled_close();
    public void start() {
        Log.i(TAG, "Starting NoyaManager Service");
        HandlerThread handlerThread = new HandlerThread("NoyaManagerServiceThread");
        handlerThread.start();
    }
}
5、INoyaManager.java:接口文件,由INoyaManager.aidl文件提供,自动生成的文件,给APP使用
interface INoyaManager {
        void reboot(boolean confirm,String reason);
        int oled_init();
        int oled_clear(int page);
        int oled_display(int page, int col, String str);
        void oled_close();
    }
6、NoyaManager.java:在里面通过INoyaManager.java的接口调用服务。
public class NoyaManager {
    private static String TAG = "NoyaManager";
    INoyaManager mNoyaManager;
    private Context context;
    public NoyaManager(Context ctx,INoyaManager noyaManager) {
        mNoyaManager = noyaManager;
        context = ctx;
    }
    public int oled_init()
{
int ret = -1;
        try {
            ret = mNoyaManager.oled_init();
        } catch (RemoteException e) {
        }
return ret;
}
    public int oled_clear(int page)
{
int ret = -1;
        try {
            ret = mNoyaManager.oled_clear(page);
        } catch (RemoteException e) {
        }
return ret;
}
    public int oled_display(int page, int col, String str)
{
int ret = -1;
        try {
            ret = mNoyaManager.oled_display(page, col, str);
        } catch (RemoteException e) {
        }
return ret;
}
    public void oled_close()
{
        try {
            mNoyaManager.oled_close();
        } catch (RemoteException e) {
        }
}
}
使用时:
NoyaManager mNoyaManager = (NoyaManager)mContext.getSystemService("noya_service");
mNoyaManager.oled_init();
权限问题:
对于新增加的设备节点,默认是没有访问权限的,所以必须要添加相应的权限:
在SElinux下,如何获得对一个内核节点的访问权限
android/external/sepolicy/file_contexts 添加
/dev/oled               u:object_r:oled_device:s0
android/external/sepolicy/device.te 添加
type oled_device, dev_type, mlstrustedobject;
android/external/sepolicy/untrusted_app.te 添加
allow untrusted_app oled_device:chr_file rw_file_perms;
device/rockchip/common/sepolicy/service_contexts 添加
noya_service               u:object_r:system_server_service:s0
system/core/rootdir/ueventd.rc 这个文件修改后需要重新编译,或者只需要修改out/target/produt/xxx/root/ueventd.rc 添加
/dev/oled                 0666   root       root
调试时出现的问题:
shell@firefly:/ # [ 625.582296] type=1400 audit(1293885273.400:14): avc: denied { read write } for pid=1114 comm=“Binder_B” name=“oled” dev=“tmpfs” ino=1270 scontext=u:r:system_server:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
[ 625.582313] drivers/spi/rk_spi_oled_drv.c, oled_ioctl, 139, cmd=0x00100001, arg=0xa93840d8
[ 625.582402] Division by zero in kernel.
[ 625.582426] CPU: 3 PID: 24 Comm: ksoftirqd/3 Tainted: P 3.10.0 #43
[ 625.582467] [] (unwind_backtrace+0x0/0xe0) from [] (show_stack+0x10/0x14)
[ 625.582497] [] (show_stack+0x10/0x14) from [] (Ldiv0+0x8/0x10)
[ 625.582526] [] (Ldiv0+0x8/0x10) from [] (pump_transfers+0x4c/0x690)
[ 625.582555] [] (pump_transfers+0x4c/0x690) from [] (tasklet_action+0x80/0xe0)
[ 625.582580] [] (tasklet_action+0x80/0xe0) from [] (__do_softirq+0x144/0x2b4)
[ 625.582605] [] (__do_softirq+0x144/0x2b4) from [] (run_ksoftirqd+0x30/0x78)
[ 625.582632] [] (run_ksoftirqd+0x30/0x78) from [] (smpboot_thread_fn+0x22c/0x234)
[ 625.582662] [] (smpboot_thread_fn+0x22c/0x234) from [] (kthread+0xa0/0xac)
[ 625.582692] [] (kthread+0xa0/0xac) from [] (ret_from_fork+0x14/0x3c)
[ 625.582709] MRST SPI0: unsupportedfreq: 48000000Hz
spi设备支持的最大频率设置错误,该成datesheet里的典型值即可
JNI文件里的oled_clear的参数没有传进去,后来发现是本地方法定义了无参的函数
JNI文件
{“native_oled_clear”, “()I”, (void *)oled_clear},
改为
{“native_oled_clear”, “(I)I”, (void *)oled_clear},

原作者:风见暗含

回帖(1)

王莉

2022-5-14 11:50:09
举报

更多回帖

发帖
×
20
完善资料,
赚取积分