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

Commit d5c8246a authored by Sherif Eid's avatar Sherif Eid Committed by Android (Google) Code Review
Browse files

Merge "Automatically enable ADB Wifi on trusted networks" into main

parents fc13b80f 6b2c1d50
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -223,6 +223,7 @@ java_library_static {
        "securebox",
        "apache-commons-math",
        "apache-commons-compress",
        "adb_flags_lib",
        "battery_saver_flag_lib",
        "notification_flags_lib",
        "power_hint_flags_lib",
+19 −5
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2025 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.
@@ -29,14 +29,18 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;

/** Monitors device Wifi and Network status in order to enable/disable ADB Wifi accordingly. */
public class AdbBroadcastReceiver extends BroadcastReceiver {
/**
 * Monitors Wi-Fi state changes to automatically disable ADB over Wi-Fi when the device disconnects
 * from Wi-Fi.
 */
public class AdbBroadcastReceiver extends BroadcastReceiver implements AdbNetworkMonitor {

    private static final String TAG = AdbBroadcastReceiver.class.getSimpleName();

    private final ContentResolver mContentResolver;
    private final Context mContext;
    private final AdbConnectionInfo mAdbConnectionInfo;
    private boolean mStarted = false;

    AdbBroadcastReceiver(@NonNull Context context, @NonNull AdbConnectionInfo info) {
        mContext = context;
@@ -44,14 +48,24 @@ public class AdbBroadcastReceiver extends BroadcastReceiver {
        mAdbConnectionInfo = info;
    }

    void register() {
    @Override
    public void register() {
        if (mStarted) {
            return;
        }
        IntentFilter intentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        mContext.registerReceiver(this, intentFilter);
        mStarted = true;
    }

    void unregister() {
    @Override
    public void unregister() {
        if (!mStarted) {
            return;
        }
        mContext.unregisterReceiver(this);
        mStarted = false;
    }

    private void disableWifi(String reason) {
+10 −6
Original line number Diff line number Diff line
@@ -474,8 +474,7 @@ public class AdbDebuggingManager {
        private NotificationManager mNotificationManager;
        private boolean mAdbNotificationShown;

        private final AdbBroadcastReceiver mBroadcastReceiver =
                new AdbBroadcastReceiver(mContext, mAdbConnectionInfo);
        private final AdbNetworkMonitor mAdbNetworkMonitor;

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

@@ -605,6 +604,12 @@ public class AdbDebuggingManager {
                thread.setHandler(this);
            }
            mThread = thread;
            if (com.android.server.adb.Flags.allowAdbWifiReconnect()) {
                mAdbNetworkMonitor =
                        new AdbWifiNetworkMonitor(mContext, mAdbKeyStore::isTrustedNetwork);
            } else {
                mAdbNetworkMonitor = new AdbBroadcastReceiver(mContext, mAdbConnectionInfo);
            }
        }

        // Show when at least one device is connected.
@@ -827,8 +832,7 @@ public class AdbDebuggingManager {
                    }

                    mAdbConnectionInfo.copy(currentInfo);
                    mBroadcastReceiver.register();

                    mAdbNetworkMonitor.register();
                    ensureAdbDebuggingThreadAlive();
                    startTLSPortPoller();
                    startAdbdWifi();
@@ -842,7 +846,7 @@ public class AdbDebuggingManager {
                    }
                    mAdbWifiEnabled = false;
                    mAdbConnectionInfo.clear();
                    mBroadcastReceiver.unregister();
                    mAdbNetworkMonitor.unregister();
                    stopAdbdWifi();
                    onAdbdWifiServerDisconnected(-1);
                }
@@ -864,7 +868,7 @@ public class AdbDebuggingManager {
                    }
                    mAdbConnectionInfo.copy(newInfo);
                    Settings.Global.putInt(mContentResolver, Settings.Global.ADB_WIFI_ENABLED, 1);
                    mBroadcastReceiver.register();
                    mAdbNetworkMonitor.register();
                    ensureAdbDebuggingThreadAlive();
                    startTLSPortPoller();
                    startAdbdWifi();
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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;

/**
 * Interface for monitoring network connectivity to enable/disable ADB over Wi-Fi.
 *
 * <p>Implementations of this interface are responsible for registering and unregistering network
 * monitoring processes.
 */
public interface AdbNetworkMonitor {

    /**
     * Registers the network monitoring process.
     *
     * <p>It is safe to call this method multiple times; implementations should handle this without
     * side effects.
     */
    void register();

    /**
     * Unregisters the network monitoring process.
     *
     * <p>It is safe to call this method multiple times, even if the monitor was not previously
     * registered.
     */
    void unregister();
}
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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 android.content.ContentResolver;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.WifiInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;

/**
 * Monitors Wi-Fi state changes to automatically enable ADB over Wi-Fi when the device connects to a
 * trusted network and disable it otherwise.
 */
public class AdbWifiNetworkMonitor extends ConnectivityManager.NetworkCallback
        implements AdbNetworkMonitor {

    private static final String TAG = AdbWifiNetworkMonitor.class.getSimpleName();

    private final Context mContext;
    private final ContentResolver mContentResolver;
    private final IsTrustedNetworkChecker mIsTrustedNetworkChecker;

    /**
     * Stores the BSSID of the most recently processed network.
     *
     * <p>This is used to deduplicate callbacks, which may fire multiple times for the same network
     * change event. By comparing against the last known BSSID, we can ensure we only react to a
     * given network update once.
     */
    @Nullable private String mLastBSSID;

    private boolean mStarted = false;

    @VisibleForTesting
    interface IsTrustedNetworkChecker {
        boolean isTrusted(String bssid);
    }

    AdbWifiNetworkMonitor(
            @NonNull Context context, @NonNull IsTrustedNetworkChecker isTrustedNetworkChecker) {
        // Flag is required to receive BSSID info in the callback.
        super(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO);

        mContext = context;
        mContentResolver = mContext.getContentResolver();
        mIsTrustedNetworkChecker = isTrustedNetworkChecker;
        register();
    }

    @Override
    public final void register() {
        if (mStarted) {
            return;
        }
        ConnectivityManager connectivityManager =
                mContext.getSystemService(ConnectivityManager.class);
        NetworkRequest request =
                new NetworkRequest.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        .build();
        connectivityManager.registerNetworkCallback(request, this);
        mStarted = true;
    }

    @Override
    public final void unregister() {
        // This NetworkMonitor must remain registered even when ADB over Wi-Fi is disabled.
        // This allows it to automatically re-enable ADB over Wi-Fi when the device connects
        // to a trusted network.
    }

    @Override
    public final void onCapabilitiesChanged(
            @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
        if (networkCapabilities.getTransportInfo() instanceof WifiInfo wifiInfo) {
            Slog.i(TAG, "Wi-Fi network available");
            processWifiConnection(wifiInfo);
        } else {
            setAdbWifiState(false, "Wi-Fi network not available. Disabling adb over Wi-Fi.");
        }
    }

    @Override
    public final void onLost(@NonNull Network network) {
        mLastBSSID = null;
        setAdbWifiState(false, "Wi-Fi network lost. Disabling adb over Wi-Fi.");
    }

    private void processWifiConnection(WifiInfo wifiInfo) {
        if (wifiInfo == null
                || wifiInfo.getNetworkId() == -1
                || TextUtils.isEmpty(wifiInfo.getBSSID())) {
            setAdbWifiState(false, "Wi-Fi connection info is invalid. Disabling adb over Wi-Fi.");
            return;
        }

        if (TextUtils.equals(wifiInfo.getBSSID(), mLastBSSID)) {
            Slog.i(TAG, "Received the same Wi-Fi BSSID. Ignoring.");
            return;
        }
        mLastBSSID = wifiInfo.getBSSID();

        boolean isTrusted = mIsTrustedNetworkChecker.isTrusted(wifiInfo.getBSSID());
        if (isTrusted) {
            setAdbWifiState(true, "Connected to a trusted Wi-Fi network. Enabling adb over Wi-Fi.");
        } else {
            setAdbWifiState(
                    false, "Connected to a non-trusted Wi-Fi network. Disabling adb over Wi-Fi.");
        }
    }

    @VisibleForTesting
    protected void setAdbWifiState(boolean enabled, String reason) {
        Slog.i(TAG, reason);
        Settings.Global.putInt(mContentResolver, Settings.Global.ADB_WIFI_ENABLED, enabled ? 1 : 0);
    }
}
Loading