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

Change-Id: Id8571a8db96770cd699a71c5fcb50fb58c8e511b
This commit is contained in:
Automerger Merge Worker
2020-02-22 15:30:26 +00:00
7 changed files with 1537 additions and 100 deletions

View File

@@ -230,6 +230,10 @@ message SystemMessage {
// Package: android // Package: android
NOTE_TEST_HARNESS_MODE_ENABLED = 54; NOTE_TEST_HARNESS_MODE_ENABLED = 54;
// 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

View File

@@ -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);

View File

@@ -21,6 +21,7 @@ cc_library_static {
"BroadcastRadio/convert.cpp", "BroadcastRadio/convert.cpp",
"BroadcastRadio/regions.cpp", "BroadcastRadio/regions.cpp",
"com_android_server_AlarmManagerService.cpp", "com_android_server_AlarmManagerService.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",
@@ -69,6 +70,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",

View File

@@ -0,0 +1,187 @@
/*
* 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 */

View File

@@ -56,6 +56,7 @@ int register_android_server_net_NetworkStatsService(JNIEnv* env);
int register_android_server_security_VerityUtils(JNIEnv* env); int register_android_server_security_VerityUtils(JNIEnv* env);
int register_android_server_am_AppCompactor(JNIEnv* env); int register_android_server_am_AppCompactor(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env); int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_android_server_AdbDebuggingManager(JNIEnv* env);
}; };
using namespace android; using namespace android;
@@ -105,5 +106,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_security_VerityUtils(env); register_android_server_security_VerityUtils(env);
register_android_server_am_AppCompactor(env); register_android_server_am_AppCompactor(env);
register_android_server_am_LowMemDetector(env); register_android_server_am_LowMemDetector(env);
register_android_server_AdbDebuggingManager(env);
return JNI_VERSION_1_4; return JNI_VERSION_1_4;
} }

View File

@@ -1717,21 +1717,6 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
*/ */
private static final int ENUMERATION_TIME_OUT_MS = 2000; private static final int ENUMERATION_TIME_OUT_MS = 2000;
/**
* Command to start native service.
*/
protected static final String CTL_START = "ctl.start";
/**
* Command to start native service.
*/
protected static final String CTL_STOP = "ctl.stop";
/**
* Adb native daemon.
*/
protected static final String ADBD = "adbd";
/** /**
* Gadget HAL fully qualified instance name for registering for ServiceNotification. * Gadget HAL fully qualified instance name for registering for ServiceNotification.
*/ */
@@ -1913,17 +1898,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
return; return;
} }
try { try {
if ((config & UsbManager.FUNCTION_ADB) != 0) { // Adbd will be started by AdbService once Global.ADB_ENABLED is set.
/**
* Start adbd if ADB function is included in the configuration.
*/
setSystemProperty(CTL_START, ADBD);
} else {
/**
* Stop adbd otherwise.
*/
setSystemProperty(CTL_STOP, ADBD);
}
UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest, UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
config, chargingFunctions); config, chargingFunctions);
mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback, mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback,