Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50269bef authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Fix binder leakage when turning off Bluetooth"

parents 5333210f d011546a
Loading
Loading
Loading
Loading
+86 −227
Original line number Diff line number Diff line
@@ -22,23 +22,16 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
@@ -209,43 +202,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
    @UnsupportedAppUsage
    public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;

    private Context mContext;
    private ServiceListener mServiceListener;
    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
    @GuardedBy("mServiceLock")
    private IBluetoothA2dp mService;
    private BluetoothAdapter mAdapter;

    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
            new IBluetoothStateChangeCallback.Stub() {
                public void onBluetoothStateChange(boolean up) {
                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
                    if (!up) {
                        if (VDBG) Log.d(TAG, "Unbinding service...");
                        try {
                            mServiceLock.writeLock().lock();
                            if (mService != null) {
                                mService = null;
                                mContext.unbindService(mConnection);
                            }
                        } catch (Exception re) {
                            Log.e(TAG, "", re);
                        } finally {
                            mServiceLock.writeLock().unlock();
                        }
                    } else {
                        try {
                            mServiceLock.readLock().lock();
                            if (mService == null) {
                                if (VDBG) Log.d(TAG, "Binding service...");
                                doBind();
                            }
                        } catch (Exception re) {
                            Log.e(TAG, "", re);
                        } finally {
                            mServiceLock.readLock().unlock();
                        }
                    }
    private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
            new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
                    IBluetoothA2dp.class.getName()) {
                @Override
                public IBluetoothA2dp getServiceInterface(IBinder service) {
                    return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
                }
    };

@@ -253,57 +216,18 @@ public final class BluetoothA2dp implements BluetoothProfile {
     * Create a BluetoothA2dp proxy object for interacting with the local
     * Bluetooth A2DP service.
     */
    /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
        mContext = context;
        mServiceListener = l;
    /*package*/ BluetoothA2dp(Context context, ServiceListener listener) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException e) {
                Log.e(TAG, "", e);
            }
        }

        doBind();
    }

    boolean doBind() {
        Intent intent = new Intent(IBluetoothA2dp.class.getName());
        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
        intent.setComponent(comp);
        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
                UserHandle.CURRENT_OR_SELF)) {
            Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
            return false;
        }
        return true;
        mProfileConnector.connect(context, listener);
    }

    @UnsupportedAppUsage
    /*package*/ void close() {
        mServiceListener = null;
        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            }
        mProfileConnector.disconnect();
    }

        try {
            mServiceLock.writeLock().lock();
            if (mService != null) {
                mService = null;
                mContext.unbindService(mConnection);
            }
        } catch (Exception re) {
            Log.e(TAG, "", re);
        } finally {
            mServiceLock.writeLock().unlock();
        }
    private IBluetoothA2dp getService() {
        return mProfileConnector.getService();
    }

    @Override
@@ -333,17 +257,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public boolean connect(BluetoothDevice device) {
        if (DBG) log("connect(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled() && isValidDevice(device)) {
                return mService.connect(device);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled() && isValidDevice(device)) {
                return service.connect(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return false;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return false;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -376,17 +298,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public boolean disconnect(BluetoothDevice device) {
        if (DBG) log("disconnect(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled() && isValidDevice(device)) {
                return mService.disconnect(device);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled() && isValidDevice(device)) {
                return service.disconnect(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return false;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return false;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -397,17 +317,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public List<BluetoothDevice> getConnectedDevices() {
        if (VDBG) log("getConnectedDevices()");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                return mService.getConnectedDevices();
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return service.getConnectedDevices();
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return new ArrayList<BluetoothDevice>();
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return new ArrayList<BluetoothDevice>();
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -418,17 +336,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        if (VDBG) log("getDevicesMatchingStates()");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                return mService.getDevicesMatchingConnectionStates(states);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return service.getDevicesMatchingConnectionStates(states);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return new ArrayList<BluetoothDevice>();
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return new ArrayList<BluetoothDevice>();
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -439,18 +355,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public int getConnectionState(BluetoothDevice device) {
        if (VDBG) log("getState(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()
                    && isValidDevice(device)) {
                return mService.getConnectionState(device);
                return service.getConnectionState(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return BluetoothProfile.STATE_DISCONNECTED;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return BluetoothProfile.STATE_DISCONNECTED;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -480,18 +394,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public boolean setActiveDevice(@Nullable BluetoothDevice device) {
        if (DBG) log("setActiveDevice(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()
                    && ((device == null) || isValidDevice(device))) {
                return mService.setActiveDevice(device);
                return service.setActiveDevice(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return false;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return false;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -511,17 +423,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public BluetoothDevice getActiveDevice() {
        if (VDBG) log("getActiveDevice()");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                return mService.getActiveDevice();
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return service.getActiveDevice();
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return null;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return null;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -543,22 +453,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public boolean setPriority(BluetoothDevice device, int priority) {
        if (DBG) log("setPriority(" + device + ", " + priority + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()
                    && isValidDevice(device)) {
                if (priority != BluetoothProfile.PRIORITY_OFF
                        && priority != BluetoothProfile.PRIORITY_ON) {
                    return false;
                }
                return mService.setPriority(device, priority);
                return service.setPriority(device, priority);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return false;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return false;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -578,18 +486,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public int getPriority(BluetoothDevice device) {
        if (VDBG) log("getPriority(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()
                    && isValidDevice(device)) {
                return mService.getPriority(device);
                return service.getPriority(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return BluetoothProfile.PRIORITY_OFF;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return BluetoothProfile.PRIORITY_OFF;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -602,17 +508,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public boolean isAvrcpAbsoluteVolumeSupported() {
        if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                return mService.isAvrcpAbsoluteVolumeSupported();
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return service.isAvrcpAbsoluteVolumeSupported();
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return false;
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
            return false;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -625,15 +529,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public void setAvrcpAbsoluteVolume(int volume) {
        if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                mService.setAvrcpAbsoluteVolume(volume);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                service.setAvrcpAbsoluteVolume(volume);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -646,18 +548,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
     */
    public boolean isA2dpPlaying(BluetoothDevice device) {
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()
                    && isValidDevice(device)) {
                return mService.isA2dpPlaying(device);
                return service.isA2dpPlaying(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return false;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return false;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -694,19 +594,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
    public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
        if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                return mService.getCodecStatus(device);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return service.getCodecStatus(device);
            }
            if (mService == null) {
            if (service == null) {
                Log.w(TAG, "Proxy not attached to service");
            }
            return null;
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
            return null;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -723,17 +621,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
                                         BluetoothCodecConfig codecConfig) {
        if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
                mService.setCodecConfigPreference(device, codecConfig);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                service.setCodecConfigPreference(device, codecConfig);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return;
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
            return;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -772,21 +668,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
     */
    private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()) {
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                if (enable) {
                    mService.enableOptionalCodecs(device);
                    service.enableOptionalCodecs(device);
                } else {
                    mService.disableOptionalCodecs(device);
                    service.disableOptionalCodecs(device);
                }
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return;
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
            return;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -801,17 +695,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    @UnsupportedAppUsage
    public int supportsOptionalCodecs(BluetoothDevice device) {
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled() && isValidDevice(device)) {
                return mService.supportsOptionalCodecs(device);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled() && isValidDevice(device)) {
                return service.supportsOptionalCodecs(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
            return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -826,17 +718,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
    @UnsupportedAppUsage
    public int getOptionalCodecsEnabled(BluetoothDevice device) {
        try {
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled() && isValidDevice(device)) {
                return mService.getOptionalCodecsEnabled(device);
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled() && isValidDevice(device)) {
                return service.getOptionalCodecsEnabled(device);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return OPTIONAL_CODECS_PREF_UNKNOWN;
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
            return OPTIONAL_CODECS_PREF_UNKNOWN;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -858,18 +748,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
                Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
                return;
            }
            mServiceLock.readLock().lock();
            if (mService != null && isEnabled()
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()
                    && isValidDevice(device)) {
                mService.setOptionalCodecsEnabled(device, value);
                service.setOptionalCodecsEnabled(device, value);
            }
            if (mService == null) Log.w(TAG, "Proxy not attached to service");
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return;
        } catch (RemoteException e) {
            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
            return;
        } finally {
            mServiceLock.readLock().unlock();
        }
    }

@@ -900,35 +788,6 @@ public final class BluetoothA2dp implements BluetoothProfile {
        }
    }

    private final ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (DBG) Log.d(TAG, "Proxy object connected");
            try {
                mServiceLock.writeLock().lock();
                mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
            } finally {
                mServiceLock.writeLock().unlock();
            }

            if (mServiceListener != null) {
                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            if (DBG) Log.d(TAG, "Proxy object disconnected");
            try {
                mServiceLock.writeLock().lock();
                mService = null;
            } finally {
                mServiceLock.writeLock().unlock();
            }
            if (mServiceListener != null) {
                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
            }
        }
    };

    private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
+22 −106

File changed.

Preview size limit exceeded, changes collapsed.

+26 −103

File changed.

Preview size limit exceeded, changes collapsed.

+19 −21
Original line number Diff line number Diff line
@@ -337,20 +337,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
                public void onBluetoothStateChange(boolean up) {
                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
                    if (!up) {
                        if (VDBG) Log.d(TAG, "Unbinding service...");
                        doUnbind();
                    } else {
                        synchronized (mConnection) {
                            try {
                                if (mService == null) {
                                    if (VDBG) Log.d(TAG, "Binding service...");
                        doBind();
                    }
                            } catch (Exception re) {
                                Log.e(TAG, "", re);
                            }
                        }
                    }
                }
            };

@@ -374,24 +364,32 @@ public final class BluetoothHeadset implements BluetoothProfile {
        doBind();
    }

    boolean doBind() {
    private boolean doBind() {
        synchronized (mConnection) {
            if (mService == null) {
                if (VDBG) Log.d(TAG, "Binding service...");
                try {
                    return mAdapter.getBluetoothManager().bindBluetoothProfileService(
                            BluetoothProfile.HEADSET, mConnection);
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to bind HeadsetService", e);
                }
            }
        }
        return false;
    }

    void doUnbind() {
    private void doUnbind() {
        synchronized (mConnection) {
            if (mService != null) {
                if (VDBG) Log.d(TAG, "Unbinding service...");
                try {
                    mAdapter.getBluetoothManager().unbindBluetoothProfileService(
                            BluetoothProfile.HEADSET, mConnection);
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to unbind HeadsetService", e);
                } finally {
                    mService = null;
                }
            }
        }
@@ -411,8 +409,8 @@ public final class BluetoothHeadset implements BluetoothProfile {
        if (mgr != null) {
            try {
                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            } catch (RemoteException re) {
                Log.e(TAG, "", re);
            }
        }
        mServiceListener = null;
@@ -1169,7 +1167,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (DBG) Log.d(TAG, "Proxy object disconnected");
            mService = null;
            doUnbind();
            mHandler.sendMessage(mHandler.obtainMessage(
                    MESSAGE_HEADSET_SERVICE_DISCONNECTED));
        }
+64 −131

File changed.

Preview size limit exceeded, changes collapsed.

Loading