测试某机器Android系统Binder数据传输大小限制

以下是一个简单的 Android 示例,用于测试 Binder 传输数据限制。该示例包含一个服务(Service),通过 Binder 机制与客户端(Activity)进行通信,并逐步增加传输的数据量,以确定触发 TransactionTooLargeException 异常(表示超过 Binder 传输限制)时的数据大小。

1. 创建 AIDL 文件

在 Android Studio 中,右键点击 app/src/main 目录,选择 New -> AIDL -> AIDL File,创建一个名为 IBinderTest.aidl 的文件,内容如下:

aidl 复制代码
// IBinderTest.aidl
package com.example.binderlimitdemo;

interface IBinderTest {
    void sendLargeData(in byte[] data);
}

AIDL(Android Interface Definition Language)用于定义跨进程通信的接口,这里定义了一个方法 sendLargeData 用于接收字节数组数据。

2. 创建服务类

创建一个继承自 Service 的类 BinderTestService,实现上述 AIDL 定义的接口:

java 复制代码
package com.example.binderlimitdemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class BinderTestService extends Service {
    private static final String TAG = "BinderTestService";

    // 继承自AIDL生成的Stub类,实现接口方法
    private final IBinderTest.Stub binder = new IBinderTest.Stub() {
        @Override
        public void sendLargeData(byte[] data) throws RemoteException {
            // 这里可以添加实际的业务逻辑,我们测试时只打印数据长度
            Log.d(TAG, "Received data length: " + data.length);
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
}

3. 在 AndroidManifest.xml 中注册服务

app/src/main/AndroidManifest.xml 文件中添加服务的注册声明:

注意:BinderTestService要设置独立进程,否则不会触发binder大小限制,试过不设置进程demo干到anr了。

ini 复制代码
<service
    android:name=".BinderTestService"
    android:enabled="true"
    android:process=":binder_test"
    android:exported="true">
</service>

4. 创建测试 Activity

创建一个 MainActivity 用于测试 Binder 传输,逐步增加数据量并尝试发送:

java 复制代码
package com.example.binderlimitdemo;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private IBinderTest binderTest;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            binderTest = IBinderTest.Stub.asInterface(service);
            testBinderLimit();
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            binderTest = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button startButton = findViewById(R.id.start_button);
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, BinderTestService.class);
                bindService(intent, connection, Context.BIND_AUTO_CREATE);
            }
        });
    }

    private void testBinderLimit() {
        int size = 1024 * 100; // 初始数据大小设为100KB,可根据需要调整起始值
        while (true) {
            byte[] data = new byte[size];
            try {
                binderTest.sendLargeData(data);
                Log.d(TAG, "Successfully sent data of size: " + size + " bytes");
                size += 1024 * 100; // 每次增加100KB
            } catch (RemoteException e) {
                if (e instanceof android.os.TransactionTooLargeException) {
                    Log.e(TAG, "Reached Binder transaction size limit at size: " + size + " bytes", e);
                } else {
                    Log.e(TAG, "RemoteException", e);
                }
                break;
            }
        }
        unbindService(connection);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (connection != null) {
            unbindService(connection);
        }
    }
}

5. 布局文件(activity_main.xml)

res/layout 目录下的 activity_main.xml 文件中,添加一个按钮用于启动测试:

xml

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Binder Limit Test" />

</LinearLayout>

运行该应用,点击按钮后,应用会逐步增加通过 Binder 传输的数据量,直到触发 TransactionTooLargeException 异常,此时日志中会记录下达到 Binder 传输大小限制时的数据量。

测试log如下,该系统上限制是 1024000 bytes左右,系统提示限制1040384 bytes,真实限制在1040288 bytes,比系统提示少 96 bytes 。
text 复制代码
int size = 1024 * 1015;
Successfully sent data of size: 1039360 bytes
int size = 1024 * 1016;
com.example.myapplication            E  !!! FAILED BINDER TRANSACTION !!!  (parcel size = 1040480)
com.example.myapplication            E  Reached Binder transaction size limit at size: 1040384 bytes

请注意,以上代码基于 Android 平台,运行时需要 Android 设备或模拟器,并且实际的 Binder 传输大小限制可能因设备和系统版本的不同而有所差异。

相关推荐
齊家治國平天下3 分钟前
AAOS 电源管理深度解析:休眠/唤醒/功耗优化
android·车载系统·aaos·aosp·电源管理·休眠唤醒·carpowermanager
Xzaveir28 分钟前
企业号码展示不可观测怎么办:状态机、拨测事件与异常回放
android·人工智能
2501_9160074737 分钟前
iOS和macOS应用程序性能分析和优化工具使用综合指南
android·macos·ios·小程序·uni-app·iphone·webview
黄林晴1 小时前
Nearby Connections 重大变更:不再自动开启 Wi-Fi / 蓝牙,适配指南
android
恋猫de小郭2 小时前
Flutter 全新真 3D 实现,用 flutter_scene 能开发一个「我的世界」
android·前端·flutter
HLC++15 小时前
Linux的进程间通信
android·linux·服务器
爱笑鱼18 小时前
Binder(二):AIDL 生成的 Proxy、Stub 和 Parcel 到底在做什么?
android
爱笑鱼19 小时前
Binder(一):一次方法调用,究竟怎样跨进程执行?
android
壮哥_icon19 小时前
【Android 系统开发】使用 BAT 脚本高效自动化管理 /system/priv-app/ 系统应用(安装与卸载)
android·运维·自动化
用户693717500138421 小时前
Claude Code终端日志Token占用实测:一个过滤器砍掉60%-90%
android·前端·后端