对于AndroidFramework实战开发-binder通信java及jni部分源码分析感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解androidframework开发教程,并且为您提
对于Android Framework实战开发-binder通信java及jni部分源码分析感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解android framework开发教程,并且为您提供关于0. 查看 Android framework 源码、0.查看Android framework源码、android framework、Android Framework Application Framework层简单介绍的宝贵知识。
本文目录一览:- Android Framework实战开发-binder通信java及jni部分源码分析(android framework开发教程)
- 0. 查看 Android framework 源码
- 0.查看Android framework源码
- android framework
- Android Framework Application Framework层简单介绍
Android Framework实战开发-binder通信java及jni部分源码分析(android framework开发教程)
csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论
android跨进程通信实战视频课程(加群获取优惠)
1、第一部分进程与ServiceManager通信及客户端程序发起调用详解
平时大部分获取ServiceManager中的某一个服务,一般都是最后都是ServiceManager.getService这种方式:
//ServiceManager.java中
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
这里getIServiceManager()如下:
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
这里最后也是调用了BinderInternal.getContextObject(),这里getContextObject是个native方法,所以继续追到了native层:
这个对应native方法在:
frameworks\base\core\jni\android_util_Binder.cpp中
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
大家看他又调用到了 ProcessState::self()->getContextObject,获取了native层面的IBinder对象,然后再调用javaObjectForIBinder把这个对象进行转换成java对象
先来看 ProcessState::self()->getContextObject方法:
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
这里其实是调用getStrongProxyForHandle(0),记住哦这里传递handle的参数是0,因为ServiceManager的一个应用固定就是0,他是我们跨进程通信一切一切的基础,几乎所有跨进程通信都是需要通过它
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn''t have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
这刚开始handle_entry肯定为null,所以这里其实就是new BpBinder(0)对象进行返回,那么这里大家就应该清楚,最后进程获取ServiceManager对应的IBinder对象,其实本质就是BpBinder对象,这个对象由对应的handle值,通过这个handle值传递到了驱动,驱动就可以知道与哪个进程进行通信,0当然是ServiceManager进程。
到这里我们就获取的一个BpBinder,但是这个是也是native层面的,怎么把它变成java层面的对象呢?这里就需要来看javaObjectForIBinder(env, b)方法:
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.
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());//这里吧val这个c++的对象指针设置到gBinderProxyOffsets.mObject这个java属性中
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);
// Also remember the death recipients registered on this proxy
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
其中的gBinderProxyOffsets修改看如下:
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);
clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;)V");
gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
。。省略
}
其实本质都是通过jni方式来构造
好了那么回到最初始:
ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
这个里面allowBlocking可以暂时忽略,名字它只是个和阻塞不阻塞相关,BinderInternal.getContextObject()本身就已经是BinderProxy类型对象了,所以asInterface其实就是:
new ServiceManagerProxy(obj);这里obj其实就是ServiceManagerProxy类中的mRemote,通信时候其实都是调用这个mRemote的transact方法
那接下来获取了ServiceManager已经分析的很清楚了,那么看看他的一个getSevice方法,这里其实addService肯定也是完全类似的,就只需要分析一个既可以:
那么我们来看getIServiceManager().getService(name)方法:
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
这里看看出,它首先要进行跨进程通信就要准备好数据包Parcel,data代表要传递过去的,reply代表要传递回来的,然后再调用最关键的mRemote.transact,这里前面分析过了mRemote本质是BinderProxy类型,故来看BinderProxy的transact(注意BinderProxy类在Binder.java这个文件中):
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
。。省略
try {
return transactNative(code, data, reply, flags);
} finally {
if (tracingEnabled) {
Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
}
}
}
这里其实就是调用transactNative 对应的jni 方法在:
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
。。省略
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
。。省略
//printf("Transact from Java code to %p sending: ", target); data->print();
status_t err = target->transact(code, *data, reply, flags);
。。省略
}
这里其实就是获取BinderProxy中的mObject对象,因为他存储是c++层面的BpBinder对象地址,故target其实就是调用BpBinder的transact:
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
这里看看到最后又调用到了IPCThreadState的transact方法
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);
}
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
writeTransactionData主要目的就是把数据组装成驱动的binder_transaction_data结构体
然后又会根据是否为oneway区分,但是最后都是调用waitForResponse方法:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
。。省略
}
}
。。省略
}
这里循环调用talkWithDriver,然后获取结果。驱动部分我们下一节会讲解,这里我们到这里就知道,binder通信在自己进程最后都会调用到talkWithDriver来与binder驱动进行通信。
这里就直接给出返回结果为对应的Serivce的handle,然后利用这个handle构造出对应的BpBinder即这一部分就完全和IServiceManager的获取是一样的,只不过ServiceManager是直接new BpBinder(0)
而远程服务则是需要先从ServiceManager中获取handle,然后再new BpBinder(handle)
至此为止,我们就分析清楚了客户端发起一个跨进程调用的java到jni的所有流程
2、服务进程的方法被调用流程从上到下详解
服务端的方法被调用流程相比客户端的主动发起调用流程更加难分析,这里我们可以分成2个部分来进行分析:
2.1 native层的BBinder执行分析:
因为这里只涉及到native层面,相对不用把java部分搞一起,相对分析起来会简单,讲解完了这一部分在去讲解java端怎么运行相对就会简单很多,如果一起讲解相对理解难度会非常大。
我们前面应该知道,native层面进行跨进程通信时候,服务端主要负责实现一个BBinder类,它最主要的方法就是onTransact方法:
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0) {
ALOGD( "Service onTransact, code = %d" , code);
switch (code) {
case FUNC_CALLFUNCTION:
callFunction();
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
return 0;
}
这里其实就是已经进入了我们的服务端的方法具体方法实现了,那么到底是怎么一步步到这里呢?
这里当然大家可以采用以前我们说过的用类似java的打印调用堆栈方法来追踪。这里我们后面再给大家展示既可以,本节课就暂时不讲啦。
那首先来看看到 IPCThreadState::self()->joinThreadPool( true);这个方法就代表会一直不断来读取驱动发过来数据
do {
。。省略
result = getAndExecuteCommand();
。。省略
}
} while (result != -ECONNREFUSED && result != -EBADF);
其实他就是在不断执行getAndExecuteCommand
status_t IPCThreadState::getAndExecuteCommand()
{
。。省略
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
。。省略
result = executeCommand(cmd);
。。省略
}
return result;
}
这里是不是talkWithDriver会与驱动进行通信获取了对应result和数据写入了mIn中,读取cmd,然后调用了executeCommand(cmd)方法
status_t IPCThreadState::executeCommand(int32_t cmd)
{
。。省略
switch ((uint32_t)cmd) {
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
if (tr.target.ptr) {
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
sendReply(reply, 0);
}
。。省略
}
break;
。。省略
return result;
}
这里省略的大部分,我们主要关心case BR_TRANSACTION:情况
有这句关键代码:
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);
这里是不是大概可以看出一个BBinder指针调用对应的transact方法,好像我们发现了真相是吧?都看到transact了,那么继续看看transact方法,因为我们自己没有实现过这个transact,只是重写了onTransact(注意哦,这里的BBinder类在Binder.cpp中):
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
..省略
switch (code) {
..省略
default:
err = onTransact(code, data, reply, flags);
break;
}
..省略
return err;
}
这里是不是就看到了我们的onTransact,这里就是真正调用到我们自己写的服务的onTransact方法中。
那这里好像就讲完了粗略流程。但是还有许多细节哦,比如
reinterpret_cast<BBinder*>(tr.cookie)->transact()
这里面的tr.cookie我们猜想肯定是我们自己的SampleService这个继承BBinder对象的类。但是它是到底怎么一步步变成了这里的tr.cookie 我们并不清楚,那么我们就来详细分析一下:
那么首先得回到最开始ServiceManager的addService:
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
这里是不是把自己的service通过Parcel 的writeStrongBinder写入了,那来看看writeStrongBinder:
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
接下来看看flatten_binder:
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
。。省略
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don''t pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
}
。。省略
return finish_flatten_binder(binder, obj, out);
}
这里我们可以看到binder->localBinder();它是用来判断是不是本地binder对象:
BBinder* BBinder::localBinder()
{
return this;
}
明显这里就返回了自己,所以返回是SampleService,那就是进入以下:
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
这里大家是不是看到了一个cookie 东西,它赋值为了local也就是我们的SampleService这个BBinder类对象
2.2 java端的Binder执行与到native层映射分析
2.1 已经清楚binder驱动是怎么调用到native的BBinder的,但同学们肯定又会问,我们平时写的代码都是java层面,请问java层又是怎么个流程呢?这个其实java当然也是基于native层面的BBinder来实现的,具体我们来看代码:
假设是调用java层的ServiceManager来addService
ServiceManager.addService("MyService", new MyService());//注册服务
//其中的MyService是真正的实现服务端的实现类,这里是不是看出和native层BBinder的要素是不是基本一致,
//最主要是onTransact这个实现,其实这里是由native层面调用过来的,稍后解密
public class MyService extends Binder implements IMyService{
public MyService() {
this.attachInterface(this, DESCRIPTOR);
}
@Override
public IBinder asBinder() {
return this;
}
/** 将MyService转换为IMyService接口 **/
public static com.test.frameworkBinder.IMyService asInterface(android.os.IBinder obj) {
。。省略
}
/** 服务端,接收远程消息,处理onTransact方法 **/
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
。。省略
case TRANSACTION_say: {
data.enforceInterface(DESCRIPTOR);
String str = data.readString();
sayHello(str);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
/** 自定义sayHello()方法 **/
@Override
public void sayHello(String str) {
System.out.println("MyService:: Hello, " + str);
}
}
那么首先我们来看ServiceManager.addService干了啥:
在ServiceManagerNative.java
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
这里调用的是data.writeStrongBinder(service);来把我们service写入:
在Parcel.java
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
调用是nativeWriteStrongBinder,是个native方法
base\core\jni\android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
其实他也是调用的native的Parcel类的writeStrongBinder方法,这个方法上一节讲过,但是这里大家看参数是一个java层面的object,所以调用了ibinderForJavaObject(env, object)方法来进行转换,这个方法也就是java层面到native可以打通的一个核心:
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
return NULL;
}
这里我们业务是本地实现的Binder对象,所以不是gBinderProxyOffsets.mClass,是我们的gBinderOffsets.mClass,这里看看这个gBinderOffsets.mClass:
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderPathName);
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
这方法里面对gBinderOffsets相关的方法和属性进行了设置,大家可以看到mClass 类名其实是android/os/Binder,而我们的MyService本身就是继承android.os.Binder对象,同时注意这里还对execTransact和mObject进行了声明
在回到ibinderForJavaObject:
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
这里会发现从MyService中的mObject对象获取了native层面的JavaBBinderHolder(有个疑问为啥可以获取,java层mObject什么时候变成了JavaBBinderHolder指针,这个稍后解答),然后再调用了JavaBBinderHolder的get方法,就可以获取一个native层面的BBinder对象:
class JavaBBinderHolder : public RefBase
{
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
}
return b;
}
sp<JavaBBinder> getExisting()
{
AutoMutex _l(mLock);
return mBinder.promote();
}
private:
Mutex mLock;
wp<JavaBBinder> mBinder;
};
这里可以看到get方法确实会在方法里面构造一个JavaBBinder返回,而且大家注意哦,这里是不是还把java层的jobject传递给了JavaBBinder,目前其实就是为了后续JavaBBinder肯定先收到驱动的调用,但是这里JavaBBinder他也要调用到Java层面。
class JavaBBinder : public BBinder
{
public:
JavaBBinder(JNIEnv* env, jobject object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
ALOGV("Creating JavaBBinder %p\n", this);
android_atomic_inc(&gNumLocalRefs);
incRefsCreated(env);
}
bool checkSubclass(const void* subclassID) const
{
return subclassID == &gBinderOffsets;
}
jobject object() const
{
return mObject;
}
protected:
。。省略
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
。。省略
JNIEnv* env = javavm_to_jnienv(mVM);
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
。。省略
private:
JavaVM* const mVM;
jobject const mObject;
};
到这里JavaBBinder 即它本身也是BBinder相信大家就已经明白,上节课native时候就已经分析过了,最后binder的读取线程会调用到onTransact这个方法,我们看这里是不是有一个CallBooleanMethod方法来调用到java端,这里是调用了gBinderOffsets.mExecTransact方法,它对于是java层Binder的execTransact方法:
// Entry point from android_util_Binder.cpp''s onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
。。省略
try {
。。省略
res = onTransact(code, data, reply, flags);
} catch (RemoteException|RuntimeException e) {
。。省略
} finally {
。。省略
}
。。省略
return res;
}
大家看这里他就会调用onTransact,这个onTransact方法当然就调用到了子类MyService的onTransact,故是不是整个java层面到native层面的穿透是不通了
最后解答一下,JavaBBinderHolder什么时候放到了java层mObject,这里我们肯定就来搜索new JavaBBinderHolder的地方:
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
。。省略
jbh->incStrong((void*)android_os_Binder_init);
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
这里大家可以看出是在android_os_Binder_init方法,它把JavaBBinderHolder对象指针赋值给了mObject,这个方法一看就是jni的一个方法,:
{
"init", "()V", (void*)android_os_Binder_init },
名字其实可以知道是Binder.java的init方法,而且init是native的
果然Binder.java定义声明如下:
private native final void init();
这里看看init是在哪里被调用的:
public Binder() {
init();
。。省略
}
他是在Binder()默认构造方法中执行,回到开始MyService 是不是继承Binder:
class MyService extends Binder
所以子类构造会先执行父类构造
4、总结类图
0. 查看 Android framework 源码
参考
http://kaedea.com/2016/02/09/android-about-source-code-how-to-read/
https://www.zhihu.com/question/19759722
https://blog.csdn.net/hejjunlin/article/details/53454514
查看系统源码说明
1. 可以在 sdk 中 source 查看大部分 framework 源码
2. 如果在 sdk 中的 source 找不到某系统类源码,则可以在官方源码网查看
https://android.googlesource.com/?format=HTML
其中 framework 源码在 platform/frameworks/base,
android/platform/frameworks/base/android-xxx/./core/java
在线查看系统源码
http://androidxref.com/
https://cs.android.com/
这个是官方出的,和第一个类似。
在 AS 中查看隐藏的 API 源码
platform 和 sources 目录的关系
AS 会把 platform 里面的 android.jar 里的 class 文件关联到 sources 里对应的 java 文件。
也就是说 android.jar 里面没有的类,在 AS 里也看不到,android.jar 有对应的 class 文件才能映射到 sources 里对应的 java 文件。
如果没有对应 api 的 sources 的话就会解析显示 android.jar 里的 class 文件。
1. 介绍
Android 有两种类型的 API 是不能经由 SDK 访问的。
- 第一种是位于 com.android.internal 包中的 API。我将称之为 internal API。
- 第二种 API 类型是一系列被标记为 @hide 属性的类和方法。
Internal 和 hidden API 的编译时 vs 运行时
当你使用 Android SDK 进行开发的时候,你引用了一个非常重要的 jar 文件 ——android.jar。它位于 Android SDK 平台的文件夹中(SDK_DIR/platforms/platform-X/android.jar)。这个 android.jar 移掉了 com.android.internal 包中所有的类,也移掉了部分标记有 @hide 的类,枚举,字段和方法。
每个模拟器或真机在运行时都会有一个等同 android.jar 的东西,叫做 framework.jar,它和 android.jar 等同,而其未移掉 internal API 和 hidden API。当你在设备上启动应用程序时,它将加载 framework.jar。
但这样对开发者来说,并不能友好地访问,因此,我将向大家展示不通过反射如何使用这些 API。
2. 解决方法
方法一
大致流程就是:我们可以从 framework.jar,提取出原始的.class 文件,并拷贝到 Android SDK 的 android.jar 中。
注意:模拟器通常在.dex 文件中包含代码,而真机一般在优化版的 dex 文件中包含代码 ——odex 文件。操作 odex 文件比较困难,这也是为什么我选择模拟器的原因。
-
adb pull /system/framework/framework.jar
或使用 DDMS 里的 File Explorer。
- 从 framework.jar 中提取出 classes.dex,
- 使用 dex2jar 工具,将其转换成 classes.jar
- 然后把 classes.jar 里的文件都替换到 android.jar 中。
-
替换 D:\Android\sdk\platforms\android-xx 里的 android.jar 即可
注意:记得备份原 android.jar
注意:可能高版本系统把隐藏 api 分到了多个 jar 包中,所以都需要进行上面操作
- android.policy.jar
- framework.jar
- framework2.jar
- services.jar
方法二
在万能的 GitHub 已有人去除 Android.jar 中 @hide 注解
地址: https://github.com/anggrayudi/android-hidden-api
1. 下载对应 API 版本的 Android.jar
2. 替换 SDK/platforms/android - 版本 / Android.jar
3. 重新打开 IDE 就可以查看
直接调用隐藏 API 的缺点:
1.Android 隐藏 API 是因为不能保证这些 API 还存在新系统版本,所以尽量少用隐藏 API!
2. 不利于团队合作,如果有人使用正常 Android.jar 就无法编译如 endCall () 之类的隐藏 API!
eclipse 中查看 Android 源码
在 eclipse 中随便创建一个项目,
右键项目 -》properties-》java build path-》Libraries-》Add external jars-》选择 D:\Android\sdk\platforms\android-xx\android.jar
在 android.jar 下的 source attachment
使用 Idea 查看 Android 源码
之前有 eclipse 来查看 Android 的 framework 源码,但 eclipse 的查找功能太弱,不太方便。AS 的查看很方便但每次查看 Android 源码都得修改 platform 的 android.jar,很不方便。
可以用 IntelliJ IDEA 来进行查看。
关联 Android sdk,
随便创建一个 java 项目即可
然后打开项目的 Project Structure,在 sdks 下可以看到可用的 sdk,其中就包含了 Android sdk,就可以通过修改 classpath
然后再 modules 选项卡中,项目根目录的 dependencies 时 jdk,这里可以直接就修改根目录的引用的 sdk。
或者可以创建一个新的 module,修改 module 的 dependencies,这样就可以同时访问 jdk 和 Android sdk 中的源码。
在 AS 中查看隐藏的 API 源码 2
不知道怎么回事,在 idea 上查看不了布局,所以经过各种尝试又回到了使用 AS 查看源码。
具体就是模仿 idea 在 project structure 中的设置。最终其实是修改的 C:\Users\puppet\.IdeaIC2019.2\config\options\jdk.table.xml 文件。
由于 as 在 3.4 中修改了 project structure 界面,把 sdks 去掉了,没法再 ide 上修改,所以直接手动修改 jdk.table.xml。
-
打开 C:\Users\puppet\.AndroidStudio3.4\config\options\jdk.table.xml 文件,找到对应的 Android 版本,在 <classPath> 标签里加入对应的完全版 android.jar。
-
然后重启 as,即可。
0.查看Android framework源码
参考
http://kaedea.com/2016/02/09/android-about-source-code-how-to-read/
https://www.zhihu.com/question/19759722
?
查看系统源码说明
1.可以在sdk中source查看大部分framework源码
?
2.如果在sdk中的source找不到某系统类源码,则可以在官方源码网查看
https://android.googlesource.com/?format=HTML
?
其中framework源码在platform/frameworks/base,
android/platform/frameworks/base/android-xxx/./core/java
?
在AS 中查看隐藏的API源码
platform和sources目录的关系
AS会把platform里面的android.jar里的class文件关联到sources里对应的java文件。
也就是说android.jar里面没有的类,在AS里也看不到,android.jar有对应的class文件才能映射到sources里对应的java文件。
如果没有对应api的sources的话就会解析显示android.jar里的class文件。
?
1.介绍
Android有两种类型的API是不能经由SDK访问的。
- 第一种是位于com.android.internal包中的API。我将称之为internal API。
- 第二种API类型是一系列被标记为@hide属性的类和方法。
Internal和hidden API的编译时 vs 运行时
当你使用Android SDK进行开发的时候,你引用了一个非常重要的jar文件——android.jar。它位于Android SDK平台的文件夹中(SDK_DIR/platforms/platform-X/android.jar)。这个android.jar移掉了com.android.internal包中所有的类,也移掉了部分标记有@hide的类,枚举,字段和方法。
每个模拟器或真机在运行时都会有一个等同android.jar的东西,叫做framework.jar,它和android.jar等同,而其未移掉internal API和hidden API。当你在设备上启动应用程序时,它将加载framework.jar。
但这样对开发者来说,并不能友好地访问,因此,我将向大家展示不通过反射如何使用这些API。
?
2.解决方法
方法一
大致流程就是:我们可以从framework.jar,提取出原始的.class文件,并拷贝到Android SDK的android.jar中。
注意:模拟器通常在.dex文件中包含代码,而真机一般在优化版的dex文件中包含代码——odex文件。操作odex文件比较困难,这也是为什么我选择模拟器的原因。
?
-
adb pull /system/framework/framework.jar
或使用DDMS里的File Explorer。
- 从framework.jar中提取出classes.dex,
- 使用dex2jar工具,将其转换成classes.jar
- 然后把classes.jar里的文件都替换到android.jar中。
-
替换D:\Android\sdk\platforms\android-xx里的android.jar即可
注意:记得备份原android.jar
?
注意:可能高版本系统把隐藏api分到了多个jar包中,所以都需要进行上面操作
- android.policy.jar
- framework.jar
- framework2.jar
- services.jar
方法二
在万能的GitHub已有人去除Android.jar中@hide注解
地址: https://github.com/anggrayudi/android-hidden-api
1.下载对应API版本的Android.jar
2.替换SDK/platforms/android-版本/Android.jar
3.重新打开IDE就可以查看
?
直接调用隐藏API的缺点:
1.Android隐藏API是因为不能保证这些API还存在新系统版本,所以尽量少用隐藏API!
2.不利于团队合作,如果有人使用正常Android.jar就无法编译如endCall()之类的隐藏API!
?
?
?
eclipse中查看Android源码
在eclipse中随便创建一个项目,
右键项目-》properties-》java build path-》Libraries-》Add external jars-》选择D:\Android\sdk\platforms\android-xx\android.jar
?
在android.jar下的source attachment
?
使用Idea查看Android源码
之前有eclipse来查看Android的framework源码,但eclipse的查找功能太弱,不太方便。AS的查看很方便但每次查看Android源码都得修改platform的android.jar,很不方便。
可以用IntelliJ IDEA来进行查看。
关联Android sdk,
?
随便创建一个java项目即可
然后打开项目的Project Structure,在sdks下可以看到可用的sdk,其中就包含了Android sdk,就可以通过修改classpath
?
然后再modules选项卡中,项目根目录的dependencies时jdk,这里可以直接就修改根目录的引用的sdk。
或者可以创建一个新的module,修改module的dependencies,这样就可以同时访问jdk和Android sdk中的源码。
?
?
?
在AS 中查看隐藏的API源码2
不知道怎么回事,在idea上查看不了布局,所以经过各种尝试又回到了使用AS查看源码。
具体就是模仿idea在project structure中的设置。最终其实是修改的C:\Users\puppet\.IdeaIC2019.2\config\options\jdk.table.xml文件。
由于as在3.4中修改了project structure界面,把sdks去掉了,没法再ide上修改,所以直接手动修改jdk.table.xml。
-
打开C:\Users\puppet\.AndroidStudio3.4\config\options\jdk.table.xml文件,找到对应的Android版本,在<classpath>标签里加入对应的完全版android.jar。
-
然后重启as,即可。
?
?
?
?
android framework
请问各位大神 android framework 怎么学,有没有推荐的书籍?Android Framework Application Framework层简单介绍
引言
Android的四层架构相比大家都很清楚,老生常谈的说一下分别为:Linux2.6内核层,核心库层,应用框架层,应用层。我今天重点介绍一下应用框架层Framework,其实也是我自己的学习心得。
Framework层为我们开发应用程序提供了非常多的API,我们通过调用特殊的API构造我们的APP,满足我们业务上的需求。写APP的人都知道,学习Android开发的第一步就是去学习各种各样的API,什么Activity,Service,Notification等。这些都是framework提供给我们的,那么我就详细的讲讲Framework到底在整个Android架构中扮演着什么角色。
Framework功能
Framework其实可以简单的理解为一些API的库房,android开发人员将一些基本功能实现,通过接口提供给上层调用,可以重复的调用
我们可以称Framework层才真正是Java语言实现的层,在这层里定义的API都是用Java语言编写。但是又因为它包含了JNI的方法,JNI用C/C++编写接口,根据函数表查询调用核心库层里的底层方法,最终访问到Linux内核。那么Framework层的作用就有2个。
1.用Java语言编写一些规范化的模块封装成框架,供APP层开发者调用开发出具有特殊业务的手机应用。
2.用Java Native Interface调用core lib层的本地方法,JNI的库是在Dalvik虚拟机启动时加载进去的,Dalvik会直接去寻址这个JNI方法,然后去调用。
2种方式的结合达到了Java方法和操作系统的相互通信。Android为什么要用Java编写Framework层呢?直接用C或C++不是更好?有关专家给出了如下解释:
C/C++过于底层,开发者要花很多的经历对C/C++的语言研究清楚,例如C/C++的内存机制,如果稍不注意,就会忘了开启或者释放。而Java的GC会自动处理这些,省去了很多的时间让开发者专注于自己的业务。所以才会从C/C++的底层慢慢向上变成了JAVA的开发语言,该层通过JNI和核心运行库层进行交互。
其实这些也是Java能发展这么迅速的原因,面对对象语言的优势。不用太关注内存,放心大胆的去做实现,才有时间去创造新的事物。
Framework API
Activity Manager
用来管理应用程序生命周期并提供常用的导航回退功能。
Window Manager
提供一些我们访问手机屏幕的方法。屏幕的透明度、亮度、背景。
Content Providers
使得应用程序可以访问另一个应用程序的数据(如联系人数据库), 或者共享它们自己的数据。
View System
可以用来构建应用程序, 它包括列表(Lists),网格(Grids),文本框(Text Boxes),按钮(Buttons), 甚至可嵌入的web浏览器。
Notification Manager
使得应用程序可以在状态栏中显示自定义的提示信息。
Package Manager
提供对系统的安装包的访问。包括安装、卸载应用,查询permission相关信息,查询Application相关信息等。
Telephony Manager
主要提供了一系列用于访问与手机通讯相关的状态和信息的方法,查询电信网络状态信息,sim卡的信息等。
Resource Manager
提供非代码资源的访问,如本地字符串,图形,和布局文件(Layout files )。
Location Manager
提供设备的地址位置的获取方式。很显然,GPS导航肯定能用到位置服务。
XMPP
可扩展通讯和表示协议。前身为Jabber,提供即时通信服务。例如推送功能,Google Talk。
。。。。
Framework层提供的服务还有很多,就不一一列出啦。
总结
从Android的整体框架开始,我们只详细介绍了一下Framework层,对其作用和功能,以及在4层框架中所扮演的角色做了简单的阐述。然后列举出来它提供给上层的一些重要的服务。对Application Framework有了一个简单的印象性了解,以此为开始,以后再对每个服务详细研究。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
关于Android Framework实战开发-binder通信java及jni部分源码分析和android framework开发教程的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于0. 查看 Android framework 源码、0.查看Android framework源码、android framework、Android Framework Application Framework层简单介绍等相关内容,可以在本站寻找。
本文标签: