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

Commit 2d9ccdb4 authored by Robert Greenwalt's avatar Robert Greenwalt Committed by Android Git Automerger
Browse files

am b445362b: Make upstream tether list threadsafe

* commit 'b445362b':
  Make upstream tether list threadsafe
parents 669e1f80 b445362b
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());
            }