日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IBinder获取手机服务信息异常

發布時間:2024/7/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IBinder获取手机服务信息异常 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

小米8 利用IBinder transact獲取服務的接口名字,結果出現以下異常:

W/System.err: java.lang.SecurityException W/System.err: ? ? at android.os.BinderProxy.transactNative(Native Method) W/System.err: ? ? at android.os.BinderProxy.transact(BinderProxy.java:482) W/System.err: ? ? at com.gamesec.essential.Essential.getInterfaceName(Essential.java:182) W/System.err: ? ? at com.gamesec.essential.Essential.getRunningServiceInfo(Essential.java:204) W/System.err: ? ? at com.gamesec.essential.Essential.getEssential(Essential.java:134) W/System.err: ? ? at com.gamesec.DataCollector.collectDeviceInfo(DataCollector.java:373) W/System.err: ? ? at com.gamesec.DataCollectorThread.run(DataCollectorThread.java:12)

?

手機系統為android9.0,所以查看源碼?/.core/jni/android_util_Binder.cpp文件

?

android_os_BinderProxy_transact

[?android_util_Binder.cpp]

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException {if (dataObj == NULL) {jniThrowNullPointerException(env, NULL);return JNI_FALSE;}Parcel* data = parcelForJavaObject(env, dataObj);if (data == NULL) {return JNI_FALSE;}Parcel* reply = parcelForJavaObject(env, replyObj);if (reply == NULL && replyObj != NULL) {return JNI_FALSE;}IBinder* target = getBPNativeData(env, obj)->mObject.get();if (target == NULL) {jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");return JNI_FALSE;}ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",target, obj, code);bool time_binder_calls;int64_t start_millis;if (kEnableBinderSample) {// Only log the binder call duration for things on the Java-level main thread.// But if we don'ttime_binder_calls = should_time_binder_calls();if (time_binder_calls) {start_millis = uptimeMillis();}}//printf("Transact from Java code to %p sending: ", target); data->print();status_t err = target->transact(code, *data, reply, flags);//if (reply) printf("Transact from Java code to %p received: ", target); reply->print();if (kEnableBinderSample) {if (time_binder_calls) {conditionally_log_binder_call(start_millis, target, code);}}if (err == NO_ERROR) {return JNI_TRUE;} else if (err == UNKNOWN_TRANSACTION) {return JNI_FALSE;}signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());return JNI_FALSE; }

這里會有異常拋出:

  • 當拋出異常NullPointerException: 代表dataObj為空,意味著java層傳遞下來的parcel data數據為空
  • 當拋出異常IllegalStateException: 代表BpBinder為空,意味著Native層的BpBinder已經被釋放
  • 當進入signalExceptionForError(): 根據transact執行具體情況拋出相應的異常,具體看signalExceptionForError內部實現
  • void signalExceptionForError(JNIEnv* env, jobject obj, status_t err, bool canThrowRemoteException, int parcelSize) {switch (err) {case UNKNOWN_ERROR:jniThrowException(env, "java/lang/RuntimeException", "Unknown error");break;case NO_MEMORY:jniThrowException(env, "java/lang/OutOfMemoryError", NULL);break;case INVALID_OPERATION:jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);break;case BAD_VALUE:jniThrowException(env, "java/lang/IllegalArgumentException", NULL);break;case BAD_INDEX:jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);break;case BAD_TYPE:jniThrowException(env, "java/lang/IllegalArgumentException", NULL);break;case NAME_NOT_FOUND:jniThrowException(env, "java/util/NoSuchElementException", NULL);break;case PERMISSION_DENIED:jniThrowException(env, "java/lang/SecurityException", NULL);break;case NOT_ENOUGH_DATA:jniThrowException(env, "android/os/ParcelFormatException", "Not enough data");break;case NO_INIT:jniThrowException(env, "java/lang/RuntimeException", "Not initialized");break;case ALREADY_EXISTS:jniThrowException(env, "java/lang/RuntimeException", "Item already exists");break;case DEAD_OBJECT:jniThrowException(env, canThrowRemoteException? "android/os/DeadObjectException": "java/lang/RuntimeException", NULL);break;case UNKNOWN_TRANSACTION:jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code");break;case FAILED_TRANSACTION: {ALOGE("!!! FAILED BINDER TRANSACTION !!! (parcel size = %d)", parcelSize);const char* exceptionToThrow;char msg[128];//transaction失敗的底層原因有可能很多種,這里無法確定是那種,后續binder driver會進一步完善if (canThrowRemoteException && parcelSize > 200*1024) {exceptionToThrow = "android/os/TransactionTooLargeException";snprintf(msg, sizeof(msg)-1, "data parcel size %d bytes", parcelSize);} else {exceptionToThrow = (canThrowRemoteException)? "android/os/DeadObjectException": "java/lang/RuntimeException";snprintf(msg, sizeof(msg)-1,"Transaction failed on small parcel; remote process probably died");}jniThrowException(env, exceptionToThrow, msg);} break;case FDS_NOT_ALLOWED:jniThrowException(env, "java/lang/RuntimeException","Not allowed to write file descriptors here");break;case UNEXPECTED_NULL:jniThrowNullPointerException(env, NULL);break;case -EBADF:jniThrowException(env, "java/lang/RuntimeException","Bad file descriptor");break;case -ENFILE:jniThrowException(env, "java/lang/RuntimeException","File table overflow");break;case -EMFILE:jniThrowException(env, "java/lang/RuntimeException","Too many open files");break;case -EFBIG:jniThrowException(env, "java/lang/RuntimeException","File too large");break;case -ENOSPC:jniThrowException(env, "java/lang/RuntimeException","No space left on device");break;case -ESPIPE:jniThrowException(env, "java/lang/RuntimeException","Illegal seek");break;case -EROFS:jniThrowException(env, "java/lang/RuntimeException","Read-only file system");break;case -EMLINK:jniThrowException(env, "java/lang/RuntimeException","Too many links");break;default:ALOGE("Unknown binder error code. 0x%" PRIx32, err);String8 msg;msg.appendFormat("Unknown binder error code. 0x%" PRIx32, err);jniThrowException(env, canThrowRemoteException? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());break;} } struct BinderProxyNativeData {// Both fields are constant and not null once javaObjectForIBinder returns this as// part of a BinderProxy.// The native IBinder proxied by this BinderProxy.sp<IBinder> mObject;// Death recipients for mObject. Reference counted only because DeathRecipients// hold a weak reference that can be temporarily promoted.sp<DeathRecipientList> mOrgue; // Death recipients for mObject. };...BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData); }...IBinder* target = getBPNativeData(env, obj)->mObject.get(); status_t err = target->transact(code, *data, reply, flags);

    從上述代碼可以看到,返回通過IBinder->transact接口返回err結果,IBinder->transact的接口可繼續查看:BpBinder.transact和IPC.transact里面的實現,關于BpBinder.transact和IPC.transact的詳細信息下面繼續介紹:

    BpBinder.transact

    [?BpBinder.cpp]

    status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {if (mAlive) {//[見小節2.6]status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);if (status == DEAD_OBJECT) mAlive = 0;return status;}return DEAD_OBJECT; }

    當binder死亡,則返回err=DEAD_OBJECT,所對應的拋出的異常為DeadObjectException

    ?

    IPC.transact

    [IPCThreadState.cpp]

    status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags) {status_t err = data.errorCheck(); //錯誤檢查flags |= TF_ACCEPT_FDS;if (err == NO_ERROR) {err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);}if (err != NO_ERROR) {if (reply) reply->setError(err);return (mLastError = err); //返回writeTransactionData的執行結果err}if ((flags & TF_ONE_WAY) == 0) {if (reply) {err = waitForResponse(reply); //} else {Parcel fakeReply;err = waitForResponse(&fakeReply);}} else {err = waitForResponse(NULL, NULL);}return err; //返回waitForResponse的執行結果err }

    返回值err的來源:

  • 返回err=DEAD_OBJECT
  • 返回writeTransactionData的執行結果err
  • 返回waitForResponse的執行結果err
  • ?

    IPC.waitForResponse

    [IPCThreadState.cpp]

    status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) {uint32_t cmd;int32_t err;while (1) {// 向Binder驅動寫入交互if ((err=talkWithDriver()) < NO_ERROR) break;err = mIn.errorCheck();...switch (cmd) {case BR_DEAD_REPLY:err = DEAD_OBJECT;goto finish;case BR_FAILED_REPLY:err = FAILED_TRANSACTION;goto finish;default:err = executeCommand(cmd); //[見小節2.7.1]if (err != NO_ERROR) goto finish;break;}}...return err; }

    當收到BR_DEAD_REPLY,則拋出err=DEAD_OBJECT

    當收到BR_FAILED_REPLY, 則拋出err=FAILED_TRANSACTION

    否則返回的是executeCommand的err

    ?

    IPC.executeCommand

    status_t IPCThreadState::executeCommand(int32_t cmd){BBinder* obj;RefBase::weakref_type* refs;status_t result = NO_ERROR;switch ((uint32_t)cmd) {case BR_ERROR://從mIn中讀取出錯誤碼result = mIn.readInt32();break;...default:result = UNKNOWN_ERROR;break;}return result;}

    talkWithDriver過程便會跟Binder驅動交互

    當服務端收到bind請求,則此時進入execTransact()過程。

    ?

    Binder.execTransact

    [Binder.java]

    private boolean execTransact(int code, long dataObj, long replyObj, int flags) {Parcel data = Parcel.obtain(dataObj);Parcel reply = Parcel.obtain(replyObj);boolean res;try {//執行onTransact方法[見小節3.1.1]res = onTransact(code, data, reply, flags);} catch (RemoteException e) {if ((flags & FLAG_ONEWAY) != 0) {Log.w(TAG, "Binder call failed.", e);} else {reply.setDataPosition(0);reply.writeException(e); //[見后續]}res = true;} catch (RuntimeException e) {if ((flags & FLAG_ONEWAY) != 0) {Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);} else {reply.setDataPosition(0);reply.writeException(e); //[見后續]}res = true;} catch (OutOfMemoryError e) {Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);RuntimeException re = new RuntimeException("Out of memory", e);reply.setDataPosition(0);reply.writeException(re); //[見后續]res = true;}//[見小節3.3]checkParcel(this, code, reply, "Unreasonably large binder reply buffer");reply.recycle();data.recycle();return res; }

    可以看到服務端發送異常有3大類:

  • RemoteException
  • RuntimeException
  • OutOfMemoryError
  • 還有一類見writeException

    writeException

    public final void writeException(Exception e) {int code = 0;if (e instanceof SecurityException) {code = EX_SECURITY;} else if (e instanceof BadParcelableException) {code = EX_BAD_PARCELABLE;} else if (e instanceof IllegalArgumentException) {code = EX_ILLEGAL_ARGUMENT;} else if (e instanceof NullPointerException) {code = EX_NULL_POINTER;} else if (e instanceof IllegalStateException) {code = EX_ILLEGAL_STATE;} else if (e instanceof NetworkOnMainThreadException) {code = EX_NETWORK_MAIN_THREAD;} else if (e instanceof UnsupportedOperationException) {code = EX_UNSUPPORTED_OPERATION;}writeInt(code); //寫入異常碼StrictMode.clearGatheredViolations();if (code == 0) {if (e instanceof RuntimeException) {throw (RuntimeException) e;}throw new RuntimeException(e);}writeString(e.getMessage()); }

    此處寫入的異常類型:

  • NullPointerException
  • SecurityException
  • BadParcelableException
  • IllegalArgumentException
  • IllegalStateException
  • NetworkOnMainThreadException
  • UnsupportedOperationException
  • ?

    checkParcel

    static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {// 檢查parcel數據是否大于800KBif (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {StringBuilder sb = new StringBuilder();sb.append(msg);sb.append(": on ");sb.append(obj);sb.append(" calling ");sb.append(code);sb.append(" size ");sb.append(parcel.dataSize());sb.append(" (data: ");parcel.setDataPosition(0);sb.append(parcel.readInt());sb.append(", ");sb.append(parcel.readInt());sb.append(", ");sb.append(parcel.readInt());sb.append(")");Slog.wtfStack(TAG, sb.toString());}}

    ?

    總結異常數據傳輸流程如下圖:

    ?

    結論:小米手機發出安全異常是binder服務端發出的,廠商設置了權限無法訪問。

    總結

    以上是生活随笔為你收集整理的IBinder获取手机服务信息异常的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 99精品免费视频 | 美日韩精品一区二区 | 99re免费视频精品全部 | 欧美日韩色图 | 国产强被迫伦姧在线观看无码 | 另类二区| 极品美女销魂一区二区三区 | 欧美日韩亚洲激情 | 亚洲精品国产一区二区 | 久草免费福利 | 草草影院在线观看视频 | 久草免费看 | 国产三级免费观看 | 91亚洲国产成人精品一区二三 | 偷拍视频一区二区 | 国产a级免费视频 | 欧美色88| 亚洲精品国产精品乱码桃花 | 激情视频一区二区三区 | 丁香婷婷成人 | 大尺度电影在线 | 中文字幕第七页 | 久久久久免费精品视频 | 日本理论片 | 91麻豆精品国产理伦片在线观看 | 欧美日韩亚洲国产精品 | 国产偷人爽久久久久久老妇app | 97精品人人a片免费看 | 天天干天天色 | 国产又粗又猛又大爽 | 欧美黄片一区二区三区 | 国产一级淫片a | 先锋资源一区二区 | 无码人妻精品一区二区三区夜夜嗨 | 在线观看成人 | 777欧美 | 国产亚洲精品久久久久四川人 | 午夜视频免费看 | 亚洲好骚综合 | 99热一区二区三区 | √资源天堂中文在线 | 一级免费看片 | 欧美日韩久久久久久 | 天天爽一爽 | 国产女厕一区二区三区在线视 | 美女张开腿让男人操 | 日韩欧美高清一区 | 婷婷爱五月 | av免费网 | 欧美无砖砖区免费 | 99热这里只有精品7 青青草社区 | 一区二区三区精彩视频 | 欧美性爱精品在线 | 国产经典自拍 | 两女双腿交缠激烈磨豆腐 | 天天天天天干 | 亚洲成色在线 | 国产乱淫av一区二区三区 | 久久久久国产精品无码免费看 | 国产成人精品亚洲男人的天堂 | 国产一区视频在线 | 91av国产在线 | 97se.com| 久久最新网址 | 一区二区三区www | 日本学生初尝黑人巨免费视频 | 中文国语毛片高清视频 | 无码人妻精品一区二区三区99不卡 | 欧美粗又大 | 国产成人av无码精品 | 国产精品日韩电影 | 久久无码视频一区 | 影音先锋二区 | 永久免费视频网站直接看 | 日本wwwxxx | 不卡二区| 国产在线欧美在线 | 丝袜操 | 日韩影院在线 | 1769国产精品视频 | 播播开心激情网 | 亚洲AV无码一区二区三区性 | 免费观看成人在线视频 | 中文字幕免费在线播放 | www.精品 | 户外少妇对白啪啪野战 | 三级性生活片 | 午夜伦伦 | 国产一级α片 | 快色在线观看 | 成人在线高清 | 日日噜噜夜夜狠狠久久波多野 | 中文字幕在线看高清电影 | 野花中文免费观看6 | 国产精品久久久久免费 | 奇米影视盒 | 日韩在线观看 | 91精品视频免费观看 | 中韩毛片 |