Android压力测试不停开启关闭蓝牙报错

51 篇文章 2 订阅
8 篇文章 0 订阅

问题分析

报错log信息如下

09-28 13:06:08.697706 30214 30214 E AndroidRuntime: FATAL EXCEPTION: main
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: Process: com.android.music, PID: 30214
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: java.lang.RuntimeException: Unable to create service com.android.music.MediaPlaybackService: java.lang.NullPointerException: Attempt to invoke interface method 'android.media.session.ISessionController android.media.session.ISession.getController()' on a null object reference
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.app.ActivityThread.handleCreateService(ActivityThread.java:4264)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.app.ActivityThread.access$1700(ActivityThread.java:244)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1995)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.os.Looper.loop(Looper.java:223)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7740)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.media.session.ISessionController android.media.session.ISession.getController()' on a null object reference
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.media.session.MediaSession.<init>(MediaSession.java:199)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.media.session.MediaSession.<init>(MediaSession.java:156)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at com.android.music.MediaPlaybackService.onCreate(MediaPlaybackService.java:45)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: at android.app.ActivityThread.handleCreateService(ActivityThread.java:4252)
09-28 13:06:08.697706 30214 30214 E AndroidRuntime: ... 8 more

从报错的log中和截图中看应该是打开蓝牙的时候会触发打开 Android Open Source Music Playback Service,从而导致的报错

<service android:name="com.android.music.MediaPlaybackService"
         android:exported="true"
         android:label="Android Open Source Music Playback Service">
    <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService" />
    </intent-filter>
</service>

packages/apps/Music/src/com/android/music/MediaPlaybackService.java

mSession = new MediaSession(this, "MediaPlaybackService");

frameworks/base/media/java/android/media/session/MediaSession.java

try {
    mBinder = manager.createSession(mCbStub, tag, sessionInfo);             
    mSessionToken = new Token(Process.myUid(), mBinder.getController());    // mBinder为空导致的报错,说明上面createSession没有成功
    mController = new MediaController(context, mSessionToken);
} catch (RemoteException e) {
    throw new RuntimeException("Remote error creating session.", e);
}

为什么 createSession 没有成功? 因为创建了太多的session了,导致报错,和问题中的描述一致
frameworks/base/services/core/java/com/android/server/media/MediaSessionService.java

@Override
public ISession createSession(String packageName, ISessionCallback cb, String tag,
        Bundle sessionInfo, int userId) throws RemoteException {
    final int pid = Binder.getCallingPid();
    final int uid = Binder.getCallingUid();
    final long token = Binder.clearCallingIdentity();
    try {
        enforcePackageName(packageName, uid);
        int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
                false /* allowAll */, true /* requireFull */, "createSession", packageName);
        if (cb == null) {
            throw new IllegalArgumentException("Controller callback cannot be null");
        }
        MediaSessionRecord session = createSessionInternal(
                pid, uid, resolvedUserId, packageName, cb, tag, sessionInfo);
        if (session == null) {
            throw new IllegalStateException("Failed to create a new session record");
        }
        ISession sessionBinder = session.getSessionBinder();
        if (sessionBinder == null) {
            throw new IllegalStateException("Invalid session record");
        }
        return sessionBinder;
    } catch (Exception e) {
        Slog.w(TAG, "Exception in creating a new session", e);              //通过这行log在sys_log中找到了关键信息
        throw e;
    } finally {
        Binder.restoreCallingIdentity(token);
    }
}

mobilelog/APLog_2021_0103_082059__1/sys_log_105__2021_0929_022307

09-28 18:45:47.365026   745  3090 W MediaSessionService: Exception in creating a new session
09-28 18:45:47.365026   745  3090 W MediaSessionService: java.lang.RuntimeException: Created too many sessions. count=100)      //创建了太多的session了,导致报错,和问题中的描述一致
09-28 18:45:47.365026   745  3090 W MediaSessionService: at com.android.server.media.MediaSessionService.createSessionInternal(MediaSessionService.java:601)
09-28 18:45:47.365026   745  3090 W MediaSessionService: at com.android.server.media.MediaSessionService.access$2400(MediaSessionService.java:105)
09-28 18:45:47.365026   745  3090 W MediaSessionService: at com.android.server.media.MediaSessionService$SessionManagerImpl.createSession(MediaSessionService.java:1144)
09-28 18:45:47.365026   745  3090 W MediaSessionService: at android.media.session.ISessionManager$Stub.onTransact(ISessionManager.java:289)
09-28 18:45:47.365026   745  3090 W MediaSessionService: at android.os.Binder.execTransactInternal(Binder.java:1154)
09-28 18:45:47.365026   745  3090 W MediaSessionService: at android.os.Binder.execTransact(Binder.java:1123)
09-28 18:45:47.411609   745   791 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: TURNING_ON > ON
09-28 18:45:47.412572   745   791 D BluetoothManagerService: Broadcasting onBluetoothStateChange(true) to 24 receivers.
09-28 18:45:47.419077   745   791 D BluetoothManagerService: Creating new ProfileServiceConnections object for profile: 1

然后找到下面这段代码,目前肯定是满足了第一个条件,private static final int SESSION_CREATION_LIMIT_PER_UID = 100;

if (sessionCount >= SESSION_CREATION_LIMIT_PER_UID
        && !hasMediaControlPermission(callerPid, callerUid)) {
    throw new RuntimeException("Created too many sessions. count="
            + sessionCount + ")");
}

private boolean hasMediaControlPermission(int pid, int uid) {
    // Check if it's system server or has MEDIA_CONTENT_CONTROL.
    // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
    // check here.
    if (uid == Process.SYSTEM_UID || mContext.checkPermission(
            android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
            == PackageManager.PERMISSION_GRANTED) {
        return true;
    } else if (DEBUG) {
        Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
    }
    return false;
}

要满足第二个条件hasMediaControlPermission(),只有sharedUserId=system(platform签名),或者有media_content_control权限的应用才可以,尝试了给 Music 添加media_content_control权限无果,不知道问题出在哪里,有兴趣的朋友可以自己尝试一下

最终修改方案

1.不预置music应用
2.或给Music应用添加platform的签名
packages/apps/Music/Android.bp

android_app {
    name: "Music",
    srcs: ["src/**/*.java"],
    sdk_version: "current",
    product_specific: true,
    certificate: "platform",// 添加platform签名
    optimize: {
        proguard_flags_files: ["proguard.flags"],
    },
}

测试方法

1.修改 MediaSessionService.java 中的 SESSION_CREATION_LIMIT_PER_UID = 5; //可以减少测试次数
2.在 final int sessionCount = user.mUidToSessionCount.get(callerUid, 0); 后面添加如下log

android.util.Log.e(TAG, "Time:2021-10-14 15:44:03-->"+Thread.currentThread().getStackTrace()[2].getClassName()+"-->"+Thread.currentThread().getStackTrace()[2].getMethodName()+"()-->"+Thread.currentThread().getStackTrace()[2].getLineNumber()+" sessionCount:"+sessionCount+" hasMediaControlPermission:"+hasMediaControlPermission);

3.运行自己写的脚本 runTest bt

echo "run BT test begin!"
for (( i = 0; i < 10000; i++ )); do
    adb shell svc bluetooth enable
    echo "enable bluetooth for $i times!"
    sleep 2
    adb shell svc bluetooth disable
    echo "disable bluetooth for $i times!"
    sleep 2
done
echo "run BT test end!"

有几个疑问

1.为什么打开关闭蓝牙的时候没有关闭session?如何关闭session?
2.为什么google的Music不会有这个问题?
3.SESSION_CREATION_LIMIT_PER_UID = 100; 这个值是否可以改大?
4.有权限之后,session可以无限创建吗?会不会OOM或者且他问题?

欢迎大家一起学习讨论~~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值