You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android R设置APP热点模块TetheringManager内存泄漏修复咨询

Android R TetheringManager内存泄漏修复方案

问题概述

在Android R系统的设置APP(热点与网络共享模块)中,使用TetheringManager时存在内存泄漏问题:

  • TetheringManager构造函数中调用registerTetheringEventCallback注册回调,但未提供对应的反注册逻辑
  • 性能分析工具检测到mTetheringEventCallback被TetheringManager持有强引用,导致TetherSettings页面实例无法被GC回收

问题代码分析

原TetheringManager构造函数代码:

@SystemApi(client = MODULE_LIBRARIES)
public TetheringManager(@NonNull final Context context,
        @NonNull Supplier<IBinder> connectorSupplier) {
    mContext = context;
    mCallback = new TetheringCallbackInternal(this);
    mConnectorSupplier = connectorSupplier;

    final String pkgName = mContext.getOpPackageName();

    final IBinder connector = mConnectorSupplier.get();
    // If the connector is available on start, do not start a polling thread. This introduces
    // differences in the thread that sends the oneway binder calls to the service between the
    // first few seconds after boot and later, but it avoids always having differences between
    // the first usage of TetheringManager from a process and subsequent usages (so the
    // difference is only on boot). On boot binder calls may be queued until the service comes
    // up and be sent from a worker thread; later, they are always sent from the caller thread.
    // Considering that it's just oneway binder calls, and ordering is preserved, this seems
    // better than inconsistent behavior persisting after boot.
    if (connector != null) {
        mConnector = ITetheringConnector.Stub.asInterface(connector);
    } else {
        startPollingForConnector();
    }
    
    getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName));
}

修复方案

方案1:系统级源码修复(最优解)

修改TetheringManager源码,添加反注册方法并要求调用方主动释放:

  1. 在TetheringManager中添加反注册方法:
@SystemApi(client = MODULE_LIBRARIES)
public void unregisterTetheringEventCallback() {
    getConnector(c -> c.unregisterTetheringEventCallback(mCallback));
}

// 可选:添加finalize方法作为兜底(注意finalize已过时,仅用于兼容旧逻辑)
@Deprecated
@Override
protected void finalize() throws Throwable {
    try {
        unregisterTetheringEventCallback();
    } finally {
        super.finalize();
    }
}
  1. 在TetherSettings的页面销毁生命周期中调用反注册:
@Override
protected void onDestroy() {
    super.onDestroy();
    if (mTetheringManager != null) {
        mTetheringManager.unregisterTetheringEventCallback();
    }
}

方案2:APP层面反射兼容(无法修改系统源码时使用)

通过反射调用系统内部接口完成反注册,避免内存泄漏:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mTetheringManager != null) {
        try {
            // 反射获取mCallback实例
            Field callbackField = TetheringManager.class.getDeclaredField("mCallback");
            callbackField.setAccessible(true);
            Object tetheringCallback = callbackField.get(mTetheringManager);
            
            // 反射获取mConnector实例
            Field connectorField = TetheringManager.class.getDeclaredField("mConnector");
            connectorField.setAccessible(true);
            ITetheringConnector connector = (ITetheringConnector) connectorField.get(mTetheringManager);
            
            if (connector != null && tetheringCallback != null) {
                // 调用反注册接口
                connector.unregisterTetheringEventCallback(tetheringCallback);
            }
        } catch (NoSuchFieldException | IllegalAccessException | RemoteException e) {
            // 捕获异常,避免页面崩溃
            e.printStackTrace();
        }
    }
}

内容的提问来源于stack exchange,提问作者Judy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:03:37