/*
 * Copyright (C) 2018 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.function.pooled.PooledLambda.obtainMessage;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.debug.AdbManager;
import android.debug.AdbManagerInternal;
import android.debug.AdbTransportType;
import android.debug.IAdbManager;
import android.debug.IAdbTransport;
import android.debug.PairDevice;
import android.hardware.usb.UsbManager;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.adb.AdbServiceDumpProto;
import android.sysprop.AdbProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;

import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * The Android Debug Bridge (ADB) service. This controls the availability of ADB and authorization
 * of devices allowed to connect to ADB.
 */
public class AdbService extends IAdbManager.Stub {
    /**
     * Adb native daemon.
     */
    static final String ADBD = "adbd";

    /**
     * Command to start native service.
     */
    static final String CTL_START = "ctl.start";

    /**
     * Command to start native service.
     */
    static final String CTL_STOP = "ctl.stop";

    // The tcp port adb is currently using
    AtomicInteger mConnectionPort = new AtomicInteger(-1);

    private final AdbConnectionPortListener mPortListener = new AdbConnectionPortListener();
    private AdbDebuggingManager.AdbConnectionPortPoller mConnectionPortPoller;

    /**
     * Manages the service lifecycle for {@code AdbService} in {@code SystemServer}.
     */
    public static class Lifecycle extends SystemService {
        private AdbService mAdbService;

        public Lifecycle(Context context) {
            super(context);
        }

        @Override
        public void onStart() {
            mAdbService = new AdbService(getContext());
            publishBinderService(Context.ADB_SERVICE, mAdbService);
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mAdbService.systemReady();
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                FgThread.getHandler().sendMessage(obtainMessage(
                        AdbService::bootCompleted, mAdbService));
            }
        }
    }

    private class AdbManagerInternalImpl extends AdbManagerInternal {
        @Override
        public void registerTransport(IAdbTransport transport) {
            mTransports.put(transport.asBinder(), transport);
        }

        @Override
        public void unregisterTransport(IAdbTransport transport) {
            mTransports.remove(transport.asBinder());
        }

        @Override
        public boolean isAdbEnabled(byte transportType) {
            if (transportType == AdbTransportType.USB) {
                return mIsAdbUsbEnabled;
            } else if (transportType == AdbTransportType.WIFI) {
                return mIsAdbWifiEnabled;
            }
            throw new IllegalArgumentException(
                    "isAdbEnabled called with unimplemented transport type=" + transportType);
        }

        @Override
        public File getAdbKeysFile() {
            return mDebuggingManager == null ? null : mDebuggingManager.getUserKeyFile();
        }

        @Override
        public File getAdbTempKeysFile() {
            return mDebuggingManager == null ? null : mDebuggingManager.getAdbTempKeysFile();
        }

        @Override
        public void startAdbdForTransport(byte transportType) {
            FgThread.getHandler().sendMessage(obtainMessage(
                    AdbService::setAdbdEnabledForTransport, AdbService.this, true, transportType));
        }

        @Override
        public void stopAdbdForTransport(byte transportType) {
            FgThread.getHandler().sendMessage(obtainMessage(
                    AdbService::setAdbdEnabledForTransport, AdbService.this, false, transportType));
        }
    }

    private void initAdbState() {
        try {
            /*
             * Use the normal bootmode persistent prop to maintain state of adb across
             * all boot modes.
             */
            mIsAdbUsbEnabled = containsFunction(
                    SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
                    UsbManager.USB_FUNCTION_ADB);
            mIsAdbWifiEnabled = "1".equals(
                    SystemProperties.get(WIFI_PERSISTENT_CONFIG_PROPERTY, "0"));

            // register observer to listen for settings changes
            mObserver = new AdbSettingsObserver();
            mContentResolver.registerContentObserver(
                    Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
                    false, mObserver);
            mContentResolver.registerContentObserver(
                    Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED),
                    false, mObserver);
        } catch (Exception e) {
            Slog.e(TAG, "Error in initAdbState", e);
        }
    }

    private static boolean containsFunction(String functions, String function) {
        int index = functions.indexOf(function);
        if (index < 0) return false;
        if (index > 0 && functions.charAt(index - 1) != ',') return false;
        int charAfter = index + function.length();
        if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
        return true;
    }

    private class AdbSettingsObserver extends ContentObserver {
        private final Uri mAdbUsbUri = Settings.Global.getUriFor(Settings.Global.ADB_ENABLED);
        private final Uri mAdbWifiUri = Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED);

        AdbSettingsObserver() {
            super(null);
        }

        @Override
        public void onChange(boolean selfChange, @NonNull Uri uri, @UserIdInt int userId) {
            if (mAdbUsbUri.equals(uri)) {
                boolean shouldEnable = (Settings.Global.getInt(mContentResolver,
                        Settings.Global.ADB_ENABLED, 0) > 0);
                FgThread.getHandler().sendMessage(obtainMessage(
                        AdbService::setAdbEnabled, AdbService.this, shouldEnable,
                            AdbTransportType.USB));
            } else if (mAdbWifiUri.equals(uri)) {
                boolean shouldEnable = (Settings.Global.getInt(mContentResolver,
                        Settings.Global.ADB_WIFI_ENABLED, 0) > 0);
                FgThread.getHandler().sendMessage(obtainMessage(
                        AdbService::setAdbEnabled, AdbService.this, shouldEnable,
                            AdbTransportType.WIFI));
            }
        }
    }

    private static final String TAG = "AdbService";
    private static final boolean DEBUG = false;

    /**
     * The persistent property which stores whether adb is enabled or not.
     * May also contain vendor-specific default functions for testing purposes.
     */
    private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
    private static final String WIFI_PERSISTENT_CONFIG_PROPERTY = "persist.adb.tls_server.enable";

    private final Context mContext;
    private final ContentResolver mContentResolver;
    private final ArrayMap<IBinder, IAdbTransport> mTransports = new ArrayMap<>();

    private boolean mIsAdbUsbEnabled;
    private boolean mIsAdbWifiEnabled;
    private AdbDebuggingManager mDebuggingManager;

    private ContentObserver mObserver;

    private AdbService(Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mDebuggingManager = new AdbDebuggingManager(context);

        initAdbState();
        LocalServices.addService(AdbManagerInternal.class, new AdbManagerInternalImpl());
    }

    /**
     * Called in response to {@code SystemService.PHASE_ACTIVITY_MANAGER_READY} from {@code
     * SystemServer}.
     */
    public void systemReady() {
        if (DEBUG) Slog.d(TAG, "systemReady");

        // make sure the ADB_ENABLED setting value matches the current state
        try {
            Settings.Global.putInt(mContentResolver,
                    Settings.Global.ADB_ENABLED, mIsAdbUsbEnabled ? 1 : 0);
            Settings.Global.putInt(mContentResolver,
                    Settings.Global.ADB_WIFI_ENABLED, mIsAdbWifiEnabled ? 1 : 0);
        } catch (SecurityException e) {
            // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
            Slog.d(TAG, "ADB_ENABLED is restricted.");
        }
    }

    /**
     * Callend in response to {@code SystemService.PHASE_BOOT_COMPLETED} from {@code SystemServer}.
     */
    public void bootCompleted() {
        if (DEBUG) Slog.d(TAG, "boot completed");
        if (mDebuggingManager != null) {
            mDebuggingManager.setAdbEnabled(mIsAdbUsbEnabled, AdbTransportType.USB);
            mDebuggingManager.setAdbEnabled(mIsAdbWifiEnabled, AdbTransportType.WIFI);
        }
    }

    @Override
    public void allowDebugging(boolean alwaysAllow, @NonNull String publicKey) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        Preconditions.checkStringNotEmpty(publicKey);
        if (mDebuggingManager != null) {
            mDebuggingManager.allowDebugging(alwaysAllow, publicKey);
        }
    }

    @Override
    public void denyDebugging() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            mDebuggingManager.denyDebugging();
        }
    }

    @Override
    public void clearDebuggingKeys() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            mDebuggingManager.clearDebuggingKeys();
        } else {
            throw new RuntimeException("Cannot clear ADB debugging keys, "
                    + "AdbDebuggingManager not enabled");
        }
    }

    /**
     * @return true if the device supports secure ADB over Wi-Fi.
     * @hide
     */
    @Override
    public boolean isAdbWifiSupported() {
        mContext.enforceCallingPermission(
                android.Manifest.permission.MANAGE_DEBUGGING, "AdbService");
        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
    }

    /**
     * @return true if the device supports secure ADB over Wi-Fi and device pairing by
     * QR code.
     * @hide
     */
    @Override
    public boolean isAdbWifiQrSupported() {
        mContext.enforceCallingPermission(
                android.Manifest.permission.MANAGE_DEBUGGING, "AdbService");
        return isAdbWifiSupported() && mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA_ANY);
    }

    @Override
    public void allowWirelessDebugging(boolean alwaysAllow, @NonNull String bssid) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        Preconditions.checkStringNotEmpty(bssid);
        if (mDebuggingManager != null) {
            mDebuggingManager.allowWirelessDebugging(alwaysAllow, bssid);
        }
    }

    @Override
    public void denyWirelessDebugging() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            mDebuggingManager.denyWirelessDebugging();
        }
    }

    @Override
    public Map<String, PairDevice> getPairedDevices() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            return mDebuggingManager.getPairedDevices();
        }
        return null;
    }

    @Override
    public void unpairDevice(@NonNull String fingerprint) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        Preconditions.checkStringNotEmpty(fingerprint);
        if (mDebuggingManager != null) {
            mDebuggingManager.unpairDevice(fingerprint);
        }
    }

    @Override
    public void enablePairingByPairingCode() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            mDebuggingManager.enablePairingByPairingCode();
        }
    }

    @Override
    public void enablePairingByQrCode(@NonNull String serviceName, @NonNull String password) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        Preconditions.checkStringNotEmpty(serviceName);
        Preconditions.checkStringNotEmpty(password);
        if (mDebuggingManager != null) {
            mDebuggingManager.enablePairingByQrCode(serviceName, password);
        }
    }

    @Override
    public void disablePairing() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            mDebuggingManager.disablePairing();
        }
    }

    @Override
    public int getAdbWirelessPort() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        if (mDebuggingManager != null) {
            return mDebuggingManager.getAdbWirelessPort();
        }
        // If ro.adb.secure=0
        return mConnectionPort.get();
    }

    /**
     * This listener is only used when ro.adb.secure=0. Otherwise, AdbDebuggingManager will
     * do this.
     */
    class AdbConnectionPortListener implements AdbDebuggingManager.AdbConnectionPortListener {
        public void onPortReceived(int port) {
            if (port > 0 && port <= 65535) {
                mConnectionPort.set(port);
            } else {
                mConnectionPort.set(-1);
                // Turn off wifi debugging, since the server did not start.
                try {
                    Settings.Global.putInt(mContentResolver,
                            Settings.Global.ADB_WIFI_ENABLED, 0);
                } catch (SecurityException e) {
                    // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't
                    // be changed.
                    Slog.d(TAG, "ADB_ENABLED is restricted.");
                }
            }
            broadcastPortInfo(mConnectionPort.get());
        }
    }

    private void broadcastPortInfo(int port) {
        Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
        intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, (port >= 0)
                ? AdbManager.WIRELESS_STATUS_CONNECTED
                : AdbManager.WIRELESS_STATUS_DISCONNECTED);
        intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
        AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
        Slog.i(TAG, "sent port broadcast port=" + port);
    }

    private void startAdbd() {
        SystemProperties.set(CTL_START, ADBD);
    }

    private void stopAdbd() {
        if (!mIsAdbUsbEnabled && !mIsAdbWifiEnabled) {
            SystemProperties.set(CTL_STOP, ADBD);
        }
    }

    private void setAdbdEnabledForTransport(boolean enable, byte transportType) {
        if (transportType == AdbTransportType.USB) {
            mIsAdbUsbEnabled = enable;
        } else if (transportType == AdbTransportType.WIFI) {
            mIsAdbWifiEnabled = enable;
        }
        if (enable) {
            startAdbd();
        } else {
            stopAdbd();
        }
    }

    private void setAdbEnabled(boolean enable, byte transportType) {
        if (DEBUG) {
            Slog.d(TAG, "setAdbEnabled(" + enable + "), mIsAdbUsbEnabled=" + mIsAdbUsbEnabled
                    + ", mIsAdbWifiEnabled=" + mIsAdbWifiEnabled + ", transportType="
                        + transportType);
        }

        if (transportType == AdbTransportType.USB && enable != mIsAdbUsbEnabled) {
            mIsAdbUsbEnabled = enable;
        } else if (transportType == AdbTransportType.WIFI && enable != mIsAdbWifiEnabled) {
            mIsAdbWifiEnabled = enable;
            if (mIsAdbWifiEnabled) {
                if (!AdbProperties.secure().orElse(false) && mDebuggingManager == null) {
                    // Start adbd. If this is secure adb, then we defer enabling adb over WiFi.
                    SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1");
                    mConnectionPortPoller =
                            new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
                    mConnectionPortPoller.start();
                }
            } else {
                // Stop adb over WiFi.
                SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "0");
                if (mConnectionPortPoller != null) {
                    mConnectionPortPoller.cancelAndWait();
                    mConnectionPortPoller = null;
                }
            }
        } else {
            // No change
            return;
        }

        if (enable) {
            startAdbd();
        } else {
            stopAdbd();
        }

        for (IAdbTransport transport : mTransports.values()) {
            try {
                transport.onAdbEnabled(enable, transportType);
            } catch (RemoteException e) {
                Slog.w(TAG, "Unable to send onAdbEnabled to transport " + transport.toString());
            }
        }

        if (mDebuggingManager != null) {
            mDebuggingManager.setAdbEnabled(enable, transportType);
        }
    }

    @Override
    public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
            ParcelFileDescriptor err, String[] args) {
        return new AdbShellCommand(this).exec(
                this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(),
                args);
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;

        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
        final long ident = Binder.clearCallingIdentity();
        try {
            ArraySet<String> argsSet = new ArraySet<>();
            Collections.addAll(argsSet, args);

            boolean dumpAsProto = false;
            if (argsSet.contains("--proto")) {
                dumpAsProto = true;
            }

            if (argsSet.size() == 0 || argsSet.contains("-a") || dumpAsProto) {
                DualDumpOutputStream dump;
                if (dumpAsProto) {
                    dump = new DualDumpOutputStream(new ProtoOutputStream(fd));
                } else {
                    pw.println("ADB MANAGER STATE (dumpsys adb):");

                    dump = new DualDumpOutputStream(new IndentingPrintWriter(pw, "  "));
                }

                if (mDebuggingManager != null) {
                    mDebuggingManager.dump(dump, "debugging_manager",
                            AdbServiceDumpProto.DEBUGGING_MANAGER);
                }

                dump.flush();
            } else {
                pw.println("Dump current ADB state");
                pw.println("  No commands available");
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
}
