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

Commit d08b3a68 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Fix locking in ServiceListener

- Use Android framework locking style
- Make sure each and ever access is protected

Test: Ran the service
Fixes: 159418766
Change-Id: I0d884f5aa1644f694f1c4f9cc9f817ebb8cbe110
parent 35fedea3
Loading
Loading
Loading
Loading
+86 −65
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.text.TextUtils;

import androidx.annotation.GuardedBy;

import com.android.printservice.recommendation.R;
import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
import com.android.printservice.recommendation.util.PrinterHashMap;
@@ -40,7 +42,12 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
    private final String[] mServiceType;
    private final Observer mObserver;
    private final ServiceResolveQueue mResolveQueue;
    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>();

    @GuardedBy("mLock")
    public HashMap<String, PrinterHashMap> mVendorHashMap = new HashMap<>();

    public interface Observer {
@@ -73,11 +80,14 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
        printerFound(nsdServiceInfo);
    }

    private synchronized void printerFound(NsdServiceInfo nsdServiceInfo) {
    private void printerFound(NsdServiceInfo nsdServiceInfo) {
        if (nsdServiceInfo == null) return;
        if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return;
        String vendor = MDnsUtils.getVendor(nsdServiceInfo);
        if (vendor == null) vendor = "";

        boolean mapsChanged;
        synchronized (mLock) {
            for (Map.Entry<String, VendorInfo> entry : mVendorInfoHashMap.entrySet()) {
                for (String vendorValues : entry.getValue().mDNSValues) {
                    if (vendor.equalsIgnoreCase(vendorValues)) {
@@ -102,7 +112,6 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback {

            if (!mObserver.matchesCriteria(vendor, nsdServiceInfo))
                return;
        boolean mapsChanged;

            PrinterHashMap vendorHash = mVendorHashMap.get(vendor);
            if (vendorHash == null) {
@@ -110,27 +119,34 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
            }
            mapsChanged = (vendorHash.addPrinter(nsdServiceInfo) == null);
            mVendorHashMap.put(vendor, vendorHash);
        }

        if (mapsChanged) {
            mObserver.dataSetChanged();
        }
    }

    private synchronized void printerRemoved(NsdServiceInfo nsdServiceInfo) {
    private void printerRemoved(NsdServiceInfo nsdServiceInfo) {
        boolean wasRemoved = false;

        synchronized (mLock) {
            Set<String> vendors = mVendorHashMap.keySet();
            for (String vendor : vendors) {
                PrinterHashMap map = mVendorHashMap.get(vendor);
                wasRemoved |= (map.removePrinter(nsdServiceInfo) != null);
                if (map.isEmpty()) wasRemoved |= (mVendorHashMap.remove(vendor) != null);
            }
        }

        if (wasRemoved) {
            mObserver.dataSetChanged();
        }
    }

    public void start() {
        synchronized (mLock) {
            stop();

            for (final String service : mServiceType) {
                NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
                    @Override
@@ -168,14 +184,17 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
                mListeners.add(listener);
            }
        }
    }

    public void stop() {
        synchronized (mLock) {
            for (NsdManager.DiscoveryListener listener : mListeners) {
                DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener);
            }
            mVendorHashMap.clear();
            mListeners.clear();
        }
    }

    /**
     * @return The {@link InetAddress addresses} of the discovered printers
@@ -183,9 +202,11 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
    public ArrayList<InetAddress> getPrinters() {
        ArrayList<InetAddress> printerAddressess = new ArrayList<>();

        synchronized (mLock) {
            for (PrinterHashMap oneVendorPrinters : mVendorHashMap.values()) {
                printerAddressess.addAll(oneVendorPrinters.getPrinterAddresses());
            }
        }

        return printerAddressess;
    }