千里马android binder深入分析-承上启下的native层(客户端部分)

Android下在C++环境实现native层binder服务 此文章主要目的:在Android 6.0环境下使用C++编程实现binder通讯服务端和客户端 1.在Android源码目录下存放代码树形结构 jack_server/ ├── Android.mk ├── log.h ├── service │   ├── Android.mk │   ├── JACK_Service.cpp │   └── JACK_Service.h 阅读详情

csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论

android跨进程通信实战视频课程(加群获取优惠)
image.png
相信大家对上面这一副binder跨进程通信的图都应该比较熟悉,图中的主要有4个角色:
1、客户端(A进程)
2、SerivceManager
3、服务端(B进程)
4、binder驱动
平时一问到binder是怎么跨进程通信的?那么同学们肯定大部分回答:binder最后调到底层还是通过binder驱动来实现跨进程通信的。那么这里就要问一下:请问android中app的java层binder调用,是怎么一步步调用到了底层binder驱动呢?
image.png
这个中间问号部分也就本节要给大家重点分享的部分。
##1.ServiceManager方法调用也是binder跨进程通信
跨进程通信那么必然会出现有两端,即客户端和服务端这样的C/S模型,那么问题是C端怎么知道的S端?那么这就会引出一个重要的角色ServiceManager,ServiceManager本身工作相对简单,其功能:查询和注册服务。客户端通过ServiceManager查询到了注册服务后,才可以进行跨进程通信,这里就是常说的ServiceManager像个DNS服务器。但问题来了,ServiceManager本身自己就是一个独立进程,那么客户端去SerivceManager中查询服务也肯定是跨进程通信,所以本节分析跨进程通信时就拿ServiceManager.getService这个跨进程调用来展开分析。

##2.ServiceManager接口获取分析
平时系统中获取某一个服务,一般都是最后都是ServiceManager.getService这种方式,来看看它的源码:

//ServiceManager.java中
    public static IBinder getService(String name) {
        try {
        	//缓存中获取,第一次缓存没有
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
            	//Binder.allowBlocking仅仅是为了提示是否为阻塞行接口,没有实际干活
                return Binder.allowBlocking(getIServiceManager().getService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

这里大家可以看到实际真正干活的是getIServiceManager().getService(name),这里首先来看getIServiceManager()方法:

//ServiceManager.java中
   private static IServiceManager getIServiceManager() {
      //这里有一个sServiceManager来缓存,但是第一次肯定还为null
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // 这里用调用了ServiceManagerNative类的asInterface方法和BinderInternal.getContextObject()方法
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

这里又调用到了ServiceManagerNative类的asInterface方法这方法本身应该在应用写aidl生成的java文件中也经常见到:

//ServiceManagerNative.java
  static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        //其实就是 new ServiceManagerProxy代理对象,参数是IBinder 类型的对象
        return new ServiceManagerProxy(obj);
    }

它的核心就是new ServiceManagerProxy,但是真正干活的还是IBinder参数,参数getIServiceManager方法中可以看出获取其实是核心是BinderInternal.getContextObject()方法,但getContextObject是个native的方法,所以就得看对应的jni方法:

//android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
   //调用getContextObject构造出一个IBinder类型对象
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    //把C++层面的IBinder类型对象转成java成的IBinder对象
    return javaObjectForIBinder(env, b);
}

这里一共才2行代码,那就一行行深入分析,首先来看ProcessState::self()->getContextObject:

//ProcessState.cpp
//这里直接就没有使用传递来的参数,本身传递来的也是个NULL
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

ProcessState这里又调用了getStrongProxyForHandle方法,而且传递了一个参数0:

//ProcessState.cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);
   //根据handle查询handle_entry对象,handle没有初始化过则构造一个handle_entry空壳出来
    handle_entry* e = lookupHandleLocked(handle);
  //因为handle_entry已经有了,只不过是一个空壳里面内容都为空
    if (e != NULL) {
        IBinder* b = e->binder;
      //这里e->binder第一次肯定为空
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
          //如果传入handle为0
            if (handle == 0) {
                Parcel data;
               //这里会调用 IPCThreadState::self()->transact方法来传递一个PING_TRANSACTION,主要目的
               //是为了试探ServiceManager是否还存活
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            //利用handle值构造出一个BpBinder对象,最后返回也是这个BpBinder对象
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}

到这里我们就看到了最后其实就是new BpBinder(handle);,这里handle就是我们经常说 “引用”,即对远程对象的引用,这里因为ServiceManager的的特殊性,所以android系统中默认把任何进程对ServiceManager的引用handle值都设置为固定的0。那么到这里就分析完了ProcessState::self()->getContextObject(NULL)了,返回的其实就是个new BpBinder(0),但是这里还是C++层的BpBinder对象,而我们是要获取Java层的IBinder类型的对象,那接下来就要分析上面剩下的 javaObjectForIBinder(env, b):

//android_util_Binder.cpp
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
        //省略部分
	//这里构造出了gBinderProxyOffsets的java对象
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        // The proxy holds a reference to the native object.
      //这里吧val这个c++的对象指针设置到gBinderProxyOffsets.mObject这个java属性中
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        // The native object needs to hold a weak reference back to the
        // proxy, so we can retrieve the same proxy if it is still active.
        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        //前面只是基于val建立对应的java对象,及java对象可以直接拿到val指针
       //但是我们进程也需要val指针可以获取到java对象
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

     //省略部分
    }

    return object;
}

这里面gBinderProxyOffsets相关的是什么呢?这里再来看它的对应初始化代码:

//android_util_Binder.cpp
const char* const kBinderProxyPathName = "android/os/BinderProxy";

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, "java/lang/Error");
    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
  //通过jni找出android/os/BinderProxy这个java类
    clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
  //通过jni找出android/os/BinderProxy这个java类的构造方法
    gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
    gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
            "(Landroid/os/IBinder$DeathRecipient;)V");
///通过jni找出android/os/BinderProxy这个java类的mObject 属性
    gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
//省略部分
}

这里面可以看出其实都是通过jni相关方法,让native的相关变量与java层的BinderProxy相绑定一起,到这里就可以看出在BinderProxy是在native层面被构造出来的,设置了它的mObject值就是c++层的BpBinder指针,那么到这里就已经分析完了开始的getIServiceManager方法,这个时候就有了ServiceManager的Proxy代理,总结以下几点核心部分:
1、ServiceManager特殊,它的handle固定为0,native层直接进行new BpBinder(0)
2、native层面的BpBinder需要转换成Java层的BinderProxy,这个需要native通过jni构造出java层对应的BinderProxy,且BinderProxy的mObject值就是BpBinder(0)的指针,mObject也是Java层面与native层面进行互通的最关键纽带

image.png

##3.getService获取远程服务代理的源码分析
首先来看ServiceManagerNative.java中的ServiceManagerProxy类中的getService

//ServiceManagerNative.java
    public IBinder getService(String name) throws RemoteException {
         //准备输入和返回Parcel对象
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
      //这里已经知道mRemote其实就是前面分析构造出来的BinderProxy对象
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
      //读取返回的IBinder数据
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

这里其实核心就是 mRemote.transact和 reply.readStrongBinder两个部分,这里先来分析transact部分,
这个mRemote对象是BinderProxy对象,所以来看BinderProxy类的transact方法,注意这里BinderProxy没有单独java文件,它在Binder.java文件中:

//Binder.java
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
//省略
        try {
            return transactNative(code, data, reply, flags);
        } finally {
           //省略
        }
    }

这里其实又是调用了一个native方法transactNative,注意这里transactNative到android_os_BinderProxy_transact是有一个转换关系的,这个在分析android系统源码时候很常见:
image.png

//android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
   //省略部分
//这里从BinderProxy类型的java对象中获取mObject属性,前面分析过它的值就是BpBinder对象指针
    IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
   //省略部分
//调用BpBinder对象的transact方法
    status_t err = target->transact(code, *data, reply, flags);
//省略部分
}

这里就可以看出前面讲的mObject为啥是“重要纽带”,那么接下来看看BpBinder的transact方法:

//BpBinder.cpp
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    if (mAlive) {
       //本质是调用了IPCThreadState的transact方法
        status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }
    return DEAD_OBJECT;
}

那么接下来看看IPCThreadState的transact方法:

//IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
 //省略部分
    if (err == NO_ERROR) {
      //准备好与驱动通信的数据格式结构体
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    }
//如果不是TF_ONE_WAY即oneway类型的调用
    if ((flags & TF_ONE_WAY) == 0) {
        if (reply) {
          //这里需要等待答复
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
    } else {
//即oneway类型的调用
        err = waitForResponse(NULL, NULL);
    }
    return err;
}

这里面分为两个大块writeTransactionData和waitForResponse,writeTransactionData主要目的就是把数据组装成和驱动一致的binder_transaction_data结构体,然后在是waitForResponse:

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        //与驱动进行通信,这里主要通过相关ioctl相关方法
        if ((err=talkWithDriver()) < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;
        //得到驱动返回cmd
        cmd = (uint32_t)mIn.readInt32();
        switch (cmd) {
        case BR_REPLY:
            {
                binder_transaction_data tr;
              //得到驱动返回数据
                err = mIn.read(&tr, sizeof(tr));
                //省略部分
         }
//省略部分
}

可以看出主要就是talkWithDriver与驱动进行通信并且一直等待返回驱动相应结果,这里涉及驱动部分就不给大家在这里讲解,大家把驱动暂时当作黑盒既可以。
这个地方简单看看ServiceManager这个服务端,面对客户端的getService做了什么呢?
在servicemanager代码中如果接受到客户端请求,最后都会调用到svcmgr_handler来负责处理:

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    struct svcinfo *si;
    uint16_t *s;
    size_t len;
    uint32_t handle;
    uint32_t strict_policy;
    int allow_isolated;
//..省略部分
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
     //根据获取到service的name
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
      //根据name从已经存在集合中找出对应的handle即索引
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
      //把handle获取到了后写入reply
        bio_put_ref(reply, handle);
        return 0;
//..省略部分
    default:
        ALOGE("unknown code %d\n", txn->code);
        return -1;
    }

    bio_put_uint32(reply, 0);
    return 0;
}

这里面根据name从集合中寻找出了服务的handle,注意这里只是找出了一个int类型的handle,然后在调用bio_put_ref进行写入reply,再通过binder驱动传递给客户端,这里看看bio_put_ref方法:

void bio_put_ref(struct binder_io *bio, uint32_t handle)
{
//构造出一个binder结构体
    struct flat_binder_object *obj;

    if (handle)
        obj = bio_alloc_obj(bio);
    else
        obj = bio_alloc(bio, sizeof(*obj));

    if (!obj)
        return;
//给flat_binder_object 结构体对应属性赋值
    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
 //设置类型为BINDER_TYPE_HANDLE
    obj->type = BINDER_TYPE_HANDLE;
   //把handle赋值给flat_binder_object 的handle属性
    obj->handle = handle;
    obj->cookie = 0;
}

这里大概我们就清除了原来servicemanager这一边做的事情就是根据name查找到这个name对应的handle,再把这个handle值包装到flat_binder_object 结构体中,再把结构体传递到驱动,驱动再传递到客户端,具体传递过程就不在这一节详细讲述,分析这里相当于客户端调用transact方法后,服务端servicemanager的数据经过binder驱动进行了返回。但是返回后的数据是怎么一步步又变成IBinder对象的呢?这里我们接下来看 IBinder getService(String name)的 IBinder binder = reply.readStrongBinder()方法了,这里看着就是从Parcel类型的reply中调用了readStrongBinder方法就返回了IBinder对象。注意啦Parcel这里是java层的,但是最后调用它又会调用到Parcel.cpp中,先看Parcel.java:

//Parcel.java
  public final IBinder readStrongBinder() {
        return nativeReadStrongBinder(mNativePtr);
    }

这里其实就只调用了nativeReadStrongBinder方法,它又是一个jni方法,所以这个方法后就会调用到native层,具体看一下这个方法在native层映射成了哪个方法:

//android_os_Parcel.cpp
    {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},

这里被映射成了android_os_Parcel_readStrongBinder方法:

//android_os_Parcel.cpp
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

这里又会先调用parcel->readStrongBinder()获取native层的BpBinder对象作为参数,然后再调用javaObjectForIBinder转为java对象,这个前面已经讲过了哦。

//Parcel.cpp
sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
//这里又调用了readNullableStrongBinder
    readNullableStrongBinder(&val);
    return val;
}

接下来看看readNullableStrongBinder:

status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
    return unflatten_binder(ProcessState::self(), *this, val);
}

这里又调用到了unflatten_binder:

status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);

    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
              //这里核心又是获取了handle后调用getStrongProxyForHandle
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

这里我们前面分析servicemanager时候就知道type类型为BINDER_TYPE_HANDLE,所以根据flat->handle的handle值调用getStrongProxyForHandle,这个getStrongProxyForHandle方法前面已经分析过他就是new BpBinder(handle),所以这里就明白了这个getService方法最后也是根据servicemanager返回的handle(这里大家要注意这个客户端的handle值和servicemanager中写入的handle值不一定相等,而是各种进程独立,但是在binder驱动可以关联上,具体区别会binder驱动中进行剖析)。
image.png
getService部分的总结:
1、获取远端Serivce整体依然是new BpBinder(handle) --> javaObjectForIBinder变成BinderProxy的过程
2、但这里的handle不再像ServiceManager那么简单的直接写死为0,而是需要把name传递到SeriveManager查询对应的服务,ServiceManager把对应服务flat_binder_object对象通过binder驱动传递到客户端,客户端再从flat_binder_object获取handle

至此我们就分析完了客户端发起一个调用到获取驱动数据返回的整个过程,那么接下要分析的是作为一个服务端即Binder实现端。

app安卓逆向之native层代码静态分析基础 app安卓逆向之Native层代码静态分析基础Native层代码静态分析1.背景分析2.概述3.开始3.1 ARM指令3.2 IDA基本使用方法3.3 Java层调用Native层方法原理3.4 Native层代码的修改3.5 So文件替换4.总结 Native层代码静态分析 1.背景分析 在安卓逆向的过程当中会遇到以下场景 经过上一阶段的Java层代码静态分析以及动态调试,发现加密参数的生成方法调用了Native层方法 经过对Native层代码分析后修改对应代码,替换原so文件发现app运行异常 针对 阅读详情

相关推荐

java层Binder——BinderProxy类

java层Binder——BinderProxy类   BinderProxy类实际上是java层Binder机制中客户端Proxy的mRemote成员变量。在Proxy中,客户端调用服务端IPC业务接口时,首先便会通过proxy中的业务接口去调用mRemote.transact,mRemote自然就是Proxy的成员变量,是一个IBinder类,这个IBinder只是一个Binder功能接口,它实际上就是由BinderProxy向上转型得来的。 一、实例化   在java层代码中很难找到这个类实例化的地方

qq_38401088的博客 2631

andrid分层的概念------native层

Android的分4层,java应用程序,java框架,本地框架和java运行环境,Linux内核空间 Java应用程序无需过多解释,基本可以理解为各个App,由Java语言实现。 Java框架层(系统服务)就是常说的Framework,这层里东西很多也很复杂,比如说主要的一些系统服务如ActivityManagerService、PackageManagerService等,我们编写的An

ffmxnjm的博客 2万+

Android Native binder 通信实例

本文是实现android native层binder通信案例,包含callback 实现。

HaikingJ的专栏 1993

Android中jni层,native层,hal层到底是什么

层级职责位置开发语言典型场景JNIJava 与 C/C++ 交互的桥梁Java 层 ↔ Native 层Java 调用本地加密算法Native高性能计算、底层操作JNI 层 ↔ Linux 内核C/C++音视频编解码、OpenGL 渲染HAL硬件抽象,统一硬件接口Native 层 ↔ 硬件驱动C/C++ 或 HIDL访问传感器、摄像头、蓝牙等硬件。

XinCurry的博客 3196

Android Binder——Native层介绍(五)

Binder Native 层主要负责实现进程间通信(IPC)和远程过程调用(RPC)的机制。在 Native 层中,Binder 架构主要包括服务端和客户端两部分。服务端存在一个 Binder 实体(BBinder)和对应的实体接口(BnInterface),而客户端存在一个 Binder 代理(BpBinder)和对应的代理接口(BpInterface)。服务端通过 Binder 驱动向 ServiceManager 进行注册,将 BBinde r的实体对象存入 ServiceManage r中。

小旭的专栏 1326

Ubuntu运行vmware时报错Vmware Unable to install all modules!Use shipped Linux kernel AIO access library解决。

Ubuntu运行vmware时报错Vmware Unable to install all modules! vmware --version 提示下面内容: [AppLoader] Use shipped Linux kernel AIO access library. An up-to-date "libaio" or "libaio1" package from your system is preferred. VMware Workstation 16.1.2 build-17966106

wto882dim的博客 2848

Android基础进阶 - 消息机制 之Native层分析,资深Android开发带你入门Framework

由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。化!**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)

2401_83974020的博客 1266

iOS远程真机之ios-minicap安装使用完全指南

minicap 是开源项目 STF 中的高速截图工具。STF利用此工具不断的传输图片信息并在web端绘制实现 以前只有Android版本,最近有新的ios版本,现在就安装过程中遇到的一些问题进行分享(ps:感谢sorccu 在issue里面给我的指点) 首先上地址:https://github.com/openstf/ios-minicap 你可以git clone或者直接下载zip包。

甫式人生 1万+

Android基础进阶 - 消息机制 之Native层分析,kotlin开源

value = sStrThreadlocal.get(); intValue = sIntegerThreadLocal.get(); System.out.println(“444 curThreadId=”+Thread.currentThread()+" strthreadLocalValue="+value +" intThreadLocalValue="+intValue); //用完之后记得remove,虽然,ThreadLocalMap.Entry的key是ThreadLocal的弱引用,但

m0_64604042的博客 1864

uniapp(全端兼容) - 最新详细实现瀑布流列表及布局设计,uni-app全平台兼容的瀑布流示例,view容器自适应瀑布流布局,图片瀑布流布局、图像+文字卡片式瀑布流,类似小红书(详细示例代码)

uni-app,瀑布流,安卓app,苹果app,微信小程序,移动端,H5网页,手机网站,微信小程序、支付宝小程序,手机app端,nvue,瀑布流布局,如何实现图片瀑布流,怎么做文字+图像瀑布流,uniapp仿小红书笔记瀑布流效果,uniAPP仿快手抖音布局列表,瀑布流列表详细教程,编译所有平台都能用的瀑布流列表,商品瀑布流列表,图文列表,小程序瀑布流,页面触底懒加载,瀑布流插件,详细示例代码教程,uni-app H5实现瀑布流效果,uniapp小程序做瀑布流,纯css瀑布流,用uniapp写瀑布流商品列表,

✅ 精选推荐文章 1万+

阿里云 Docker 镜像加速收费后:这些免费替代方案值得收藏

阿里云Docker镜像加速服务收费后,国内开发者急需免费替代方案。本文推荐2025年仍可用的7个免费镜像源,包括轩辕镜像、DaoCloud、网易云等,并提供多源配置方案以提高稳定性。建议开发者在CI/CD环境中配置多个镜像源,避免构建失败。文章还提供了详细的配置步骤和使用建议,适合个人和团队开发者参考。

sg_knight的专栏 1930

Android Binder实战开发指南之Native层使用Java层Binder服务

Android Binder实战开发指南之Native层使用Framework层Binder服务 承接上一篇 Android Binder实战开发指南之创建Framework层Binder系统服务,前面主要介绍了在Java的世界里面怎么通过Binder进行PIC跨进程调用,那么本篇将介绍Native层怎么通过C++使用上一篇文章中实现的Bind...

IT先森 2831

使用SSC添加大量的SDO条目

使用SSC添加大量的SDO条目 SSC用表格添加SDO,PDO部分必须指定到0x1600和0x1A00分配TxPdo和RxPdo映射,在0x1C12和0x1C13分别分配到SM2和SM3。在0x6000和0x7000未指定的entry就是SDO部分。

PI_sunyang的博客 3166

Binder源码分析之Native层(原)

前面两节中介绍了Binder机制中的ServiceManager和Binder驱动,在这一节中,我们来介绍Native中的Binder通讯。         为了更好的理解过程,我们挑选Native中的MediaServer进行分析。     一、MediaServer加载过程         Android启动过程中会去执行init.rc脚本,在这个脚本中将会启动一些关键的系统服务,其中之

阿杜的专栏 7625

SKUA-GOCAD入门教程-第七节 点的创建与编辑3

本文介绍了四种从井数据创建点集的方法

江洋大葱的博客 963

12. Web安全—渗透测试用例—敏感信息泄漏

12. Web安全—渗透测试用例—敏感信息泄漏

weixin_43567873的博客 412

Android之IPC5————Binder2 Native层分析

Android之IPC5————Binder2 native层分析

冰炭不投day的博客 1019

YOLOv13添加WDBB模块,map提升5.34!!,召回率提升6.55,准确率提升3.23

本文提出了一种基于YOLOv13改进的目标检测模型,通过引入WDBB模块显著提升了检测性能。实验结果表明,添加WDBB模块后,mAP提升11.34,召回率提升14.55,准确率提升3.23。文章详细介绍了模型移植方法,包括创建新的yaml配置文件、修改tasks.py和__init__.py文件,以及实现rep_block.py中的核心转换函数。改进后的模型通过深度卷积、通道注意力等模块优化了特征提取能力,同时保持了轻量化的特点。该工作为YOLO系列模型的性能提升提供了新的思路和技术实现。

FJN110的博客 2623

Android Binder框架实现之Native层getService详解之请求的发送

   Android Binder机制(十) getService详解之请求的发送    在前面的篇章中,我们以MediaPlayerService为例,介绍了Service服务是如何通过addService请求添加到ServiceManager中的(其中的艰难困苦,你懂的)。本文,将以MediaPlayer获取MediaPlayerService服务为例,来介绍Client端是如...

IT先森 3548

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android7.0 Binder通信(4) Java层中的Binder

之前博客分析Binder机制时,集中分析的是Native层Binder的架构,现在来分析一下Java层Binder的架构。

橡果生长记的博客 3772

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

千里马Android Framework实战开发-native程序之间binder通信实战案例分析

千里马Android Framework实战开发-native程序之间binder通信实战案例分析 1、需求背景 在android系统开发中,不仅仅我们都停留在java层面,很可能也会遇到比如一些native的可执行程序,比如surfaceflinger,bootanimation等他们都是native的执行程序,这些程序之间也经常会有要进行binder跨进程通信的需求,所以这个时候学习native层进行跨进程通信是非常有必要的。 2、案例功能介绍 在app的java层面我们之前已经实现过了binder的双

learnframework的博客 1692

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Android Binder之native层解析

1 前言 Binder是Android系统中提供的一种进程间通信方式,Android是基于Linux内核的,除了Binder外,还有其他的进程间 通信方式,可以参考笔者之前的文章, Linux自带多种进程间IPC,为什么Google却用Binder作为Android主要的进程间IPC?。 对我们好多开发者来讲,最难也最想掌握的恐怕就是Binder了,Android整个系统可以看作一个基于Binde...

Kelly_ge的博客 745

native层的c++如何通过binder获取sm服务(四)

前几篇Binder相关文章讲了驱动的注册和提供的接口,以及ServiceManager的启动运行,很自然接下来我们需要思考客户端进程应该如何获取到sm提供的服务(注册服务和查询服务),本篇从native层c++角度继续分析。 我们需要时刻牢记,应用程序跨进程只能依靠某种介质(比如socket是靠网卡、binder是靠驱动、内存共享是靠物理内存),直接软件去架构是无法做到的,在分析ServiceManager时也说了,sm是一个标准的Binder Server,因之,客户端进程想要访问ServiceManag

dream_caoyun的博客 1451

Android Binder框架实现之Native层getService详解之请求的反馈

   Android Binder机制(十二) getService详解之请求的反馈    前面两篇文章分别介绍了getService中"请求的发送"和"请求的处理"这两部分,本文将介绍getService请求的最后一部分–请求的反馈。下面继续分析分析MediaPlayer收到请求反馈之后的处理流程。 注意:本文是基于Android 7.xx版本进行介绍的! 1 唤醒MediaPlayer客户...

IT先森 1752

android11 native binder service入门之创建一个自己的service

本文实现了一个Android Binder服务"myservice",包含服务端和客户端两部分。服务端通过继承BBinder类实现了一个加法服务,接收两个整数并返回它们的和。客户端通过ServiceManager获取该服务,发送40和50两个整数,成功获取到结果90。代码展示了Binder跨进程通信的基本流程,包括服务注册、事务处理和结果返回等关键步骤。该实现验证了Android Binder机制的可行性,为开发系统服务提供了参考范例。

juruiyuan111的专栏 948
上一篇: ubuntu 20.04 aosp 13/14/android s/android T/android12/android13 build
下一篇: android8.1编译出现py相关语法错误: SyntaxError: invalid syntax
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值