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

Commit b445362b authored by Robert Greenwalt's avatar Robert Greenwalt
Browse files

Make upstream tether list threadsafe

Outsiders asking for this list may cause the list to change on another thread.
Fixing general synchronization issues.

bug:5531630
Change-Id: I7a3ee0bba3db40f45bcb0159491942fa4cf38c37
parent 7311bd4b
Loading
Loading
Loading
Loading
+172 −131
Original line number Diff line number Diff line
@@ -81,6 +81,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    private String[] mTetherableBluetoothRegexs;
    private Collection<Integer> mUpstreamIfaceTypes;

    // used to synchronize public access to members
    private Object mPublicSync;

    private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
    private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
    private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
@@ -135,6 +138,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        mConnService = connService;
        mLooper = looper;

        mPublicSync = new Object();

        mIfaces = new HashMap<String, TetherInterfaceSM>();

        // make our own thread so we don't anr the system
@@ -172,18 +177,25 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    }

    void updateConfiguration() {
        mTetherableUsbRegexs = mContext.getResources().getStringArray(
        String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_tether_usb_regexs);
        mTetherableWifiRegexs = mContext.getResources().getStringArray(
        String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_tether_wifi_regexs);
        mTetherableBluetoothRegexs = mContext.getResources().getStringArray(
        String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_tether_bluetooth_regexs);

        int ifaceTypes[] = mContext.getResources().getIntArray(
                com.android.internal.R.array.config_tether_upstream_types);
        mUpstreamIfaceTypes = new ArrayList();
        Collection<Integer> upstreamIfaceTypes = new ArrayList();
        for (int i : ifaceTypes) {
            mUpstreamIfaceTypes.add(new Integer(i));
            upstreamIfaceTypes.add(new Integer(i));
        }

        synchronized (mPublicSync) {
            mTetherableUsbRegexs = tetherableUsbRegexs;
            mTetherableWifiRegexs = tetherableWifiRegexs;
            mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
            mUpstreamIfaceTypes = upstreamIfaceTypes;
        }

        // check if the upstream type list needs to be modified due to secure-settings
@@ -194,6 +206,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
        boolean found = false;
        boolean usb = false;
        synchronized (mPublicSync) {
            if (isWifi(iface)) {
                found = true;
            } else if (isUsb(iface)) {
@@ -204,7 +217,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
            }
            if (found == false) return;

        synchronized (mIfaces) {
            TetherInterfaceSM sm = mIfaces.get(iface);
            if (up) {
                if (sm == null) {
@@ -231,30 +243,37 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    }

    private boolean isUsb(String iface) {
        synchronized (mPublicSync) {
            for (String regex : mTetherableUsbRegexs) {
                if (iface.matches(regex)) return true;
            }
            return false;
        }
    }

    public boolean isWifi(String iface) {
        synchronized (mPublicSync) {
            for (String regex : mTetherableWifiRegexs) {
                if (iface.matches(regex)) return true;
            }
            return false;
        }
    }

    public boolean isBluetooth(String iface) {
        synchronized (mPublicSync) {
            for (String regex : mTetherableBluetoothRegexs) {
                if (iface.matches(regex)) return true;
            }
            return false;
        }
    }

    public void interfaceAdded(String iface) {
        if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
        boolean found = false;
        boolean usb = false;
        synchronized (mPublicSync) {
            if (isWifi(iface)) {
                found = true;
            }
@@ -270,7 +289,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                return;
            }

        synchronized (mIfaces) {
            TetherInterfaceSM sm = mIfaces.get(iface);
            if (sm != null) {
                if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
@@ -285,7 +303,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

    public void interfaceRemoved(String iface) {
        if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            TetherInterfaceSM sm = mIfaces.get(iface);
            if (sm == null) {
                if (VDBG) {
@@ -303,7 +321,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    public int tether(String iface) {
        if (DBG) Log.d(TAG, "Tethering " + iface);
        TetherInterfaceSM sm = null;
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            sm = mIfaces.get(iface);
        }
        if (sm == null) {
@@ -321,7 +339,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    public int untether(String iface) {
        if (DBG) Log.d(TAG, "Untethering " + iface);
        TetherInterfaceSM sm = null;
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            sm = mIfaces.get(iface);
        }
        if (sm == null) {
@@ -338,16 +356,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

    public int getLastTetherError(String iface) {
        TetherInterfaceSM sm = null;
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            sm = mIfaces.get(iface);
        }
            if (sm == null) {
            Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring");
                Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
                        ", ignoring");
                return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
            }
            return sm.getLastError();
        }
    }

    // TODO - move all private methods used only by the state machine into the state machine
    // to clarify what needs synchronized protection.
    private void sendTetherStateChangedBroadcast() {
        try {
            if (!mConnService.isTetheringSupported()) return;
@@ -363,7 +384,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        boolean usbTethered = false;
        boolean bluetoothTethered = false;

        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            Set ifaces = mIfaces.keySet();
            for (Object iface : ifaces) {
                TetherInterfaceSM sm = mIfaces.get(iface);
@@ -469,7 +490,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        public void onReceive(Context content, Intent intent) {
            String action = intent.getAction();
            if (action.equals(UsbManager.ACTION_USB_STATE)) {
                synchronized (Tethering.this) {
                synchronized (Tethering.this.mPublicSync) {
                    boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
                    mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
                    // start tethering if we have a request pending
@@ -545,6 +566,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        return true;
    }

    // TODO - return copies so people can't tamper
    public String[] getTetherableUsbRegexs() {
        return mTetherableUsbRegexs;
    }
@@ -561,7 +583,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
        UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);

        synchronized (this) {
        synchronized (mPublicSync) {
            if (enable) {
                if (mRndisEnabled) {
                    tetherUsb(true);
@@ -581,18 +603,22 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    }

    public int[] getUpstreamIfaceTypes() {
        int values[];
        synchronized (mPublicSync) {
            updateConfiguration();
        int values[] = new int[mUpstreamIfaceTypes.size()];
            values = new int[mUpstreamIfaceTypes.size()];
            Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
            for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
                values[i] = iterator.next();
            }
        }
        return values;
    }

    public void checkDunRequired() {
        int secureSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.TETHER_DUN_REQUIRED, 2);
        synchronized (mPublicSync) {
            // 2 = not set, 0 = DUN not required, 1 = DUN required
            if (secureSetting != 2) {
                int requiredApn = (secureSetting == 1 ?
@@ -626,10 +652,12 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
            }
        }
    }

    // TODO review API - maybe return ArrayList<String> here and below?
    public String[] getTetheredIfaces() {
        ArrayList<String> list = new ArrayList<String>();
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            Set keys = mIfaces.keySet();
            for (Object key : keys) {
                TetherInterfaceSM sm = mIfaces.get(key);
@@ -647,7 +675,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

    public String[] getTetheredIfacePairs() {
        final ArrayList<String> list = Lists.newArrayList();
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            for (TetherInterfaceSM sm : mIfaces.values()) {
                if (sm.isTethered()) {
                    list.add(sm.mMyUpstreamIfaceName);
@@ -660,7 +688,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

    public String[] getTetherableIfaces() {
        ArrayList<String> list = new ArrayList<String>();
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            Set keys = mIfaces.keySet();
            for (Object key : keys) {
                TetherInterfaceSM sm = mIfaces.get(key);
@@ -678,7 +706,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

    public String[] getErroredIfaces() {
        ArrayList<String> list = new ArrayList<String>();
        synchronized (mIfaces) {
        synchronized (mPublicSync) {
            Set keys = mIfaces.keySet();
            for (Object key : keys) {
                TetherInterfaceSM sm = mIfaces.get(key);
@@ -777,11 +805,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
            return res;
        }

        public synchronized int getLastError() {
        public int getLastError() {
            synchronized (Tethering.this.mPublicSync) {
                return mLastError;
            }
        }

        private synchronized void setLastError(int error) {
        private void setLastError(int error) {
            synchronized (Tethering.this.mPublicSync) {
                mLastError = error;

                if (isErrored()) {
@@ -792,29 +823,37 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                    }
                }
            }
        }

        // synchronized between this getter and the following setter
        public synchronized boolean isAvailable() {
        public boolean isAvailable() {
            synchronized (Tethering.this.mPublicSync) {
                return mAvailable;
            }
        }

        private synchronized void setAvailable(boolean available) {
        private void setAvailable(boolean available) {
            synchronized (Tethering.this.mPublicSync) {
                mAvailable = available;
            }
        }

        // synchronized between this getter and the following setter
        public synchronized boolean isTethered() {
        public boolean isTethered() {
            synchronized (Tethering.this.mPublicSync) {
                return mTethered;
            }
        }

        private synchronized void setTethered(boolean tethered) {
        private void setTethered(boolean tethered) {
            synchronized (Tethering.this.mPublicSync) {
                mTethered = tethered;
            }
        }

        // synchronized between this getter and the following setter
        public synchronized boolean isErrored() {
        public boolean isErrored() {
            synchronized (Tethering.this.mPublicSync) {
                return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
            }
        }

        class InitialState extends State {
            @Override
@@ -922,7 +961,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                sendTetherStateChangedBroadcast();
            }

            void cleanupUpstream() {
            private void cleanupUpstream() {
                if (mMyUpstreamIfaceName != null) {
                    // note that we don't care about errors here.
                    // sometimes interfaces are gone before we get
@@ -1237,6 +1276,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

                updateConfiguration();

                synchronized (mPublicSync) {
                    if (VDBG) {
                        Log.d(TAG, "chooseUpstreamType has upstream iface types:");
                        for (Integer netType : mUpstreamIfaceTypes) {
@@ -1254,6 +1294,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                            break;
                        }
                    }
                }

                if (VDBG) {
                    Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
@@ -1479,6 +1520,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                    return;
        }

        synchronized (mPublicSync) {
            pw.println("mUpstreamIfaceTypes: ");
            for (Integer netType : mUpstreamIfaceTypes) {
                pw.println(" " + netType);
@@ -1486,7 +1528,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

            pw.println();
            pw.println("Tether state:");
        synchronized (mIfaces) {
            for (Object o : mIfaces.values()) {
                pw.println(" "+o.toString());
            }