17ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/*
27ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Copyright (C) 2011 The Android Open Source Project
37ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
47ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
57ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * you may not use this file except in compliance with the License.
67ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * You may obtain a copy of the License at
77ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
87ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
97ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk *
107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * Unless required by applicable law or agreed to in writing, software
117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * See the License for the specific language governing permissions and
147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * limitations under the License.
157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkpackage com.android.settingslib.bluetooth;
187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothAdapter;
207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothClass;
217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothDevice;
227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothPan;
237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.bluetooth.BluetoothProfile;
247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.content.Context;
257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport android.util.Log;
267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport com.android.settingslib.R;
287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.HashMap;
307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monkimport java.util.List;
317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk/**
337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk * PanProfile handles Bluetooth PAN profile (NAP and PANU).
347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk */
3560598075a0d54dcb4287d77c91b946e6c407a669Andre Eisenbachpublic final class PanProfile implements LocalBluetoothProfile {
367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final String TAG = "PanProfile";
377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static boolean V = true;
387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private BluetoothPan mService;
407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private boolean mIsProfileReady;
417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // Tethering direction for each device
437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final HashMap<BluetoothDevice, Integer> mDeviceRoleMap =
447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            new HashMap<BluetoothDevice, Integer>();
457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    static final String NAME = "PAN";
477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // Order of this profile in device profiles list
497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private static final int ORDINAL = 4;
507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // These callbacks run on the main thread.
527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    private final class PanServiceListener
537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            implements BluetoothProfile.ServiceListener {
547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public void onServiceConnected(int profile, BluetoothProfile proxy) {
567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (V) Log.d(TAG,"Bluetooth service connected");
577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mService = (BluetoothPan) proxy;
587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mIsProfileReady=true;
597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        public void onServiceDisconnected(int profile) {
627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            if (V) Log.d(TAG,"Bluetooth service disconnected");
637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            mIsProfileReady=false;
647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public boolean isProfileReady() {
687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mIsProfileReady;
697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    PanProfile(Context context) {
727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        adapter.getProfileProxy(context, new PanServiceListener(),
747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                BluetoothProfile.PAN);
757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public boolean isConnectable() {
787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return true;
797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public boolean isAutoConnectable() {
827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return false;
837ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
847ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
857ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public boolean connect(BluetoothDevice device) {
867ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (mService == null) return false;
877ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        List<BluetoothDevice> sinks = mService.getConnectedDevices();
887ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (sinks != null) {
897ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            for (BluetoothDevice sink : sinks) {
907ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mService.disconnect(sink);
917ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
927ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
937ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mService.connect(device);
947ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
957ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
967ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public boolean disconnect(BluetoothDevice device) {
977ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (mService == null) return false;
987ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mService.disconnect(device);
997ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1007ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1017ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public int getConnectionStatus(BluetoothDevice device) {
1027ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (mService == null) {
1037ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return BluetoothProfile.STATE_DISCONNECTED;
1047ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1057ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return mService.getConnectionState(device);
1067ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1077ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1087ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public boolean isPreferred(BluetoothDevice device) {
10960598075a0d54dcb4287d77c91b946e6c407a669Andre Eisenbach        return true;
1107ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1117ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1127ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public int getPreferred(BluetoothDevice device) {
1137ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return -1;
1147ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1157ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1167ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public void setPreferred(BluetoothDevice device, boolean preferred) {
1177ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        // ignore: isPreferred is always true for PAN
1187ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1197ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1207ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public String toString() {
1217ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return NAME;
1227ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1237ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1247ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public int getOrdinal() {
1257ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return ORDINAL;
1267ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1277ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1287ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public int getNameResource(BluetoothDevice device) {
1297ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (isLocalRoleNap(device)) {
1307ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return R.string.bluetooth_profile_pan_nap;
1317ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        } else {
1327ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return R.string.bluetooth_profile_pan;
1337ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1347ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1357ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1367ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public int getSummaryResourceForDevice(BluetoothDevice device) {
1377ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        int state = getConnectionStatus(device);
1387ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        switch (state) {
1397ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            case BluetoothProfile.STATE_DISCONNECTED:
1407ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                return R.string.bluetooth_pan_profile_summary_use_for;
1417ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1427ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            case BluetoothProfile.STATE_CONNECTED:
1437ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                if (isLocalRoleNap(device)) {
1447ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return R.string.bluetooth_pan_nap_profile_summary_connected;
1457ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                } else {
1467ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                    return R.string.bluetooth_pan_user_profile_summary_connected;
1477ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                }
1487ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1497ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            default:
1507ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                return Utils.getConnectionStateSummary(state);
1517ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1527ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1537ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1547ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    public int getDrawableResource(BluetoothClass btClass) {
1557ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        return R.drawable.ic_bt_network_pan;
1567ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1577ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1587ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    // Tethering direction determines UI strings.
1597ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    void setLocalRole(BluetoothDevice device, int role) {
1607ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        mDeviceRoleMap.put(device, role);
1617ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1627ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1637ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    boolean isLocalRoleNap(BluetoothDevice device) {
1647ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (mDeviceRoleMap.containsKey(device)) {
1657ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return mDeviceRoleMap.get(device) == BluetoothPan.LOCAL_NAP_ROLE;
1667ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        } else {
1677ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            return false;
1687ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1697ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1707ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk
1717ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    protected void finalize() {
1727ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (V) Log.d(TAG, "finalize()");
1737ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        if (mService != null) {
1747ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            try {
1757ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.PAN, mService);
1767ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                mService = null;
1777ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }catch (Throwable t) {
1787ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk                Log.w(TAG, "Error cleaning up PAN proxy", t);
1797ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk            }
1807ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk        }
1817ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk    }
1827ce96b9e610de2782ec5f2af806e7bc0f90c8578Jason Monk}
183