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

Commit d65ed881 authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Avoid NPE when quickly toggling USB debugging state"

parents 53e52669 f6197e8f
Loading
Loading
Loading
Loading
+123 −69
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.Slog;
import android.util.Slog;
import android.util.Base64;
import android.util.Base64;

import com.android.server.FgThread;
import com.android.server.FgThread;


import java.lang.Thread;
import java.lang.Thread;
@@ -48,7 +49,7 @@ import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Arrays;


public class UsbDebuggingManager implements Runnable {
public class UsbDebuggingManager {
    private static final String TAG = "UsbDebuggingManager";
    private static final String TAG = "UsbDebuggingManager";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;


@@ -59,32 +60,73 @@ public class UsbDebuggingManager implements Runnable {


    private final Context mContext;
    private final Context mContext;
    private final Handler mHandler;
    private final Handler mHandler;
    private Thread mThread;
    private UsbDebuggingThread mThread;
    private boolean mAdbEnabled = false;
    private boolean mAdbEnabled = false;
    private String mFingerprints;
    private String mFingerprints;
    private LocalSocket mSocket = null;
    private OutputStream mOutputStream = null;


    public UsbDebuggingManager(Context context) {
    public UsbDebuggingManager(Context context) {
        mHandler = new UsbDebuggingHandler(FgThread.get().getLooper());
        mHandler = new UsbDebuggingHandler(FgThread.get().getLooper());
        mContext = context;
        mContext = context;
    }
    }


    private void listenToSocket() throws IOException {
    class UsbDebuggingThread extends Thread {
        private boolean mStopped;
        private LocalSocket mSocket;
        private OutputStream mOutputStream;
        private InputStream mInputStream;

        UsbDebuggingThread() {
            super(TAG);
        }

        @Override
        public void run() {
            if (DEBUG) Slog.d(TAG, "Entering thread");
            while (true) {
                synchronized (this) {
                    if (mStopped) {
                        if (DEBUG) Slog.d(TAG, "Exiting thread");
                        return;
                    }
                    try {
                        openSocketLocked();
                    } catch (Exception e) {
                        /* Don't loop too fast if adbd dies, before init restarts it */
                        SystemClock.sleep(1000);
                    }
                }
                try {
                    listenToSocket();
                } catch (IOException e) {
                    /* Don't loop too fast if adbd dies, before init restarts it */
                    SystemClock.sleep(1000);
                }
            }
        }

        private void openSocketLocked() throws IOException {
            try {
            try {
            byte[] buffer = new byte[BUFFER_SIZE];
                LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
                LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
                        LocalSocketAddress.Namespace.RESERVED);
                        LocalSocketAddress.Namespace.RESERVED);
            InputStream inputStream = null;
                mInputStream = null;


                if (DEBUG) Slog.d(TAG, "Creating socket");
                mSocket = new LocalSocket();
                mSocket = new LocalSocket();
                mSocket.connect(address);
                mSocket.connect(address);


                mOutputStream = mSocket.getOutputStream();
                mOutputStream = mSocket.getOutputStream();
            inputStream = mSocket.getInputStream();
                mInputStream = mSocket.getInputStream();
            } catch (IOException ioe) {
                closeSocketLocked();
                throw ioe;
            }
        }


        private void listenToSocket() throws IOException {
            try {
                byte[] buffer = new byte[BUFFER_SIZE];
                while (true) {
                while (true) {
                int count = inputStream.read(buffer);
                    int count = mInputStream.read(buffer);
                    if (count < 0) {
                    if (count < 0) {
                        break;
                        break;
                    }
                    }
@@ -95,45 +137,51 @@ public class UsbDebuggingManager implements Runnable {
                        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
                        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
                        msg.obj = key;
                        msg.obj = key;
                        mHandler.sendMessage(msg);
                        mHandler.sendMessage(msg);
                }
                    } else {
                else {
                        Slog.e(TAG, "Wrong message: "
                    Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2))));
                                + (new String(Arrays.copyOfRange(buffer, 0, 2))));
                        break;
                        break;
                    }
                    }
                }
                }
            } finally {
            } finally {
            closeSocket();
                synchronized (this) {
        }
                    closeSocketLocked();
    }

    @Override
    public void run() {
        while (mAdbEnabled) {
            try {
                listenToSocket();
            } catch (Exception e) {
                /* Don't loop too fast if adbd dies, before init restarts it */
                SystemClock.sleep(1000);
                }
                }
            }
            }
        }
        }


    private void closeSocket() {
        private void closeSocketLocked() {
            if (DEBUG) Slog.d(TAG, "Closing socket");
            try {
            try {
                if (mOutputStream != null) {
                    mOutputStream.close();
                    mOutputStream.close();
                    mOutputStream = null;
                }
            } catch (IOException e) {
            } catch (IOException e) {
                Slog.e(TAG, "Failed closing output stream: " + e);
                Slog.e(TAG, "Failed closing output stream: " + e);
            }
            }


            try {
            try {
                if (mSocket != null) {
                    mSocket.close();
                    mSocket.close();
                    mSocket = null;
                }
            } catch (IOException ex) {
            } catch (IOException ex) {
                Slog.e(TAG, "Failed closing socket: " + ex);
                Slog.e(TAG, "Failed closing socket: " + ex);
            }
            }
        }
        }


    private void sendResponse(String msg) {
        /** Call to stop listening on the socket and exit the thread. */
        if (mOutputStream != null) {
        void stopListening() {
            synchronized (this) {
                mStopped = true;
                closeSocketLocked();
            }
        }

        void sendResponse(String msg) {
            synchronized (this) {
                if (!mStopped && mOutputStream != null) {
                    try {
                    try {
                        mOutputStream.write(msg.getBytes());
                        mOutputStream.write(msg.getBytes());
                    }
                    }
@@ -142,6 +190,8 @@ public class UsbDebuggingManager implements Runnable {
                    }
                    }
                }
                }
            }
            }
        }
    }


    class UsbDebuggingHandler extends Handler {
    class UsbDebuggingHandler extends Handler {
        private static final int MESSAGE_ADB_ENABLED = 1;
        private static final int MESSAGE_ADB_ENABLED = 1;
@@ -163,7 +213,7 @@ public class UsbDebuggingManager implements Runnable {


                    mAdbEnabled = true;
                    mAdbEnabled = true;


                    mThread = new Thread(UsbDebuggingManager.this, TAG);
                    mThread = new UsbDebuggingThread();
                    mThread.start();
                    mThread.start();


                    break;
                    break;
@@ -173,16 +223,12 @@ public class UsbDebuggingManager implements Runnable {
                        break;
                        break;


                    mAdbEnabled = false;
                    mAdbEnabled = false;
                    closeSocket();


                    try {
                    if (mThread != null) {
                        mThread.join();
                        mThread.stopListening();
                    } catch (Exception ex) {
                        mThread = null;
                    }
                    }


                    mThread = null;
                    mOutputStream = null;
                    mSocket = null;
                    break;
                    break;


                case MESSAGE_ADB_ALLOW: {
                case MESSAGE_ADB_ALLOW: {
@@ -199,25 +245,33 @@ public class UsbDebuggingManager implements Runnable {
                        writeKey(key);
                        writeKey(key);
                    }
                    }


                    sendResponse("OK");
                    if (mThread != null) {
                        mThread.sendResponse("OK");
                    }
                    break;
                    break;
                }
                }


                case MESSAGE_ADB_DENY:
                case MESSAGE_ADB_DENY:
                    sendResponse("NO");
                    if (mThread != null) {
                        mThread.sendResponse("NO");
                    }
                    break;
                    break;


                case MESSAGE_ADB_CONFIRM: {
                case MESSAGE_ADB_CONFIRM: {
                    if ("trigger_restart_min_framework".equals(
                    if ("trigger_restart_min_framework".equals(
                            SystemProperties.get("vold.decrypt"))) {
                            SystemProperties.get("vold.decrypt"))) {
                        Slog.d(TAG, "Deferring adb confirmation until after vold decrypt");
                        Slog.d(TAG, "Deferring adb confirmation until after vold decrypt");
                        sendResponse("NO");
                        if (mThread != null) {
                            mThread.sendResponse("NO");
                        }
                        break;
                        break;
                    }
                    }
                    String key = (String)msg.obj;
                    String key = (String)msg.obj;
                    String fingerprints = getFingerprints(key);
                    String fingerprints = getFingerprints(key);
                    if ("".equals(fingerprints)) {
                    if ("".equals(fingerprints)) {
                        sendResponse("NO");
                        if (mThread != null) {
                            mThread.sendResponse("NO");
                        }
                        break;
                        break;
                    }
                    }
                    mFingerprints = fingerprints;
                    mFingerprints = fingerprints;
@@ -387,7 +441,7 @@ public class UsbDebuggingManager implements Runnable {


    public void dump(FileDescriptor fd, PrintWriter pw) {
    public void dump(FileDescriptor fd, PrintWriter pw) {
        pw.println("  USB Debugging State:");
        pw.println("  USB Debugging State:");
        pw.println("    Connected to adbd: " + (mOutputStream != null));
        pw.println("    Connected to adbd: " + (mThread != null));
        pw.println("    Last key received: " + mFingerprints);
        pw.println("    Last key received: " + mFingerprints);
        pw.println("    User keys:");
        pw.println("    User keys:");
        try {
        try {