/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.adb;

import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.debug.AdbManager;
import android.debug.AdbNotifications;
import android.debug.AdbProtoEnums;
import android.debug.AdbTransportType;
import android.debug.PairDevice;
import android.net.ConnectivityManager;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.adb.AdbDebuggingManagerProto;
import android.util.AtomicFile;
import android.util.Base64;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Provides communication to the Android Debug Bridge daemon to allow, deny, or clear public keys
 * that are authorized to connect to the ADB service itself.
 *
 * <p>The AdbDebuggingManager controls two files:
 * <ol>
 *     <li>adb_keys
 *     <li>adb_temp_keys.xml
 * </ol>
 *
 * <p>The ADB Daemon (adbd) reads <em>only</em> the adb_keys file for authorization. Public keys
 * from registered hosts are stored in adb_keys, one entry per line.
 *
 * <p>AdbDebuggingManager also keeps adb_temp_keys.xml, which is used for two things
 * <ol>
 *     <li>Removing unused keys from the adb_keys file
 *     <li>Managing authorized WiFi access points for ADB over WiFi
 * </ol>
 */
public class AdbDebuggingManager {
    private static final String TAG = AdbDebuggingManager.class.getSimpleName();
    private static final boolean DEBUG = false;
    private static final boolean MDNS_DEBUG = false;

    private static final String ADBD_SOCKET = "adbd";
    private static final String ADB_DIRECTORY = "misc/adb";
    // This file contains keys that will always be allowed to connect to the device via adb.
    private static final String ADB_KEYS_FILE = "adb_keys";
    // This file contains keys that will be allowed to connect without user interaction as long
    // as a subsequent connection occurs within the allowed duration.
    private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
    private static final int BUFFER_SIZE = 65536;
    private static final Ticker SYSTEM_TICKER = () -> System.currentTimeMillis();

    private final Context mContext;
    private final ContentResolver mContentResolver;
    @VisibleForTesting final AdbDebuggingHandler mHandler;
    @Nullable private AdbDebuggingThread mThread;
    private boolean mAdbUsbEnabled = false;
    private boolean mAdbWifiEnabled = false;
    private String mFingerprints;
    // A key can be used more than once (e.g. USB, wifi), so need to keep a refcount
    private final Map<String, Integer> mConnectedKeys = new HashMap<>();
    private final String mConfirmComponent;
    @Nullable private final File mUserKeyFile;
    @Nullable private final File mTempKeysFile;

    private static final String WIFI_PERSISTENT_CONFIG_PROPERTY =
            "persist.adb.tls_server.enable";
    private static final String WIFI_PERSISTENT_GUID =
            "persist.adb.wifi.guid";
    private static final int PAIRING_CODE_LENGTH = 6;
    private PairingThread mPairingThread = null;
    // A list of keys connected via wifi
    private final Set<String> mWifiConnectedKeys = new HashSet<>();
    // The current info of the adbwifi connection.
    private AdbConnectionInfo mAdbConnectionInfo = new AdbConnectionInfo();
    // Polls for a tls port property when adb wifi is enabled
    private AdbConnectionPortPoller mConnectionPortPoller;
    private final PortListenerImpl mPortListener = new PortListenerImpl();
    private final Ticker mTicker;

    public AdbDebuggingManager(Context context) {
        this(
                context,
                /* confirmComponent= */ null,
                getAdbFile(ADB_KEYS_FILE),
                getAdbFile(ADB_TEMP_KEYS_FILE),
                /* adbDebuggingThread= */ null,
                SYSTEM_TICKER);
    }

    /**
     * Constructor that accepts the component to be invoked to confirm if the user wants to allow
     * an adb connection from the key.
     */
    @VisibleForTesting
    AdbDebuggingManager(
            Context context,
            String confirmComponent,
            File testUserKeyFile,
            File tempKeysFile,
            AdbDebuggingThread adbDebuggingThread,
            Ticker ticker) {
        mContext = context;
        mContentResolver = mContext.getContentResolver();
        mConfirmComponent = confirmComponent;
        mUserKeyFile = testUserKeyFile;
        mTempKeysFile = tempKeysFile;
        mThread = adbDebuggingThread;
        mTicker = ticker;
        mHandler = new AdbDebuggingHandler(FgThread.get().getLooper(), mThread);
    }

    static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent,
            @NonNull UserHandle userHandle) {
        context.sendBroadcastAsUser(intent, userHandle,
                android.Manifest.permission.MANAGE_DEBUGGING);
    }

    class PairingThread extends Thread implements NsdManager.RegistrationListener {
        private NsdManager mNsdManager;
        private String mPublicKey;
        private String mPairingCode;
        private String mGuid;
        private String mServiceName;
        // From RFC6763 (https://tools.ietf.org/html/rfc6763#section-7.2),
        // The rules for Service Names [RFC6335] state that they may be no more
        // than fifteen characters long (not counting the mandatory underscore),
        // consisting of only letters, digits, and hyphens, must begin and end
        // with a letter or digit, must not contain consecutive hyphens, and
        // must contain at least one letter.
        @VisibleForTesting static final String SERVICE_PROTOCOL = "adb-tls-pairing";
        private final String mServiceType = String.format("_%s._tcp.", SERVICE_PROTOCOL);
        private int mPort;

        private native int native_pairing_start(String guid, String password);
        private native void native_pairing_cancel();
        private native boolean native_pairing_wait();

        PairingThread(String pairingCode, String serviceName) {
            super(TAG);
            mPairingCode = pairingCode;
            mGuid = SystemProperties.get(WIFI_PERSISTENT_GUID);
            mServiceName = serviceName;
            if (serviceName == null || serviceName.isEmpty()) {
                mServiceName = mGuid;
            }
            mPort = -1;
            mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
        }

        @Override
        public void run() {
            if (mGuid.isEmpty()) {
                Slog.e(TAG, "adbwifi guid was not set");
                return;
            }
            mPort = native_pairing_start(mGuid, mPairingCode);
            if (mPort <= 0 || mPort > 65535) {
                Slog.e(TAG, "Unable to start pairing server");
                return;
            }

            // Register the mdns service
            NsdServiceInfo serviceInfo = new NsdServiceInfo();
            serviceInfo.setServiceName(mServiceName);
            serviceInfo.setServiceType(mServiceType);
            serviceInfo.setPort(mPort);
            mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, this);

            // Send pairing port to UI
            Message msg = mHandler.obtainMessage(
                    AdbDebuggingHandler.MSG_RESPONSE_PAIRING_PORT);
            msg.obj = mPort;
            mHandler.sendMessage(msg);

            boolean paired = native_pairing_wait();
            if (DEBUG) {
                if (mPublicKey != null) {
                    Slog.i(TAG, "Pairing succeeded key=" + mPublicKey);
                } else {
                    Slog.i(TAG, "Pairing failed");
                }
            }

            mNsdManager.unregisterService(this);

            Bundle bundle = new Bundle();
            bundle.putString("publicKey", paired ? mPublicKey : null);
            Message message = Message.obtain(mHandler,
                                             AdbDebuggingHandler.MSG_RESPONSE_PAIRING_RESULT,
                                             bundle);
            mHandler.sendMessage(message);
        }

        public void cancelPairing() {
            native_pairing_cancel();
        }

        @Override
        public void onServiceRegistered(NsdServiceInfo serviceInfo) {
            if (MDNS_DEBUG) Slog.i(TAG, "Registered pairing service: " + serviceInfo);
        }

        @Override
        public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            Slog.e(TAG, "Failed to register pairing service(err=" + errorCode
                    + "): " + serviceInfo);
            cancelPairing();
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
            if (MDNS_DEBUG) Slog.i(TAG, "Unregistered pairing service: " + serviceInfo);
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            Slog.w(TAG, "Failed to unregister pairing service(err=" + errorCode
                    + "): " + serviceInfo);
        }
    }

    interface AdbConnectionPortListener {
        void onPortReceived(int port);
    }

    /**
     * This class will poll for a period of time for adbd to write the port
     * it connected to.
     *
     * TODO(joshuaduong): The port is being sent via system property because the adbd socket
     * (AdbDebuggingManager) is not created when ro.adb.secure=0. Thus, we must communicate the
     * port through different means. A better fix would be to always start AdbDebuggingManager, but
     * it needs to adjust accordingly on whether ro.adb.secure is set.
     */
    static class AdbConnectionPortPoller extends Thread {
        private final String mAdbPortProp = "service.adb.tls.port";
        private AdbConnectionPortListener mListener;
        private final int mDurationSecs = 10;
        private AtomicBoolean mCanceled = new AtomicBoolean(false);

        AdbConnectionPortPoller(AdbConnectionPortListener listener) {
            mListener = listener;
        }

        @Override
        public void run() {
            if (DEBUG) Slog.d(TAG, "Starting adb port property poller");
            // Once adbwifi is enabled, we poll the service.adb.tls.port
            // system property until we get the port, or -1 on failure.
            // Let's also limit the polling to 10 seconds, just in case
            // something went wrong.
            for (int i = 0; i < mDurationSecs; ++i) {
                if (mCanceled.get()) {
                    return;
                }

                // If the property is set to -1, then that means adbd has failed
                // to start the server. Otherwise we should have a valid port.
                int port = SystemProperties.getInt(mAdbPortProp, Integer.MAX_VALUE);
                if (port == -1 || (port > 0 && port <= 65535)) {
                    mListener.onPortReceived(port);
                    return;
                }
                SystemClock.sleep(1000);
            }
            Slog.w(TAG, "Failed to receive adb connection port");
            mListener.onPortReceived(-1);
        }

        public void cancelAndWait() {
            mCanceled.set(true);
            if (this.isAlive()) {
                try {
                    this.join();
                } catch (InterruptedException e) {
                }
            }
        }
    }

    class PortListenerImpl implements AdbConnectionPortListener {
        public void onPortReceived(int port) {
            if (DEBUG) Slog.d(TAG, "Received tls port=" + port);
            Message msg = mHandler.obtainMessage(port > 0
                     ? AdbDebuggingHandler.MSG_SERVER_CONNECTED
                     : AdbDebuggingHandler.MSG_SERVER_DISCONNECTED);
            msg.obj = port;
            mHandler.sendMessage(msg);
        }
    }

    @VisibleForTesting
    static class AdbDebuggingThread extends Thread {
        private boolean mStopped;
        private LocalSocket mSocket;
        private OutputStream mOutputStream;
        private InputStream mInputStream;
        private Handler mHandler;

        @VisibleForTesting
        AdbDebuggingThread() {
            super(TAG);
        }

        @VisibleForTesting
        void setHandler(Handler handler) {
            mHandler = handler;
        }

        @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 (Exception e) {
                    /* Don't loop too fast if adbd dies, before init restarts it */
                    SystemClock.sleep(1000);
                }
            }
        }

        private void openSocketLocked() throws IOException {
            try {
                LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
                        LocalSocketAddress.Namespace.RESERVED);
                mInputStream = null;

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

                mOutputStream = mSocket.getOutputStream();
                mInputStream = mSocket.getInputStream();
                mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_ADBD_SOCKET_CONNECTED);
            } catch (IOException ioe) {
                Slog.e(TAG, "Caught an exception opening the socket: " + ioe);
                closeSocketLocked();
                throw ioe;
            }
        }

        private void listenToSocket() throws IOException {
            try {
                byte[] buffer = new byte[BUFFER_SIZE];
                while (true) {
                    int count = mInputStream.read(buffer);
                    // if less than 2 bytes are read the if statements below will throw an
                    // IndexOutOfBoundsException.
                    if (count < 2) {
                        Slog.w(TAG, "Read failed with count " + count);
                        break;
                    }

                    if (buffer[0] == 'P' && buffer[1] == 'K') {
                        String key = new String(Arrays.copyOfRange(buffer, 2, count));
                        Slog.d(TAG, "Received public key: " + key);
                        Message msg = mHandler.obtainMessage(
                                AdbDebuggingHandler.MESSAGE_ADB_CONFIRM);
                        msg.obj = key;
                        mHandler.sendMessage(msg);
                    } else if (buffer[0] == 'D' && buffer[1] == 'C') {
                        String key = new String(Arrays.copyOfRange(buffer, 2, count));
                        Slog.d(TAG, "Received disconnected message: " + key);
                        Message msg = mHandler.obtainMessage(
                                AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT);
                        msg.obj = key;
                        mHandler.sendMessage(msg);
                    } else if (buffer[0] == 'C' && buffer[1] == 'K') {
                        String key = new String(Arrays.copyOfRange(buffer, 2, count));
                        Slog.d(TAG, "Received connected key message: " + key);
                        Message msg = mHandler.obtainMessage(
                                AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY);
                        msg.obj = key;
                        mHandler.sendMessage(msg);
                    } else if (buffer[0] == 'W' && buffer[1] == 'E') {
                        // adbd_auth.h and AdbTransportType.aidl need to be kept in
                        // sync.
                        byte transportType = buffer[2];
                        String key = new String(Arrays.copyOfRange(buffer, 3, count));
                        if (transportType == AdbTransportType.USB) {
                            Slog.d(TAG, "Received USB TLS connected key message: " + key);
                            Message msg = mHandler.obtainMessage(
                                    AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY);
                            msg.obj = key;
                            mHandler.sendMessage(msg);
                        } else if (transportType == AdbTransportType.WIFI) {
                            Slog.d(TAG, "Received WIFI TLS connected key message: " + key);
                            Message msg = mHandler.obtainMessage(
                                    AdbDebuggingHandler.MSG_WIFI_DEVICE_CONNECTED);
                            msg.obj = key;
                            mHandler.sendMessage(msg);
                        } else {
                            Slog.e(TAG, "Got unknown transport type from adbd (" + transportType
                                    + ")");
                        }
                    } else if (buffer[0] == 'W' && buffer[1] == 'F') {
                        byte transportType = buffer[2];
                        String key = new String(Arrays.copyOfRange(buffer, 3, count));
                        if (transportType == AdbTransportType.USB) {
                            Slog.d(TAG, "Received USB TLS disconnect message: " + key);
                            Message msg = mHandler.obtainMessage(
                                    AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT);
                            msg.obj = key;
                            mHandler.sendMessage(msg);
                        } else if (transportType == AdbTransportType.WIFI) {
                            Slog.d(TAG, "Received WIFI TLS disconnect key message: " + key);
                            Message msg = mHandler.obtainMessage(
                                    AdbDebuggingHandler.MSG_WIFI_DEVICE_DISCONNECTED);
                            msg.obj = key;
                            mHandler.sendMessage(msg);
                        } else {
                            Slog.e(TAG, "Got unknown transport type from adbd (" + transportType
                                    + ")");
                        }
                    } else {
                        Slog.e(TAG, "Wrong message: "
                                + (new String(Arrays.copyOfRange(buffer, 0, 2))));
                        break;
                    }
                }
            } finally {
                synchronized (this) {
                    closeSocketLocked();
                }
            }
        }

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

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

        /** Call to stop listening on the socket and exit the thread. */
        void stopListening() {
            synchronized (this) {
                mStopped = true;
                closeSocketLocked();
            }
        }

        void sendResponse(String msg) {
            synchronized (this) {
                if (!mStopped && mOutputStream != null) {
                    try {
                        mOutputStream.write(msg.getBytes());
                    } catch (IOException ex) {
                        Slog.e(TAG, "Failed to write response:", ex);
                    }
                }
            }
        }
    }

    private static class AdbConnectionInfo {
        private String mBssid;
        private String mSsid;
        private int mPort;

        AdbConnectionInfo() {
            mBssid = "";
            mSsid = "";
            mPort = -1;
        }

        AdbConnectionInfo(String bssid, String ssid) {
            mBssid = bssid;
            mSsid = ssid;
        }

        AdbConnectionInfo(AdbConnectionInfo other) {
            mBssid = other.mBssid;
            mSsid = other.mSsid;
            mPort = other.mPort;
        }

        public String getBSSID() {
            return mBssid;
        }

        public String getSSID() {
            return mSsid;
        }

        public int getPort() {
            return mPort;
        }

        public void setPort(int port) {
            mPort = port;
        }

        public void clear() {
            mBssid = "";
            mSsid = "";
            mPort = -1;
        }
    }

    private void setAdbConnectionInfo(AdbConnectionInfo info) {
        synchronized (mAdbConnectionInfo) {
            if (info == null) {
                mAdbConnectionInfo.clear();
                return;
            }
            mAdbConnectionInfo = info;
        }
    }

    private AdbConnectionInfo getAdbConnectionInfo() {
        synchronized (mAdbConnectionInfo) {
            return new AdbConnectionInfo(mAdbConnectionInfo);
        }
    }

    class AdbDebuggingHandler extends Handler {
        private NotificationManager mNotificationManager;
        private boolean mAdbNotificationShown;

        private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                // We only care about when wifi is disabled, and when there is a wifi network
                // change.
                if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
                    int state = intent.getIntExtra(
                            WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
                    if (state == WifiManager.WIFI_STATE_DISABLED) {
                        Slog.i(TAG, "Wifi disabled. Disabling adbwifi.");
                        Settings.Global.putInt(mContentResolver,
                                Settings.Global.ADB_WIFI_ENABLED, 0);
                    }
                } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
                    // We only care about wifi type connections
                    NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(
                            WifiManager.EXTRA_NETWORK_INFO);
                    if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                        // Check for network disconnect
                        if (!networkInfo.isConnected()) {
                            Slog.i(TAG, "Network disconnected. Disabling adbwifi.");
                            Settings.Global.putInt(mContentResolver,
                                    Settings.Global.ADB_WIFI_ENABLED, 0);
                            return;
                        }

                        WifiManager wifiManager =
                                (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
                        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                        if (wifiInfo == null || wifiInfo.getNetworkId() == -1) {
                            Slog.i(TAG, "Not connected to any wireless network."
                                    + " Not enabling adbwifi.");
                            Settings.Global.putInt(mContentResolver,
                                    Settings.Global.ADB_WIFI_ENABLED, 0);
                        }

                        // Check for network change
                        String bssid = wifiInfo.getBSSID();
                        if (bssid == null || bssid.isEmpty()) {
                            Slog.e(TAG, "Unable to get the wifi ap's BSSID. Disabling adbwifi.");
                            Settings.Global.putInt(mContentResolver,
                                    Settings.Global.ADB_WIFI_ENABLED, 0);
                        }
                        synchronized (mAdbConnectionInfo) {
                            if (!bssid.equals(mAdbConnectionInfo.getBSSID())) {
                                Slog.i(TAG, "Detected wifi network change. Disabling adbwifi.");
                                Settings.Global.putInt(mContentResolver,
                                        Settings.Global.ADB_WIFI_ENABLED, 0);
                            }
                        }
                    }
                }
            }
        };

        private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";

        private boolean isTv() {
            return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
        }

        private void setupNotifications() {
            if (mNotificationManager != null) {
                return;
            }
            mNotificationManager = (NotificationManager)
                    mContext.getSystemService(Context.NOTIFICATION_SERVICE);
            if (mNotificationManager == null) {
                Slog.e(TAG, "Unable to setup notifications for wireless debugging");
                return;
            }

            // Ensure that the notification channels are set up
            if (isTv()) {
                // TV-specific notification channel
                mNotificationManager.createNotificationChannel(
                        new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
                                mContext.getString(
                                        com.android.internal.R.string
                                                .adb_debugging_notification_channel_tv),
                                NotificationManager.IMPORTANCE_HIGH));
            }
        }

        // The default time to schedule the job to keep the keystore updated with a currently
        // connected key as well as to removed expired keys.
        static final long UPDATE_KEYSTORE_JOB_INTERVAL = 86400000;
        // The minimum interval at which the job should run to update the keystore. This is intended
        // to prevent the job from running too often if the allowed connection time for adb grants
        // is set to an extremely small value.
        static final long UPDATE_KEYSTORE_MIN_JOB_INTERVAL = 60000;

        static final int MESSAGE_ADB_ENABLED = 1;
        static final int MESSAGE_ADB_DISABLED = 2;
        static final int MESSAGE_ADB_ALLOW = 3;
        static final int MESSAGE_ADB_DENY = 4;
        static final int MESSAGE_ADB_CONFIRM = 5;
        static final int MESSAGE_ADB_CLEAR = 6;
        static final int MESSAGE_ADB_DISCONNECT = 7;
        static final int MESSAGE_ADB_PERSIST_KEYSTORE = 8;
        static final int MESSAGE_ADB_UPDATE_KEYSTORE = 9;
        static final int MESSAGE_ADB_CONNECTED_KEY = 10;

        // === Messages from the UI ==============
        // UI asks adbd to enable adbdwifi
        static final int MSG_ADBDWIFI_ENABLE = 11;
        // UI asks adbd to disable adbdwifi
        static final int MSG_ADBDWIFI_DISABLE = 12;
        // Cancel pairing
        static final int MSG_PAIRING_CANCEL = 14;
        // Enable pairing by pairing code
        static final int MSG_PAIR_PAIRING_CODE = 15;
        // Enable pairing by QR code
        static final int MSG_PAIR_QR_CODE = 16;
        // UI asks to unpair (forget) a device.
        static final int MSG_REQ_UNPAIR = 17;
        // User allows debugging on the current network
        static final int MSG_ADBWIFI_ALLOW = 18;
        // User denies debugging on the current network
        static final int MSG_ADBWIFI_DENY = 19;

        // === Messages from the PairingThread ===========
        // Result of the pairing
        static final int MSG_RESPONSE_PAIRING_RESULT = 20;
        // The port opened for pairing
        static final int MSG_RESPONSE_PAIRING_PORT = 21;

        // === Messages from adbd ================
        // Notifies us a wifi device connected.
        static final int MSG_WIFI_DEVICE_CONNECTED = 22;
        // Notifies us a wifi device disconnected.
        static final int MSG_WIFI_DEVICE_DISCONNECTED = 23;
        // Notifies us the TLS server is connected and listening
        static final int MSG_SERVER_CONNECTED = 24;
        // Notifies us the TLS server is disconnected
        static final int MSG_SERVER_DISCONNECTED = 25;
        // Notification when adbd socket successfully connects.
        static final int MSG_ADBD_SOCKET_CONNECTED = 26;
        // Notification when adbd socket is disconnected.
        static final int MSG_ADBD_SOCKET_DISCONNECTED = 27;

        // === Messages from other parts of the system
        private static final int MESSAGE_KEY_FILES_UPDATED = 28;

        // === Messages we can send to adbd ===========
        static final String MSG_DISCONNECT_DEVICE = "DD";
        static final String MSG_DISABLE_ADBDWIFI = "DA";

        @Nullable @VisibleForTesting AdbKeyStore mAdbKeyStore;

        // Usb, Wi-Fi transports can be enabled together or separately, so don't break the framework
        // connection unless all transport types are disconnected.
        private int mAdbEnabledRefCount = 0;

        private ContentObserver mAuthTimeObserver = new ContentObserver(this) {
            @Override
            public void onChange(boolean selfChange, Uri uri) {
                Slog.d(TAG, "Received notification that uri " + uri
                        + " was modified; rescheduling keystore job");
                scheduleJobToUpdateAdbKeyStore();
            }
        };

        /** Constructor that accepts the AdbDebuggingThread to which responses should be sent. */
        @VisibleForTesting
        AdbDebuggingHandler(Looper looper, AdbDebuggingThread thread) {
            super(looper);
            mThread = thread;
        }

        /** Initialize the AdbKeyStore so tests can grab mAdbKeyStore immediately. */
        @VisibleForTesting
        void initKeyStore() {
            if (mAdbKeyStore == null) {
                mAdbKeyStore = new AdbKeyStore();
            }
        }

        // Show when at least one device is connected.
        public void showAdbConnectedNotification(boolean show) {
            final int id = SystemMessage.NOTE_ADB_WIFI_ACTIVE;
            if (show == mAdbNotificationShown) {
                return;
            }
            setupNotifications();
            if (!mAdbNotificationShown) {
                Notification notification = AdbNotifications.createNotification(mContext,
                        AdbTransportType.WIFI);
                mAdbNotificationShown = true;
                mNotificationManager.notifyAsUser(null, id, notification,
                        UserHandle.ALL);
            } else {
                mAdbNotificationShown = false;
                mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
            }
        }

        private void startAdbDebuggingThread() {
            ++mAdbEnabledRefCount;
            if (DEBUG) Slog.i(TAG, "startAdbDebuggingThread ref=" + mAdbEnabledRefCount);
            if (mAdbEnabledRefCount > 1) {
                return;
            }

            registerForAuthTimeChanges();
            mThread = new AdbDebuggingThread();
            mThread.setHandler(mHandler);
            mThread.start();

            mAdbKeyStore.updateKeyStore();
            scheduleJobToUpdateAdbKeyStore();
        }

        private void stopAdbDebuggingThread() {
            --mAdbEnabledRefCount;
            if (DEBUG) Slog.i(TAG, "stopAdbDebuggingThread ref=" + mAdbEnabledRefCount);
            if (mAdbEnabledRefCount > 0) {
                return;
            }

            if (mThread != null) {
                mThread.stopListening();
                mThread = null;
            }

            if (!mConnectedKeys.isEmpty()) {
                for (Map.Entry<String, Integer> entry : mConnectedKeys.entrySet()) {
                    mAdbKeyStore.setLastConnectionTime(entry.getKey(), mTicker.currentTimeMillis());
                }
                sendPersistKeyStoreMessage();
                mConnectedKeys.clear();
                mWifiConnectedKeys.clear();
            }
            scheduleJobToUpdateAdbKeyStore();
        }

        public void handleMessage(Message msg) {
            initKeyStore();

            switch (msg.what) {
                case MESSAGE_ADB_ENABLED:
                    if (mAdbUsbEnabled) {
                        break;
                    }
                    startAdbDebuggingThread();
                    mAdbUsbEnabled = true;
                    break;

                case MESSAGE_ADB_DISABLED:
                    if (!mAdbUsbEnabled) {
                        break;
                    }
                    stopAdbDebuggingThread();
                    mAdbUsbEnabled = false;
                    break;

                case MESSAGE_ADB_ALLOW: {
                    String key = (String) msg.obj;
                    String fingerprints = getFingerprints(key);
                    if (!fingerprints.equals(mFingerprints)) {
                        Slog.e(TAG, "Fingerprints do not match. Got "
                                + fingerprints + ", expected " + mFingerprints);
                        break;
                    }

                    boolean alwaysAllow = msg.arg1 == 1;
                    if (mThread != null) {
                        mThread.sendResponse("OK");
                        if (alwaysAllow) {
                            if (!mConnectedKeys.containsKey(key)) {
                                mConnectedKeys.put(key, 1);
                            }
                            mAdbKeyStore.setLastConnectionTime(key, mTicker.currentTimeMillis());
                            sendPersistKeyStoreMessage();
                            scheduleJobToUpdateAdbKeyStore();
                        }
                        logAdbConnectionChanged(key, AdbProtoEnums.USER_ALLOWED, alwaysAllow);
                    }
                    break;
                }

                case MESSAGE_ADB_DENY:
                    if (mThread != null) {
                        Slog.w(TAG, "Denying adb confirmation");
                        mThread.sendResponse("NO");
                        logAdbConnectionChanged(null, AdbProtoEnums.USER_DENIED, false);
                    }
                    break;

                case MESSAGE_ADB_CONFIRM: {
                    String key = (String) msg.obj;
                    if ("trigger_restart_min_framework".equals(
                            SystemProperties.get("vold.decrypt"))) {
                        Slog.w(TAG, "Deferring adb confirmation until after vold decrypt");
                        if (mThread != null) {
                            mThread.sendResponse("NO");
                            logAdbConnectionChanged(key, AdbProtoEnums.DENIED_VOLD_DECRYPT, false);
                        }
                        break;
                    }
                    String fingerprints = getFingerprints(key);
                    if ("".equals(fingerprints)) {
                        if (mThread != null) {
                            mThread.sendResponse("NO");
                            logAdbConnectionChanged(key, AdbProtoEnums.DENIED_INVALID_KEY, false);
                        }
                        break;
                    }
                    logAdbConnectionChanged(key, AdbProtoEnums.AWAITING_USER_APPROVAL, false);
                    mFingerprints = fingerprints;
                    startConfirmationForKey(key, mFingerprints);
                    break;
                }

                case MESSAGE_ADB_CLEAR: {
                    Slog.d(TAG, "Received a request to clear the adb authorizations");
                    mConnectedKeys.clear();
                    // If the key store has not yet been instantiated then do so now; this avoids
                    // the unnecessary creation of the key store when adb is not enabled.
                    initKeyStore();
                    mWifiConnectedKeys.clear();
                    mAdbKeyStore.deleteKeyStore();
                    cancelJobToUpdateAdbKeyStore();
                    break;
                }

                case MESSAGE_ADB_DISCONNECT: {
                    String key = (String) msg.obj;
                    boolean alwaysAllow = false;
                    if (key != null && key.length() > 0) {
                        if (mConnectedKeys.containsKey(key)) {
                            alwaysAllow = true;
                            int refcount = mConnectedKeys.get(key) - 1;
                            if (refcount == 0) {
                                mAdbKeyStore.setLastConnectionTime(
                                        key, mTicker.currentTimeMillis());
                                sendPersistKeyStoreMessage();
                                scheduleJobToUpdateAdbKeyStore();
                                mConnectedKeys.remove(key);
                            } else {
                                mConnectedKeys.put(key, refcount);
                            }
                        }
                    } else {
                        Slog.w(TAG, "Received a disconnected key message with an empty key");
                    }
                    logAdbConnectionChanged(key, AdbProtoEnums.DISCONNECTED, alwaysAllow);
                    break;
                }

                case MESSAGE_ADB_PERSIST_KEYSTORE: {
                    if (mAdbKeyStore != null) {
                        mAdbKeyStore.persistKeyStore();
                    }
                    break;
                }

                case MESSAGE_ADB_UPDATE_KEYSTORE: {
                    if (!mConnectedKeys.isEmpty()) {
                        for (Map.Entry<String, Integer> entry : mConnectedKeys.entrySet()) {
                            mAdbKeyStore.setLastConnectionTime(entry.getKey(),
                                    mTicker.currentTimeMillis());
                        }
                        sendPersistKeyStoreMessage();
                        scheduleJobToUpdateAdbKeyStore();
                    } else if (!mAdbKeyStore.isEmpty()) {
                        mAdbKeyStore.updateKeyStore();
                        scheduleJobToUpdateAdbKeyStore();
                    }
                    break;
                }

                case MESSAGE_ADB_CONNECTED_KEY: {
                    String key = (String) msg.obj;
                    if (key == null || key.length() == 0) {
                        Slog.w(TAG, "Received a connected key message with an empty key");
                    } else {
                        if (!mConnectedKeys.containsKey(key)) {
                            mConnectedKeys.put(key, 1);
                        } else {
                            mConnectedKeys.put(key, mConnectedKeys.get(key) + 1);
                        }
                        mAdbKeyStore.setLastConnectionTime(key, mTicker.currentTimeMillis());
                        sendPersistKeyStoreMessage();
                        scheduleJobToUpdateAdbKeyStore();
                        logAdbConnectionChanged(key, AdbProtoEnums.AUTOMATICALLY_ALLOWED, true);
                    }
                    break;
                }
                case MSG_ADBDWIFI_ENABLE: {
                    if (mAdbWifiEnabled) {
                        break;
                    }

                    AdbConnectionInfo currentInfo = getCurrentWifiApInfo();
                    if (currentInfo == null) {
                        Settings.Global.putInt(mContentResolver,
                                Settings.Global.ADB_WIFI_ENABLED, 0);
                        break;
                    }

                    if (!verifyWifiNetwork(currentInfo.getBSSID(),
                            currentInfo.getSSID())) {
                        // This means that the network is not in the list of trusted networks.
                        // We'll give user a prompt on whether to allow wireless debugging on
                        // the current wifi network.
                        Settings.Global.putInt(mContentResolver,
                                Settings.Global.ADB_WIFI_ENABLED, 0);
                        break;
                    }

                    setAdbConnectionInfo(currentInfo);
                    IntentFilter intentFilter =
                            new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
                    intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
                    mContext.registerReceiver(mBroadcastReceiver, intentFilter);

                    SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1");
                    mConnectionPortPoller =
                            new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
                    mConnectionPortPoller.start();

                    startAdbDebuggingThread();
                    mAdbWifiEnabled = true;

                    if (DEBUG) Slog.i(TAG, "adb start wireless adb");
                    break;
                }
                case MSG_ADBDWIFI_DISABLE:
                    if (!mAdbWifiEnabled) {
                        break;
                    }
                    mAdbWifiEnabled = false;
                    setAdbConnectionInfo(null);
                    mContext.unregisterReceiver(mBroadcastReceiver);

                    if (mThread != null) {
                        mThread.sendResponse(MSG_DISABLE_ADBDWIFI);
                    }
                    onAdbdWifiServerDisconnected(-1);
                    stopAdbDebuggingThread();
                    break;
                case MSG_ADBWIFI_ALLOW:
                    if (mAdbWifiEnabled) {
                        break;
                    }
                    String bssid = (String) msg.obj;
                    boolean alwaysAllow = msg.arg1 == 1;
                    if (alwaysAllow) {
                        mAdbKeyStore.addTrustedNetwork(bssid);
                    }

                    // Let's check again to make sure we didn't switch networks while verifying
                    // the wifi bssid.
                    AdbConnectionInfo newInfo = getCurrentWifiApInfo();
                    if (newInfo == null || !bssid.equals(newInfo.getBSSID())) {
                        break;
                    }

                    setAdbConnectionInfo(newInfo);
                    Settings.Global.putInt(mContentResolver,
                            Settings.Global.ADB_WIFI_ENABLED, 1);
                    IntentFilter intentFilter =
                            new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
                    intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
                    mContext.registerReceiver(mBroadcastReceiver, intentFilter);

                    SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1");
                    mConnectionPortPoller =
                            new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
                    mConnectionPortPoller.start();

                    startAdbDebuggingThread();
                    mAdbWifiEnabled = true;

                    if (DEBUG) Slog.i(TAG, "adb start wireless adb");
                    break;
                case MSG_ADBWIFI_DENY:
                    Settings.Global.putInt(mContentResolver,
                            Settings.Global.ADB_WIFI_ENABLED, 0);
                    sendServerConnectionState(false, -1);
                    break;
                case MSG_REQ_UNPAIR: {
                    String fingerprint = (String) msg.obj;
                    // Tell adbd to disconnect the device if connected.
                    String publicKey = mAdbKeyStore.findKeyFromFingerprint(fingerprint);
                    if (publicKey == null || publicKey.isEmpty()) {
                        Slog.e(TAG, "Not a known fingerprint [" + fingerprint + "]");
                        break;
                    }
                    String cmdStr = MSG_DISCONNECT_DEVICE + publicKey;
                    if (mThread != null) {
                        mThread.sendResponse(cmdStr);
                    }
                    mAdbKeyStore.removeKey(publicKey);
                    // Send the updated paired devices list to the UI.
                    sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
                    break;
                }
                case MSG_RESPONSE_PAIRING_RESULT: {
                    Bundle bundle = (Bundle) msg.obj;
                    String publicKey = bundle.getString("publicKey");
                    onPairingResult(publicKey);
                    // Send the updated paired devices list to the UI.
                    sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
                    break;
                }
                case MSG_RESPONSE_PAIRING_PORT: {
                    int port = (int) msg.obj;
                    sendPairingPortToUI(port);
                    break;
                }
                case MSG_PAIR_PAIRING_CODE: {
                    String pairingCode = createPairingCode(PAIRING_CODE_LENGTH);
                    updateUIPairCode(pairingCode);
                    mPairingThread = new PairingThread(pairingCode, null);
                    mPairingThread.start();
                    break;
                }
                case MSG_PAIR_QR_CODE: {
                    Bundle bundle = (Bundle) msg.obj;
                    String serviceName = bundle.getString("serviceName");
                    String password = bundle.getString("password");
                    mPairingThread = new PairingThread(password, serviceName);
                    mPairingThread.start();
                    break;
                }
                case MSG_PAIRING_CANCEL:
                    if (mPairingThread != null) {
                        mPairingThread.cancelPairing();
                        try {
                            mPairingThread.join();
                        } catch (InterruptedException e) {
                            Slog.w(TAG, "Error while waiting for pairing thread to quit.");
                            e.printStackTrace();
                        }
                        mPairingThread = null;
                    }
                    break;
                case MSG_WIFI_DEVICE_CONNECTED: {
                    String key = (String) msg.obj;
                    if (mWifiConnectedKeys.add(key)) {
                        sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
                        showAdbConnectedNotification(true);
                    }
                    break;
                }
                case MSG_WIFI_DEVICE_DISCONNECTED: {
                    String key = (String) msg.obj;
                    if (mWifiConnectedKeys.remove(key)) {
                        sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
                        if (mWifiConnectedKeys.isEmpty()) {
                            showAdbConnectedNotification(false);
                        }
                    }
                    break;
                }
                case MSG_SERVER_CONNECTED: {
                    int port = (int) msg.obj;
                    onAdbdWifiServerConnected(port);
                    synchronized (mAdbConnectionInfo) {
                        mAdbConnectionInfo.setPort(port);
                    }
                    Settings.Global.putInt(mContentResolver,
                            Settings.Global.ADB_WIFI_ENABLED, 1);
                    break;
                }
                case MSG_SERVER_DISCONNECTED: {
                    if (!mAdbWifiEnabled) {
                        break;
                    }
                    int port = (int) msg.obj;
                    onAdbdWifiServerDisconnected(port);
                    Settings.Global.putInt(mContentResolver,
                            Settings.Global.ADB_WIFI_ENABLED, 0);
                    stopAdbDebuggingThread();
                    if (mConnectionPortPoller != null) {
                        mConnectionPortPoller.cancelAndWait();
                        mConnectionPortPoller = null;
                    }
                    break;
                }
                case MSG_ADBD_SOCKET_CONNECTED: {
                    if (DEBUG) Slog.d(TAG, "adbd socket connected");
                    if (mAdbWifiEnabled) {
                        // In scenarios where adbd is restarted, the tls port may change.
                        mConnectionPortPoller =
                                new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
                        mConnectionPortPoller.start();
                    }
                    break;
                }
                case MSG_ADBD_SOCKET_DISCONNECTED: {
                    if (DEBUG) Slog.d(TAG, "adbd socket disconnected");
                    if (mConnectionPortPoller != null) {
                        mConnectionPortPoller.cancelAndWait();
                        mConnectionPortPoller = null;
                    }
                    if (mAdbWifiEnabled) {
                        // In scenarios where adbd is restarted, the tls port may change.
                        onAdbdWifiServerDisconnected(-1);
                    }
                    break;
                }
                case MESSAGE_KEY_FILES_UPDATED: {
                    mAdbKeyStore.reloadKeyMap();
                    break;
                }
            }
        }

        void registerForAuthTimeChanges() {
            Uri uri = Settings.Global.getUriFor(Settings.Global.ADB_ALLOWED_CONNECTION_TIME);
            mContext.getContentResolver().registerContentObserver(uri, false, mAuthTimeObserver);
        }

        private void logAdbConnectionChanged(String key, int state, boolean alwaysAllow) {
            long lastConnectionTime = mAdbKeyStore.getLastConnectionTime(key);
            long authWindow = mAdbKeyStore.getAllowedConnectionTime();
            Slog.d(TAG,
                    "Logging key " + key + ", state = " + state + ", alwaysAllow = " + alwaysAllow
                            + ", lastConnectionTime = " + lastConnectionTime + ", authWindow = "
                            + authWindow);
            FrameworkStatsLog.write(FrameworkStatsLog.ADB_CONNECTION_CHANGED, lastConnectionTime,
                    authWindow, state, alwaysAllow);
        }


        /**
         * Schedules a job to update the connection time of the currently connected key and filter
         * out any keys that are beyond their expiration time.
         *
         * @return the time in ms when the next job will run or -1 if the job should not be
         * scheduled to run.
         */
        @VisibleForTesting
        long scheduleJobToUpdateAdbKeyStore() {
            cancelJobToUpdateAdbKeyStore();
            long keyExpiration = mAdbKeyStore.getNextExpirationTime();
            // if the keyExpiration time is -1 then either the keys are set to never expire or
            // there are no keys in the keystore, just return for now as a new job will be
            // scheduled on the next connection or when the auth time changes.
            if (keyExpiration == -1) {
                return -1;
            }
            long delay;
            // if the keyExpiration is 0 this indicates a key has already expired; schedule the job
            // to run now to ensure the key is removed immediately from adb_keys.
            if (keyExpiration == 0) {
                delay = 0;
            } else {
                // else the next job should be run either daily or when the next key is set to
                // expire with a min job interval to ensure this job does not run too often if a
                // small value is set for the key expiration.
                delay = Math.max(Math.min(UPDATE_KEYSTORE_JOB_INTERVAL, keyExpiration),
                        UPDATE_KEYSTORE_MIN_JOB_INTERVAL);
            }
            Message message = obtainMessage(MESSAGE_ADB_UPDATE_KEYSTORE);
            sendMessageDelayed(message, delay);
            return delay;
        }

        /**
         * Cancels the scheduled job to update the connection time of the currently connected key
         * and to remove any expired keys.
         */
        private void cancelJobToUpdateAdbKeyStore() {
            removeMessages(AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEYSTORE);
        }

        // Generates a random string of digits with size |size|.
        private String createPairingCode(int size) {
            String res = "";
            SecureRandom rand = new SecureRandom();
            for (int i = 0; i < size; ++i) {
                res += rand.nextInt(10);
            }

            return res;
        }

        private void sendServerConnectionState(boolean connected, int port) {
            Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
            intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, connected
                    ? AdbManager.WIRELESS_STATUS_CONNECTED
                    : AdbManager.WIRELESS_STATUS_DISCONNECTED);
            intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
        }

        private void onAdbdWifiServerConnected(int port) {
            // Send the paired devices list to the UI
            sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
            sendServerConnectionState(true, port);
        }

        private void onAdbdWifiServerDisconnected(int port) {
            // The TLS server disconnected while we had wireless debugging enabled.
            // Let's disable it.
            mWifiConnectedKeys.clear();
            showAdbConnectedNotification(false);
            sendServerConnectionState(false, port);
        }

        /**
         * Returns the [bssid, ssid] of the current access point.
         */
        private AdbConnectionInfo getCurrentWifiApInfo() {
            WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            if (wifiInfo == null || wifiInfo.getNetworkId() == -1) {
                Slog.i(TAG, "Not connected to any wireless network. Not enabling adbwifi.");
                return null;
            }

            String ssid = null;
            if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
                ssid = wifiInfo.getPasspointProviderFriendlyName();
            } else {
                ssid = wifiInfo.getSSID();
                if (ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid)) {
                    // OK, it's not in the connectionInfo; we have to go hunting for it
                    List<WifiConfiguration> networks = wifiManager.getConfiguredNetworks();
                    int length = networks.size();
                    for (int i = 0; i < length; i++) {
                        if (networks.get(i).networkId == wifiInfo.getNetworkId()) {
                            ssid = networks.get(i).SSID;
                        }
                    }
                    if (ssid == null) {
                        Slog.e(TAG, "Unable to get ssid of the wifi AP.");
                        return null;
                    }
                }
            }

            String bssid = wifiInfo.getBSSID();
            if (bssid == null || bssid.isEmpty()) {
                Slog.e(TAG, "Unable to get the wifi ap's BSSID.");
                return null;
            }
            return new AdbConnectionInfo(bssid, ssid);
        }

        private boolean verifyWifiNetwork(String bssid, String ssid) {
            // Check against a list of user-trusted networks.
            if (mAdbKeyStore.isTrustedNetwork(bssid)) {
                return true;
            }

            // Ask user to confirm using wireless debugging on this network.
            startConfirmationForNetwork(ssid, bssid);
            return false;
        }

        private void onPairingResult(String publicKey) {
            if (publicKey == null) {
                Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
                intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL);
                AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
                        UserHandle.ALL);
            } else {
                Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
                intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
                        AdbManager.WIRELESS_STATUS_SUCCESS);
                String fingerprints = getFingerprints(publicKey);
                String hostname = "nouser@nohostname";
                String[] args = publicKey.split("\\s+");
                if (args.length > 1) {
                    hostname = args[1];
                }
                PairDevice device = new PairDevice();
                device.name = fingerprints;
                device.guid = hostname;
                device.connected = false;
                intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
                AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
                        UserHandle.ALL);
                // Add the key into the keystore
                mAdbKeyStore.setLastConnectionTime(publicKey, mTicker.currentTimeMillis());
                sendPersistKeyStoreMessage();
                scheduleJobToUpdateAdbKeyStore();
            }
        }

        private void sendPairingPortToUI(int port) {
            Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
            intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
                    AdbManager.WIRELESS_STATUS_CONNECTED);
            intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
        }

        private void sendPairedDevicesToUI(Map<String, PairDevice> devices) {
            Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
            // Map is not serializable, so need to downcast
            intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices);
            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
        }

        private void updateUIPairCode(String code) {
            if (DEBUG) Slog.i(TAG, "updateUIPairCode: " + code);

            Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
            intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code);
            intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
                    AdbManager.WIRELESS_STATUS_PAIRING_CODE);
            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
        }
    }

    private String getFingerprints(String key) {
        String hex = "0123456789ABCDEF";
        StringBuilder sb = new StringBuilder();
        MessageDigest digester;

        if (key == null) {
            return "";
        }

        try {
            digester = MessageDigest.getInstance("MD5");
        } catch (Exception ex) {
            Slog.e(TAG, "Error getting digester", ex);
            return "";
        }

        byte[] base64_data = key.split("\\s+")[0].getBytes();
        byte[] digest;
        try {
            digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
        } catch (IllegalArgumentException e) {
            Slog.e(TAG, "error doing base64 decoding", e);
            return "";
        }
        for (int i = 0; i < digest.length; i++) {
            sb.append(hex.charAt((digest[i] >> 4) & 0xf));
            sb.append(hex.charAt(digest[i] & 0xf));
            if (i < digest.length - 1) {
                sb.append(":");
            }
        }
        return sb.toString();
    }

    private void startConfirmationForNetwork(String ssid, String bssid) {
        List<Map.Entry<String, String>> extras = new ArrayList<Map.Entry<String, String>>();
        extras.add(new AbstractMap.SimpleEntry<String, String>("ssid", ssid));
        extras.add(new AbstractMap.SimpleEntry<String, String>("bssid", bssid));
        int currentUserId = ActivityManager.getCurrentUser();
        String componentString =
                Resources.getSystem().getString(
                        R.string.config_customAdbWifiNetworkConfirmationComponent);
        ComponentName componentName = ComponentName.unflattenFromString(componentString);
        UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
        if (startConfirmationActivity(componentName, userInfo.getUserHandle(), extras)
                || startConfirmationService(componentName, userInfo.getUserHandle(), extras)) {
            return;
        }
        Slog.e(TAG, "Unable to start customAdbWifiNetworkConfirmation[SecondaryUser]Component "
                + componentString + " as an Activity or a Service");
    }

    private void startConfirmationForKey(String key, String fingerprints) {
        List<Map.Entry<String, String>> extras = new ArrayList<Map.Entry<String, String>>();
        extras.add(new AbstractMap.SimpleEntry<String, String>("key", key));
        extras.add(new AbstractMap.SimpleEntry<String, String>("fingerprints", fingerprints));
        int currentUserId = ActivityManager.getCurrentUser();
        UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
        String componentString;
        if (userInfo.isAdmin()) {
            componentString = mConfirmComponent != null
                    ? mConfirmComponent : Resources.getSystem().getString(
                    com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
        } else {
            // If the current foreground user is not the admin user we send a different
            // notification specific to secondary users.
            componentString = Resources.getSystem().getString(
                    R.string.config_customAdbPublicKeyConfirmationSecondaryUserComponent);
        }
        ComponentName componentName = ComponentName.unflattenFromString(componentString);
        if (startConfirmationActivity(componentName, userInfo.getUserHandle(), extras)
                || startConfirmationService(componentName, userInfo.getUserHandle(),
                        extras)) {
            return;
        }
        Slog.e(TAG, "unable to start customAdbPublicKeyConfirmation[SecondaryUser]Component "
                + componentString + " as an Activity or a Service");
    }

    /**
     * @return true if the componentName led to an Activity that was started.
     */
    private boolean startConfirmationActivity(ComponentName componentName, UserHandle userHandle,
            List<Map.Entry<String, String>> extras) {
        PackageManager packageManager = mContext.getPackageManager();
        Intent intent = createConfirmationIntent(componentName, extras);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
            try {
                mContext.startActivityAsUser(intent, userHandle);
                return true;
            } catch (ActivityNotFoundException e) {
                Slog.e(TAG, "unable to start adb whitelist activity: " + componentName, e);
            }
        }
        return false;
    }

    /**
     * @return true if the componentName led to a Service that was started.
     */
    private boolean startConfirmationService(ComponentName componentName, UserHandle userHandle,
            List<Map.Entry<String, String>> extras) {
        Intent intent = createConfirmationIntent(componentName, extras);
        try {
            if (mContext.startServiceAsUser(intent, userHandle) != null) {
                return true;
            }
        } catch (SecurityException e) {
            Slog.e(TAG, "unable to start adb whitelist service: " + componentName, e);
        }
        return false;
    }

    private Intent createConfirmationIntent(ComponentName componentName,
            List<Map.Entry<String, String>> extras) {
        Intent intent = new Intent();
        intent.setClassName(componentName.getPackageName(), componentName.getClassName());
        for (Map.Entry<String, String> entry : extras) {
            intent.putExtra(entry.getKey(), entry.getValue());
        }
        return intent;
    }

    /**
     * Returns a new File with the specified name in the adb directory.
     */
    private static File getAdbFile(String fileName) {
        File dataDir = Environment.getDataDirectory();
        File adbDir = new File(dataDir, ADB_DIRECTORY);

        if (!adbDir.exists()) {
            Slog.e(TAG, "ADB data directory does not exist");
            return null;
        }

        return new File(adbDir, fileName);
    }

    File getAdbTempKeysFile() {
        return mTempKeysFile;
    }

    File getUserKeyFile() {
        return mUserKeyFile;
    }

    private void writeKeys(Iterable<String> keys) {
        if (mUserKeyFile == null) {
            return;
        }

        AtomicFile atomicKeyFile = new AtomicFile(mUserKeyFile);
        // Note: Do not use a try-with-resources with the FileOutputStream, because AtomicFile
        // requires that it's cleaned up with AtomicFile.failWrite();
        FileOutputStream fo = null;
        try {
            fo = atomicKeyFile.startWrite();
            for (String key : keys) {
                fo.write(key.getBytes());
                fo.write('\n');
            }
            atomicKeyFile.finishWrite(fo);
        } catch (IOException ex) {
            Slog.e(TAG, "Error writing keys: " + ex);
            atomicKeyFile.failWrite(fo);
            return;
        }

        FileUtils.setPermissions(
                mUserKeyFile.toString(),
                FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
    }

    /**
     * When {@code enabled} is {@code true}, this allows ADB debugging and starts the ADB handler
     * thread. When {@code enabled} is {@code false}, this disallows ADB debugging for the given
     * @{code transportType}. See {@link IAdbTransport} for all available transport types.
     * If all transport types are disabled, the ADB handler thread will shut down.
     */
    public void setAdbEnabled(boolean enabled, byte transportType) {
        if (transportType == AdbTransportType.USB) {
            mHandler.sendEmptyMessage(enabled ? AdbDebuggingHandler.MESSAGE_ADB_ENABLED
                                              : AdbDebuggingHandler.MESSAGE_ADB_DISABLED);
        } else if (transportType == AdbTransportType.WIFI) {
            mHandler.sendEmptyMessage(enabled ? AdbDebuggingHandler.MSG_ADBDWIFI_ENABLE
                                              : AdbDebuggingHandler.MSG_ADBDWIFI_DISABLE);
        } else {
            throw new IllegalArgumentException(
                    "setAdbEnabled called with unimplemented transport type=" + transportType);
        }
    }

    /**
     * Allows the debugging from the endpoint identified by {@code publicKey} either once or
     * always if {@code alwaysAllow} is {@code true}.
     */
    public void allowDebugging(boolean alwaysAllow, String publicKey) {
        Message msg = mHandler.obtainMessage(AdbDebuggingHandler.MESSAGE_ADB_ALLOW);
        msg.arg1 = alwaysAllow ? 1 : 0;
        msg.obj = publicKey;
        mHandler.sendMessage(msg);
    }

    /**
     * Denies debugging connection from the device that last requested to connect.
     */
    public void denyDebugging() {
        mHandler.sendEmptyMessage(AdbDebuggingHandler.MESSAGE_ADB_DENY);
    }

    /**
     * Clears all previously accepted ADB debugging public keys. Any subsequent request will need
     * to pass through {@link #allowUsbDebugging(boolean, String)} again.
     */
    public void clearDebuggingKeys() {
        mHandler.sendEmptyMessage(AdbDebuggingHandler.MESSAGE_ADB_CLEAR);
    }

    /**
     * Allows wireless debugging on the network identified by {@code bssid} either once
     * or always if {@code alwaysAllow} is {@code true}.
     */
    public void allowWirelessDebugging(boolean alwaysAllow, String bssid) {
        Message msg = mHandler.obtainMessage(AdbDebuggingHandler.MSG_ADBWIFI_ALLOW);
        msg.arg1 = alwaysAllow ? 1 : 0;
        msg.obj = bssid;
        mHandler.sendMessage(msg);
    }

    /**
     * Denies wireless debugging connection on the last requested network.
     */
    public void denyWirelessDebugging() {
        mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_ADBWIFI_DENY);
    }

    /**
     * Returns the port adbwifi is currently opened on.
     */
    public int getAdbWirelessPort() {
        AdbConnectionInfo info = getAdbConnectionInfo();
        if (info == null) {
            return 0;
        }
        return info.getPort();
    }

    /**
     * Returns the list of paired devices.
     */
    public Map<String, PairDevice> getPairedDevices() {
        AdbKeyStore keystore = new AdbKeyStore();
        return keystore.getPairedDevices();
    }

    /**
     * Unpair with device
     */
    public void unpairDevice(String fingerprint) {
        Message message = Message.obtain(mHandler,
                                         AdbDebuggingHandler.MSG_REQ_UNPAIR,
                                         fingerprint);
        mHandler.sendMessage(message);
    }

    /**
     * Enable pairing by pairing code
     */
    public void enablePairingByPairingCode() {
        mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_PAIR_PAIRING_CODE);
    }

    /**
     * Enable pairing by pairing code
     */
    public void enablePairingByQrCode(String serviceName, String password) {
        Bundle bundle = new Bundle();
        bundle.putString("serviceName", serviceName);
        bundle.putString("password", password);
        Message message = Message.obtain(mHandler,
                                         AdbDebuggingHandler.MSG_PAIR_QR_CODE,
                                         bundle);
        mHandler.sendMessage(message);
    }

    /**
     * Disables pairing
     */
    public void disablePairing() {
        mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_PAIRING_CANCEL);
    }

    /**
     * Status enabled/disabled check
     */
    public boolean isAdbWifiEnabled() {
        return mAdbWifiEnabled;
    }

    /**
     * Notify that they key files were updated so the AdbKeyManager reloads the keys.
     */
    public void notifyKeyFilesUpdated() {
        mHandler.sendEmptyMessage(AdbDebuggingHandler.MESSAGE_KEY_FILES_UPDATED);
    }

    /**
     * Sends a message to the handler to persist the keystore.
     */
    private void sendPersistKeyStoreMessage() {
        Message msg = mHandler.obtainMessage(AdbDebuggingHandler.MESSAGE_ADB_PERSIST_KEYSTORE);
        mHandler.sendMessage(msg);
    }

    /**
     * Dump the USB debugging state.
     */
    public void dump(DualDumpOutputStream dump, String idName, long id) {
        long token = dump.start(idName, id);

        dump.write("connected_to_adb", AdbDebuggingManagerProto.CONNECTED_TO_ADB, mThread != null);
        writeStringIfNotNull(dump, "last_key_received", AdbDebuggingManagerProto.LAST_KEY_RECEVIED,
                mFingerprints);

        try {
            dump.write("user_keys", AdbDebuggingManagerProto.USER_KEYS,
                    FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
        } catch (IOException e) {
            Slog.i(TAG, "Cannot read user keys", e);
        }

        try {
            dump.write("system_keys", AdbDebuggingManagerProto.SYSTEM_KEYS,
                    FileUtils.readTextFile(new File("/adb_keys"), 0, null));
        } catch (IOException e) {
            Slog.i(TAG, "Cannot read system keys", e);
        }

        try {
            dump.write("keystore", AdbDebuggingManagerProto.KEYSTORE,
                    FileUtils.readTextFile(mTempKeysFile, 0, null));
        } catch (IOException e) {
            Slog.i(TAG, "Cannot read keystore: ", e);
        }

        dump.end(token);
    }

    /**
     * Handles adb keys for which the user has granted the 'always allow' option. This class ensures
     * these grants are revoked after a period of inactivity as specified in the
     * ADB_ALLOWED_CONNECTION_TIME setting.
     */
    class AdbKeyStore {
        private AtomicFile mAtomicKeyFile;

        private final Set<String> mSystemKeys;
        private final Map<String, Long> mKeyMap = new HashMap<>();
        private final List<String> mTrustedNetworks = new ArrayList<>();

        private static final int KEYSTORE_VERSION = 1;
        private static final int MAX_SUPPORTED_KEYSTORE_VERSION = 1;
        private static final String XML_KEYSTORE_START_TAG = "keyStore";
        private static final String XML_ATTRIBUTE_VERSION = "version";
        private static final String XML_TAG_ADB_KEY = "adbKey";
        private static final String XML_ATTRIBUTE_KEY = "key";
        private static final String XML_ATTRIBUTE_LAST_CONNECTION = "lastConnection";
        // A list of trusted networks a device can always wirelessly debug on (always allow).
        // TODO: Move trusted networks list into a different file?
        private static final String XML_TAG_WIFI_ACCESS_POINT = "wifiAP";
        private static final String XML_ATTRIBUTE_WIFI_BSSID = "bssid";

        private static final String SYSTEM_KEY_FILE = "/adb_keys";

        /**
         * Value returned by {@code getLastConnectionTime} when there is no previously saved
         * connection time for the specified key.
         */
        public static final long NO_PREVIOUS_CONNECTION = 0;

        /**
         * Create an AdbKeyStore instance.
         *
         * <p>Upon creation, we parse {@link #mTempKeysFile} to determine authorized WiFi APs and
         * retrieve the map of stored ADB keys and their last connected times. After that, we read
         * the {@link #mUserKeyFile}, and any keys that exist in that file that do not exist in the
         * map are added to the map (for backwards compatibility).
         */
        AdbKeyStore() {
            initKeyFile();
            readTempKeysFile();
            mSystemKeys = getSystemKeysFromFile(SYSTEM_KEY_FILE);
            addExistingUserKeysToKeyStore();
        }

        public void reloadKeyMap() {
            readTempKeysFile();
        }

        public void addTrustedNetwork(String bssid) {
            mTrustedNetworks.add(bssid);
            sendPersistKeyStoreMessage();
        }

        public Map<String, PairDevice> getPairedDevices() {
            Map<String, PairDevice> pairedDevices = new HashMap<String, PairDevice>();
            for (Map.Entry<String, Long> keyEntry : mKeyMap.entrySet()) {
                String fingerprints = getFingerprints(keyEntry.getKey());
                String hostname = "nouser@nohostname";
                String[] args = keyEntry.getKey().split("\\s+");
                if (args.length > 1) {
                    hostname = args[1];
                }
                PairDevice pairDevice = new PairDevice();
                pairDevice.name = hostname;
                pairDevice.guid = fingerprints;
                pairDevice.connected = mWifiConnectedKeys.contains(keyEntry.getKey());
                pairedDevices.put(keyEntry.getKey(), pairDevice);
            }
            return pairedDevices;
        }

        public String findKeyFromFingerprint(String fingerprint) {
            for (Map.Entry<String, Long> entry : mKeyMap.entrySet()) {
                String f = getFingerprints(entry.getKey());
                if (fingerprint.equals(f)) {
                    return entry.getKey();
                }
            }
            return null;
        }

        public void removeKey(String key) {
            if (mKeyMap.containsKey(key)) {
                mKeyMap.remove(key);
                sendPersistKeyStoreMessage();
            }
        }

        /**
         * Initializes the key file that will be used to persist the adb grants.
         */
        private void initKeyFile() {
            // mTempKeysFile can be null if the adb file cannot be obtained
            if (mTempKeysFile != null) {
                mAtomicKeyFile = new AtomicFile(mTempKeysFile);
            }
        }

        private Set<String> getSystemKeysFromFile(String fileName) {
            Set<String> systemKeys = new HashSet<>();
            File systemKeyFile = new File(fileName);
            if (systemKeyFile.exists()) {
                try (BufferedReader in = new BufferedReader(new FileReader(systemKeyFile))) {
                    String key;
                    while ((key = in.readLine()) != null) {
                        key = key.trim();
                        if (key.length() > 0) {
                            systemKeys.add(key);
                        }
                    }
                } catch (IOException e) {
                    Slog.e(TAG, "Caught an exception reading " + fileName + ": " + e);
                }
            }
            return systemKeys;
        }

        /**
         * Returns whether there are any 'always allowed' keys in the keystore.
         */
        public boolean isEmpty() {
            return mKeyMap.isEmpty();
        }

        /**
         * Iterates through the keys in the keystore and removes any that are beyond the window
         * within which connections are automatically allowed without user interaction.
         */
        public void updateKeyStore() {
            if (filterOutOldKeys()) {
                sendPersistKeyStoreMessage();
            }
        }

        /**
         * Update the key map and the trusted networks list with values parsed from the temp keys
         * file.
         */
        private void readTempKeysFile() {
            mKeyMap.clear();
            mTrustedNetworks.clear();
            if (mAtomicKeyFile == null) {
                initKeyFile();
                if (mAtomicKeyFile == null) {
                    Slog.e(
                            TAG,
                            "Unable to obtain the key file, " + mTempKeysFile + ", for reading");
                    return;
                }
            }
            if (!mAtomicKeyFile.exists()) {
                return;
            }
            try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
                TypedXmlPullParser parser;
                try {
                    parser = Xml.resolvePullParser(keyStream);
                    XmlUtils.beginDocument(parser, XML_KEYSTORE_START_TAG);

                    int keystoreVersion = parser.getAttributeInt(null, XML_ATTRIBUTE_VERSION);
                    if (keystoreVersion > MAX_SUPPORTED_KEYSTORE_VERSION) {
                        Slog.e(TAG, "Keystore version=" + keystoreVersion
                                + " not supported (max_supported="
                                + MAX_SUPPORTED_KEYSTORE_VERSION + ")");
                        return;
                    }
                } catch (XmlPullParserException e) {
                    // This could be because the XML document doesn't start with
                    // XML_KEYSTORE_START_TAG. Try again, instead just starting the document with
                    // the adbKey tag (the old format).
                    parser = Xml.resolvePullParser(keyStream);
                }
                readKeyStoreContents(parser);
            } catch (IOException e) {
                Slog.e(TAG, "Caught an IOException parsing the XML key file: ", e);
            } catch (XmlPullParserException e) {
                Slog.e(TAG, "Caught XmlPullParserException parsing the XML key file: ", e);
            }
        }

        private void readKeyStoreContents(TypedXmlPullParser parser)
                throws XmlPullParserException, IOException {
            // This parser is very forgiving. For backwards-compatibility, we simply iterate through
            // all the tags in the file, skipping over anything that's not an <adbKey> tag or a
            // <wifiAP> tag. Invalid tags (such as ones that don't have a valid "lastConnection"
            // attribute) are simply ignored.
            while ((parser.next()) != XmlPullParser.END_DOCUMENT) {
                String tagName = parser.getName();
                if (XML_TAG_ADB_KEY.equals(tagName)) {
                    addAdbKeyToKeyMap(parser);
                } else if (XML_TAG_WIFI_ACCESS_POINT.equals(tagName)) {
                    addTrustedNetworkToTrustedNetworks(parser);
                } else {
                    Slog.w(TAG, "Ignoring tag '" + tagName + "'. Not recognized.");
                }
                XmlUtils.skipCurrentTag(parser);
            }
        }

        private void addAdbKeyToKeyMap(TypedXmlPullParser parser) {
            String key = parser.getAttributeValue(null, XML_ATTRIBUTE_KEY);
            try {
                long connectionTime =
                        parser.getAttributeLong(null, XML_ATTRIBUTE_LAST_CONNECTION);
                mKeyMap.put(key, connectionTime);
            } catch (XmlPullParserException e) {
                Slog.e(TAG, "Error reading adbKey attributes", e);
            }
        }

        private void addTrustedNetworkToTrustedNetworks(TypedXmlPullParser parser) {
            String bssid = parser.getAttributeValue(null, XML_ATTRIBUTE_WIFI_BSSID);
            mTrustedNetworks.add(bssid);
        }

        /**
         * Updates the keystore with keys that were previously set to be always allowed before the
         * connection time of keys was tracked.
         */
        private void addExistingUserKeysToKeyStore() {
            if (mUserKeyFile == null || !mUserKeyFile.exists()) {
                return;
            }
            boolean mapUpdated = false;
            try (BufferedReader in = new BufferedReader(new FileReader(mUserKeyFile))) {
                String key;
                while ((key = in.readLine()) != null) {
                    // if the keystore does not contain the key from the user key file then add
                    // it to the Map with the current system time to prevent it from expiring
                    // immediately if the user is actively using this key.
                    if (!mKeyMap.containsKey(key)) {
                        mKeyMap.put(key, mTicker.currentTimeMillis());
                        mapUpdated = true;
                    }
                }
            } catch (IOException e) {
                Slog.e(TAG, "Caught an exception reading " + mUserKeyFile + ": " + e);
            }
            if (mapUpdated) {
                sendPersistKeyStoreMessage();
            }
        }

        /**
         * Writes the key map to the key file.
         */
        public void persistKeyStore() {
            // if there is nothing in the key map then ensure any keys left in the keystore files
            // are deleted as well.
            filterOutOldKeys();
            if (mKeyMap.isEmpty() && mTrustedNetworks.isEmpty()) {
                deleteKeyStore();
                return;
            }
            if (mAtomicKeyFile == null) {
                initKeyFile();
                if (mAtomicKeyFile == null) {
                    Slog.e(
                            TAG,
                            "Unable to obtain the key file, " + mTempKeysFile + ", for writing");
                    return;
                }
            }
            FileOutputStream keyStream = null;
            try {
                keyStream = mAtomicKeyFile.startWrite();
                TypedXmlSerializer serializer = Xml.resolveSerializer(keyStream);
                serializer.startDocument(null, true);

                serializer.startTag(null, XML_KEYSTORE_START_TAG);
                serializer.attributeInt(null, XML_ATTRIBUTE_VERSION, KEYSTORE_VERSION);
                for (Map.Entry<String, Long> keyEntry : mKeyMap.entrySet()) {
                    serializer.startTag(null, XML_TAG_ADB_KEY);
                    serializer.attribute(null, XML_ATTRIBUTE_KEY, keyEntry.getKey());
                    serializer.attributeLong(null, XML_ATTRIBUTE_LAST_CONNECTION,
                            keyEntry.getValue());
                    serializer.endTag(null, XML_TAG_ADB_KEY);
                }
                for (String bssid : mTrustedNetworks) {
                    serializer.startTag(null, XML_TAG_WIFI_ACCESS_POINT);
                    serializer.attribute(null, XML_ATTRIBUTE_WIFI_BSSID, bssid);
                    serializer.endTag(null, XML_TAG_WIFI_ACCESS_POINT);
                }
                serializer.endTag(null, XML_KEYSTORE_START_TAG);
                serializer.endDocument();
                mAtomicKeyFile.finishWrite(keyStream);
            } catch (IOException e) {
                Slog.e(TAG, "Caught an exception writing the key map: ", e);
                mAtomicKeyFile.failWrite(keyStream);
            }
            writeKeys(mKeyMap.keySet());
        }

        private boolean filterOutOldKeys() {
            long allowedTime = getAllowedConnectionTime();
            if (allowedTime == 0) {
                return false;
            }
            boolean keysDeleted = false;
            long systemTime = mTicker.currentTimeMillis();
            Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
            while (keyMapIterator.hasNext()) {
                Map.Entry<String, Long> keyEntry = keyMapIterator.next();
                long connectionTime = keyEntry.getValue();
                if (systemTime > (connectionTime + allowedTime)) {
                    keyMapIterator.remove();
                    keysDeleted = true;
                }
            }
            // if any keys were deleted then the key file should be rewritten with the active keys
            // to prevent authorizing a key that is now beyond the allowed window.
            if (keysDeleted) {
                writeKeys(mKeyMap.keySet());
            }
            return keysDeleted;
        }

        /**
         * Returns the time in ms that the next key will expire or -1 if there are no keys or the
         * keys will not expire.
         */
        public long getNextExpirationTime() {
            long minExpiration = -1;
            long allowedTime = getAllowedConnectionTime();
            // if the allowedTime is 0 then keys never expire; return -1 to indicate this
            if (allowedTime == 0) {
                return minExpiration;
            }
            long systemTime = mTicker.currentTimeMillis();
            Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
            while (keyMapIterator.hasNext()) {
                Map.Entry<String, Long> keyEntry = keyMapIterator.next();
                long connectionTime = keyEntry.getValue();
                // if the key has already expired then ensure that the result is set to 0 so that
                // any scheduled jobs to clean up the keystore can run right away.
                long keyExpiration = Math.max(0, (connectionTime + allowedTime) - systemTime);
                if (minExpiration == -1 || keyExpiration < minExpiration) {
                    minExpiration = keyExpiration;
                }
            }
            return minExpiration;
        }

        /**
         * Removes all of the entries in the key map and deletes the key file.
         */
        public void deleteKeyStore() {
            mKeyMap.clear();
            mTrustedNetworks.clear();
            if (mUserKeyFile != null) {
                mUserKeyFile.delete();
            }
            if (mAtomicKeyFile == null) {
                return;
            }
            mAtomicKeyFile.delete();
        }

        /**
         * Returns the time of the last connection from the specified key, or {@code
         * NO_PREVIOUS_CONNECTION} if the specified key does not have an active adb grant.
         */
        public long getLastConnectionTime(String key) {
            return mKeyMap.getOrDefault(key, NO_PREVIOUS_CONNECTION);
        }

        /**
         * Sets the time of the last connection for the specified key to the provided time.
         */
        public void setLastConnectionTime(String key, long connectionTime) {
            setLastConnectionTime(key, connectionTime, false);
        }

        /**
         * Sets the time of the last connection for the specified key to the provided time. If force
         * is set to true the time will be set even if it is older than the previously written
         * connection time.
         */
        @VisibleForTesting
        void setLastConnectionTime(String key, long connectionTime, boolean force) {
            // Do not set the connection time to a value that is earlier than what was previously
            // stored as the last connection time unless force is set.
            if (mKeyMap.containsKey(key) && mKeyMap.get(key) >= connectionTime && !force) {
                return;
            }
            // System keys are always allowed so there's no need to keep track of their connection
            // time.
            if (mSystemKeys.contains(key)) {
                return;
            }
            mKeyMap.put(key, connectionTime);
        }

        /**
         * Returns the connection time within which a connection from an allowed key is
         * automatically allowed without user interaction.
         */
        public long getAllowedConnectionTime() {
            return Settings.Global.getLong(mContext.getContentResolver(),
                    Settings.Global.ADB_ALLOWED_CONNECTION_TIME,
                    Settings.Global.DEFAULT_ADB_ALLOWED_CONNECTION_TIME);
        }

        /**
         * Returns whether the specified key should be authroized to connect without user
         * interaction. This requires that the user previously connected this device and selected
         * the option to 'Always allow', and the time since the last connection is within the
         * allowed window.
         */
        public boolean isKeyAuthorized(String key) {
            // A system key is always authorized to connect.
            if (mSystemKeys.contains(key)) {
                return true;
            }
            long lastConnectionTime = getLastConnectionTime(key);
            if (lastConnectionTime == NO_PREVIOUS_CONNECTION) {
                return false;
            }
            long allowedConnectionTime = getAllowedConnectionTime();
            // if the allowed connection time is 0 then revert to the previous behavior of always
            // allowing previously granted adb grants.
            return allowedConnectionTime == 0
                    || (mTicker.currentTimeMillis() < (lastConnectionTime + allowedConnectionTime));
        }

        /**
         * Returns whether the specified bssid is in the list of trusted networks. This requires
         * that the user previously allowed wireless debugging on this network and selected the
         * option to 'Always allow'.
         */
        public boolean isTrustedNetwork(String bssid) {
            return mTrustedNetworks.contains(bssid);
        }
    }

    /**
     * A Guava-like interface for getting the current system time.
     *
     * This allows us to swap a fake ticker in for testing to reduce "Thread.sleep()" calls and test
     * for exact expected times instead of random ones.
     */
    @VisibleForTesting
    interface Ticker {
        long currentTimeMillis();
    }
}
