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

Commit 8e607d84 authored by Joshua Duong's avatar Joshua Duong Committed by Android (Google) Code Review
Browse files

Merge "[adbwifi] Make AdbManager changes for adb over WiFi."

parents 52815246 a5969b5a
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -255,6 +255,10 @@ message SystemMessage {
    // Inform the user a foreground service while-in-use permission is restricted.
    // Inform the user a foreground service while-in-use permission is restricted.
    NOTE_FOREGROUND_SERVICE_WHILE_IN_USE_PERMISSION = 61;
    NOTE_FOREGROUND_SERVICE_WHILE_IN_USE_PERMISSION = 61;


    // Display the Android Debug Protocol status
    // Package: android
    NOTE_ADB_WIFI_ACTIVE = 62;

    // ADD_NEW_IDS_ABOVE_THIS_LINE
    // ADD_NEW_IDS_ABOVE_THIS_LINE
    // Legacy IDs with arbitrary values appear below
    // Legacy IDs with arbitrary values appear below
    // Legacy IDs existed as stable non-conflicting constants prior to the O release
    // Legacy IDs existed as stable non-conflicting constants prior to the O release
+1209 −58

File changed.

Preview size limit exceeded, changes collapsed.

+130 −16
Original line number Original line Diff line number Diff line
@@ -21,8 +21,10 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.content.ContentResolver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.debug.AdbManager;
import android.debug.AdbManagerInternal;
import android.debug.AdbManagerInternal;
import android.debug.AdbTransportType;
import android.debug.AdbTransportType;
import android.debug.IAdbManager;
import android.debug.IAdbManager;
@@ -34,6 +36,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings;
import android.service.adb.AdbServiceDumpProto;
import android.service.adb.AdbServiceDumpProto;
import android.sysprop.AdbProperties;
import android.sysprop.AdbProperties;
@@ -44,6 +47,7 @@ import android.util.proto.ProtoOutputStream;


import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.LocalServices;
@@ -54,12 +58,34 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Collections;
import java.util.Map;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


/**
/**
 * The Android Debug Bridge (ADB) service. This controls the availability of ADB and authorization
 * The Android Debug Bridge (ADB) service. This controls the availability of ADB and authorization
 * of devices allowed to connect to ADB.
 * of devices allowed to connect to ADB.
 */
 */
public class AdbService extends IAdbManager.Stub {
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}.
     * Manages the service lifecycle for {@code AdbService} in {@code SystemServer}.
     */
     */
@@ -129,9 +155,8 @@ public class AdbService extends IAdbManager.Stub {
            mIsAdbUsbEnabled = containsFunction(
            mIsAdbUsbEnabled = containsFunction(
                    SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
                    SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
                    UsbManager.USB_FUNCTION_ADB);
                    UsbManager.USB_FUNCTION_ADB);
            // TODO(joshuaduong): Read the adb wifi state from a persistent system
            mIsAdbWifiEnabled = "1".equals(
            // property (persist.sys.adb.wifi).
                    SystemProperties.get(WIFI_PERSISTENT_CONFIG_PROPERTY, "0"));
            mIsAdbWifiEnabled = false;


            // register observer to listen for settings changes
            // register observer to listen for settings changes
            mObserver = new AdbSettingsObserver();
            mObserver = new AdbSettingsObserver();
@@ -189,6 +214,7 @@ public class AdbService extends IAdbManager.Stub {
     * May also contain vendor-specific default functions for testing purposes.
     * 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 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 Context mContext;
    private final ContentResolver mContentResolver;
    private final ContentResolver mContentResolver;
@@ -245,8 +271,9 @@ public class AdbService extends IAdbManager.Stub {
    }
    }


    @Override
    @Override
    public void allowDebugging(boolean alwaysAllow, String publicKey) {
    public void allowDebugging(boolean alwaysAllow, @NonNull String publicKey) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        Preconditions.checkStringNotEmpty(publicKey);
        if (mDebuggingManager != null) {
        if (mDebuggingManager != null) {
            mDebuggingManager.allowDebugging(alwaysAllow, publicKey);
            mDebuggingManager.allowDebugging(alwaysAllow, publicKey);
        }
        }
@@ -296,53 +323,118 @@ public class AdbService extends IAdbManager.Stub {
    }
    }


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


    @Override
    @Override
    public void denyWirelessDebugging() {
    public void denyWirelessDebugging() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        // TODO(joshuaduong): NOT IMPLEMENTED
        if (mDebuggingManager != null) {
            mDebuggingManager.denyWirelessDebugging();
        }
    }
    }


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


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


    @Override
    @Override
    public void enablePairingByPairingCode() {
    public void enablePairingByPairingCode() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        // TODO(joshuaduong): NOT IMPLEMENTED
        if (mDebuggingManager != null) {
            mDebuggingManager.enablePairingByPairingCode();
        }
    }
    }


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


    @Override
    @Override
    public void disablePairing() {
    public void disablePairing() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        // TODO(joshuaduong): NOT IMPLEMENTED
        if (mDebuggingManager != null) {
            mDebuggingManager.disablePairing();
        }
    }
    }


    @Override
    @Override
    public int getAdbWirelessPort() {
    public int getAdbWirelessPort() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
        // TODO(joshuaduong): NOT IMPLEMENTED
        if (mDebuggingManager != null) {
        return 0;
            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);
        mContext.sendBroadcastAsUser(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 setAdbEnabled(boolean enable, byte transportType) {
    private void setAdbEnabled(boolean enable, byte transportType) {
@@ -356,11 +448,33 @@ public class AdbService extends IAdbManager.Stub {
            mIsAdbUsbEnabled = enable;
            mIsAdbUsbEnabled = enable;
        } else if (transportType == AdbTransportType.WIFI && enable != mIsAdbWifiEnabled) {
        } else if (transportType == AdbTransportType.WIFI && enable != mIsAdbWifiEnabled) {
            mIsAdbWifiEnabled = enable;
            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 {
        } else {
            // No change
            // No change
            return;
            return;
        }
        }


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

        for (IAdbTransport transport : mTransports.values()) {
        for (IAdbTransport transport : mTransports.values()) {
            try {
            try {
                transport.onAdbEnabled(enable, transportType);
                transport.onAdbEnabled(enable, transportType);
+3 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ cc_library_static {
        "BroadcastRadio/regions.cpp",
        "BroadcastRadio/regions.cpp",
        "stats/PowerStatsPuller.cpp",
        "stats/PowerStatsPuller.cpp",
        "stats/SubsystemSleepStatePuller.cpp",
        "stats/SubsystemSleepStatePuller.cpp",
        "com_android_server_adb_AdbDebuggingManager.cpp",
        "com_android_server_am_BatteryStatsService.cpp",
        "com_android_server_am_BatteryStatsService.cpp",
        "com_android_server_connectivity_Vpn.cpp",
        "com_android_server_connectivity_Vpn.cpp",
        "com_android_server_ConsumerIrService.cpp",
        "com_android_server_ConsumerIrService.cpp",
@@ -86,6 +87,8 @@ cc_library_static {
cc_defaults {
cc_defaults {
    name: "libservices.core-libs",
    name: "libservices.core-libs",
    shared_libs: [
    shared_libs: [
        "libadb_pairing_server",
        "libadb_pairing_connection",
        "libandroid_runtime",
        "libandroid_runtime",
        "libandroidfw",
        "libandroidfw",
        "libaudioclient",
        "libaudioclient",
+168 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */

#define LOG_TAG "AdbDebuggingManager-JNI"

#define LOG_NDEBUG 0

#include <algorithm>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <random>
#include <string>
#include <vector>

#include <adb/pairing/pairing_server.h>
#include <android-base/properties.h>
#include <utils/Log.h>

#include <nativehelper/JNIHelp.h>
#include "jni.h"

namespace android {

// ----------------------------------------------------------------------------
namespace {

template <class T, class N>
class JSmartWrapper {
public:
    JSmartWrapper(JNIEnv* env, T* jData) : mEnv(env), mJData(jData) {}

    virtual ~JSmartWrapper() = default;

    const N* data() const { return mRawData; }

    jsize size() const { return mSize; }

protected:
    N* mRawData = nullptr;
    JNIEnv* mEnv = nullptr;
    T* mJData = nullptr;
    jsize mSize = 0;
}; // JSmartWrapper

class JStringUTFWrapper : public JSmartWrapper<jstring, const char> {
public:
    explicit JStringUTFWrapper(JNIEnv* env, jstring* str) : JSmartWrapper(env, str) {
        mRawData = env->GetStringUTFChars(*str, NULL);
        mSize = env->GetStringUTFLength(*str);
    }

    virtual ~JStringUTFWrapper() {
        if (data()) {
            mEnv->ReleaseStringUTFChars(*mJData, mRawData);
        }
    }
}; // JStringUTFWrapper

struct ServerDeleter {
    void operator()(PairingServerCtx* p) { pairing_server_destroy(p); }
};
using PairingServerPtr = std::unique_ptr<PairingServerCtx, ServerDeleter>;
struct PairingResultWaiter {
    std::mutex mutex_;
    std::condition_variable cv_;
    std::optional<bool> is_valid_;
    PeerInfo peer_info_;

    static void ResultCallback(const PeerInfo* peer_info, void* opaque) {
        auto* p = reinterpret_cast<PairingResultWaiter*>(opaque);
        {
            std::unique_lock<std::mutex> lock(p->mutex_);
            if (peer_info) {
                memcpy(&(p->peer_info_), peer_info, sizeof(PeerInfo));
            }
            p->is_valid_ = (peer_info != nullptr);
        }
        p->cv_.notify_one();
    }
};

PairingServerPtr sServer;
std::unique_ptr<PairingResultWaiter> sWaiter;
} // namespace

static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring guid, jstring password) {
    // Server-side only sends its GUID on success.
    PeerInfo system_info = {};
    system_info.type = ADB_DEVICE_GUID;
    JStringUTFWrapper guidWrapper(env, &guid);
    memcpy(system_info.data, guidWrapper.data(), guidWrapper.size());

    JStringUTFWrapper passwordWrapper(env, &password);

    // Create the pairing server
    sServer = PairingServerPtr(
            pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(passwordWrapper.data()),
                                       passwordWrapper.size(), &system_info, 0));

    sWaiter.reset(new PairingResultWaiter);
    uint16_t port = pairing_server_start(sServer.get(), sWaiter->ResultCallback, sWaiter.get());
    if (port == 0) {
        ALOGE("Failed to start pairing server");
        return -1;
    }

    return port;
}

static void native_pairing_cancel(JNIEnv* /* env */, jclass /* clazz */) {
    if (sServer != nullptr) {
        sServer.reset();
    }
}

static jboolean native_pairing_wait(JNIEnv* env, jobject thiz) {
    ALOGI("Waiting for pairing server to complete");
    std::unique_lock<std::mutex> lock(sWaiter->mutex_);
    if (!sWaiter->is_valid_.has_value()) {
        sWaiter->cv_.wait(lock, [&]() { return sWaiter->is_valid_.has_value(); });
    }
    if (!*(sWaiter->is_valid_)) {
        return JNI_FALSE;
    }

    std::string peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
    // Write to PairingThread's member variables
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID mPublicKey = env->GetFieldID(clazz, "mPublicKey", "Ljava/lang/String;");
    jstring jpublickey = env->NewStringUTF(peer_public_key.c_str());
    env->SetObjectField(thiz, mPublicKey, jpublickey);
    return JNI_TRUE;
}

// ----------------------------------------------------------------------------

static const JNINativeMethod gPairingThreadMethods[] = {
        /* name, signature, funcPtr */
        {"native_pairing_start", "(Ljava/lang/String;Ljava/lang/String;)I",
         (void*)native_pairing_start},
        {"native_pairing_cancel", "()V", (void*)native_pairing_cancel},
        {"native_pairing_wait", "()Z", (void*)native_pairing_wait},
};

int register_android_server_AdbDebuggingManager(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env,
                                       "com/android/server/adb/AdbDebuggingManager$PairingThread",
                                       gPairingThreadMethods, NELEM(gPairingThreadMethods));
    (void)res; // Faked use when LOG_NDEBUG.
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
    return 0;
}

} /* namespace android */
Loading