基于spi接口的oled屏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);

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},

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值