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

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

Merge "Add visibility control to ADB QR code preference." into rvc-dev

parents 2f7a77b7 56ad92c3
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -47,7 +47,8 @@
            android:key="adb_pair_method_qrcode_pref"
            android:key="adb_pair_method_qrcode_pref"
            android:icon="@drawable/ic_scan_24dp"
            android:icon="@drawable/ic_scan_24dp"
            android:title="@string/adb_pair_method_qrcode_title"
            android:title="@string/adb_pair_method_qrcode_title"
            android:summary="@string/adb_pair_method_qrcode_summary"/>
            android:summary="@string/adb_pair_method_qrcode_summary"
            settings:controller="com.android.settings.development.AdbQrCodePreferenceController"/>
        <Preference
        <Preference
            android:key="adb_pair_method_code_pref"
            android:key="adb_pair_method_code_pref"
            android:title="@string/adb_pair_method_code_title"
            android:title="@string/adb_pair_method_code_title"
+79 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 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.settings.development;

import android.app.settings.SettingsEnums;
import android.content.Context;
import android.debug.IAdbManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.fragment.app.Fragment;
import androidx.preference.Preference;

import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;

/**
 * Controller for the "Pair device with QR code" preference in the Wireless debugging
 * fragment.
 */
public class AdbQrCodePreferenceController extends BasePreferenceController {
    private static final String TAG = "AdbQrCodePrefCtrl";

    private IAdbManager mAdbManager;
    private Fragment mParentFragment;

    public AdbQrCodePreferenceController(Context context, String key) {
        super(context, key);

        mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService(
                Context.ADB_SERVICE));
    }

    public void setParentFragment(Fragment parent) {
        mParentFragment = parent;
    }

    @Override
    public int getAvailabilityStatus() {
        try {
            return mAdbManager.isAdbWifiQrSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to check if adb wifi QR code scanning is supported.", e);
        }

        return UNSUPPORTED_ON_DEVICE;
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
            return false;
        }

        new SubSettingLauncher(preference.getContext())
                .setDestination(AdbQrcodeScannerFragment.class.getName())
                .setSourceMetricsCategory(SettingsEnums.SETTINGS_ADB_WIRELESS)
                .setResultListener(mParentFragment,
                    WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST)
                .launch();
        return true;
    }
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -193,6 +193,7 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to cancel pairing");
            Log.e(TAG, "Unable to cancel pairing");
        }
        }
        getActivity().setResult(Activity.RESULT_CANCELED);
        getActivity().finish();
        getActivity().finish();
    }
    }


@@ -268,6 +269,7 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
                    mAdbConfig.getPreSharedKey());
                    mAdbConfig.getPreSharedKey());
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to enable QR code pairing");
            Log.e(TAG, "Unable to enable QR code pairing");
            getActivity().setResult(Activity.RESULT_CANCELED);
            getActivity().finish();
            getActivity().finish();
        }
        }
    }
    }
+37 −53
Original line number Original line Diff line number Diff line
@@ -63,66 +63,44 @@ public class WirelessDebuggingFragment extends DashboardFragment
    private static final String TAG = "WirelessDebuggingFrag";
    private static final String TAG = "WirelessDebuggingFrag";


    // Activity result from clicking on a paired device.
    // Activity result from clicking on a paired device.
    private static final int PAIRED_DEVICE_REQUEST = 0;
    static final int PAIRED_DEVICE_REQUEST = 0;
    public static final String PAIRED_DEVICE_REQUEST_TYPE = "request_type";
    static final String PAIRED_DEVICE_REQUEST_TYPE = "request_type";
    public static final int FORGET_ACTION = 0;
    static final int FORGET_ACTION = 0;

    // Activity result from pairing a device.
    // Activity result from pairing a device.
    private static final int PAIRING_DEVICE_REQUEST = 1;
    static final int PAIRING_DEVICE_REQUEST = 1;
    public static final String PAIRING_DEVICE_REQUEST_TYPE = "request_type_pairing";
    static final String PAIRING_DEVICE_REQUEST_TYPE = "request_type_pairing";
    public static final int SUCCESS_ACTION = 0;
    static final int SUCCESS_ACTION = 0;
    public static final int FAIL_ACTION = 1;
    static final int FAIL_ACTION = 1;

    static final String PAIRED_DEVICE_EXTRA = "paired_device";
    public static final String PAIRED_DEVICE_EXTRA = "paired_device";
    static final String DEVICE_NAME_EXTRA = "device_name";
    public static final String DEVICE_NAME_EXTRA = "device_name";
    static final String IP_ADDR_EXTRA = "ip_addr";
    public static final String IP_ADDR_EXTRA = "ip_addr";

    private WirelessDebuggingEnabler mWifiDebuggingEnabler;


    private static AdbIpAddressPreferenceController sAdbIpAddressPreferenceController;
    // UI components
    // UI components
    private static final String PREF_KEY_ADB_DEVICE_NAME = "adb_device_name_pref";
    private static final String PREF_KEY_ADB_DEVICE_NAME = "adb_device_name_pref";
    private static final String PREF_KEY_ADB_IP_ADDR = "adb_ip_addr_pref";
    private static final String PREF_KEY_ADB_IP_ADDR = "adb_ip_addr_pref";
    private static final String PREF_KEY_PAIRING_METHODS_CATEGORY = "adb_pairing_methods_category";
    private static final String PREF_KEY_PAIRING_METHODS_CATEGORY = "adb_pairing_methods_category";
    private static final String PREF_KEY_ADB_QRCODE_PAIRING = "adb_pair_method_qrcode_pref";
    private static final String PREF_KEY_ADB_CODE_PAIRING = "adb_pair_method_code_pref";
    private static final String PREF_KEY_ADB_CODE_PAIRING = "adb_pair_method_code_pref";
    private static final String PREF_KEY_PAIRED_DEVICES_CATEGORY = "adb_paired_devices_category";
    private static final String PREF_KEY_PAIRED_DEVICES_CATEGORY = "adb_paired_devices_category";
    private static final String PREF_KEY_FOOTER_CATEGORY = "adb_wireless_footer_category";
    private static final String PREF_KEY_FOOTER_CATEGORY = "adb_wireless_footer_category";
    private static AdbIpAddressPreferenceController sAdbIpAddressPreferenceController;


    private final PairingCodeDialogListener mPairingCodeDialogListener =
            new PairingCodeDialogListener();
    private WirelessDebuggingEnabler mWifiDebuggingEnabler;
    private Preference mDeviceNamePreference;
    private Preference mDeviceNamePreference;
    private Preference mIpAddrPreference;
    private Preference mIpAddrPreference;

    private PreferenceCategory mPairingMethodsCategory;
    private PreferenceCategory mPairingMethodsCategory;
    private Preference mQrcodePairingPreference;
    private Preference mCodePairingPreference;
    private Preference mCodePairingPreference;

    private PreferenceCategory mPairedDevicesCategory;
    private PreferenceCategory mPairedDevicesCategory;

    private PreferenceCategory mFooterCategory;
    private PreferenceCategory mFooterCategory;
    private FooterPreference mOffMessagePreference;
    private FooterPreference mOffMessagePreference;

    // Map of paired devices, with the device GUID is the key
    // Map of paired devices, with the device GUID is the key
    private Map<String, AdbPairedDevicePreference> mPairedDevicePreferences;
    private Map<String, AdbPairedDevicePreference> mPairedDevicePreferences;

    private IAdbManager mAdbManager;
    private IAdbManager mAdbManager;
    private int mConnectionPort;
    private int mConnectionPort;

    class PairingCodeDialogListener implements AdbWirelessDialog.AdbWirelessDialogListener {
        @Override
        public void onDismiss() {
            Log.i(TAG, "onDismiss");
            mPairingCodeDialog = null;
            try {
                mAdbManager.disablePairing();
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to cancel pairing");
            }
        }
    }
    final PairingCodeDialogListener mPairingCodeDialogListener = new PairingCodeDialogListener();
    AdbWirelessDialog mPairingCodeDialog;

    private IntentFilter mIntentFilter;
    private IntentFilter mIntentFilter;
    private AdbWirelessDialog mPairingCodeDialog;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
@@ -171,6 +149,25 @@ public class WirelessDebuggingFragment extends DashboardFragment
        }
        }
    };
    };


    class PairingCodeDialogListener implements AdbWirelessDialog.AdbWirelessDialogListener {
        @Override
        public void onDismiss() {
            Log.i(TAG, "onDismiss");
            mPairingCodeDialog = null;
            try {
                mAdbManager.disablePairing();
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to cancel pairing");
            }
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        use(AdbQrCodePreferenceController.class).setParentFragment(this);
    }

    @Override
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        super.onActivityCreated(savedInstanceState);
@@ -203,12 +200,6 @@ public class WirelessDebuggingFragment extends DashboardFragment
            showDialog(AdbWirelessDialogUiBase.MODE_PAIRING);
            showDialog(AdbWirelessDialogUiBase.MODE_PAIRING);
            return true;
            return true;
        });
        });
        mQrcodePairingPreference =
                (Preference) findPreference(PREF_KEY_ADB_QRCODE_PAIRING);
        mQrcodePairingPreference.setOnPreferenceClickListener(preference -> {
            launchQrcodeScannerFragment();
            return true;
        });


        mPairedDevicesCategory =
        mPairedDevicesCategory =
                (PreferenceCategory) findPreference(PREF_KEY_PAIRED_DEVICES_CATEGORY);
                (PreferenceCategory) findPreference(PREF_KEY_PAIRED_DEVICES_CATEGORY);
@@ -462,6 +453,7 @@ public class WirelessDebuggingFragment extends DashboardFragment
                showDialog(AdbWirelessDialogUiBase.MODE_PAIRING_FAILED);
                showDialog(AdbWirelessDialogUiBase.MODE_PAIRING_FAILED);
                break;
                break;
            default:
            default:
                Log.d(TAG, "Successfully paired device");
                break;
                break;
        }
        }
    }
    }
@@ -476,16 +468,8 @@ public class WirelessDebuggingFragment extends DashboardFragment
        return deviceName;
        return deviceName;
    }
    }


    private void launchQrcodeScannerFragment() {
        new SubSettingLauncher(getContext())
                .setDestination(AdbQrcodeScannerFragment.class.getName())
                .setSourceMetricsCategory(getMetricsCategory())
                .setResultListener(this, PAIRING_DEVICE_REQUEST)
                .launch();
    }

    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
            new BaseSearchIndexProvider(R.xml.development_tile_settings) {
            new BaseSearchIndexProvider(R.xml.adb_wireless_settings) {


                @Override
                @Override
                protected boolean isPageSearchEnabled(Context context) {
                protected boolean isPageSearchEnabled(Context context) {
+118 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 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.settings.development;

import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.Intent;
import android.debug.IAdbManager;
import android.os.RemoteException;

import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.testutils.shadow.ShadowUtils;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowUtils.class)
public class AdbQrCodePreferenceControllerTest {
    @Mock
    private PreferenceScreen mScreen;
    @Mock
    private Preference mPreference;
    @Mock
    private IAdbManager mAdbManager;
    @Mock
    private WirelessDebuggingFragment mFragment;

    private AdbQrCodePreferenceController mController;
    private Context mContext;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;
        mController = spy(new AdbQrCodePreferenceController(mContext, "test_key"));
        mController.setParentFragment(mFragment);
        ReflectionHelpers.setField(mController, "mAdbManager", mAdbManager);
        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
        when(mPreference.getContext()).thenReturn(mContext);
    }

    @Test
    public void getAvailabilityStatus_isAdbWifiQrSupported_yes_shouldBeTrue()
            throws RemoteException {
        when(mAdbManager.isAdbWifiQrSupported()).thenReturn(true);

        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
    }

    @Test
    public void getAvailabilityStatus_isAdbWifiQrSupported_no_shouldBeFalse()
            throws RemoteException {
        when(mAdbManager.isAdbWifiQrSupported()).thenReturn(false);

        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
    }

    @Test
    public void displayPreference_isAdbWifiQrSupported_yes_prefIsVisible() throws RemoteException {
        when(mAdbManager.isAdbWifiQrSupported()).thenReturn(true);

        mController.displayPreference(mScreen);
        verify(mPreference).setVisible(true);
    }

    @Test
    public void displayPreference_isAdbWifiQrSupported_no_prefIsNotVisible()
            throws RemoteException {
        when(mAdbManager.isAdbWifiQrSupported()).thenReturn(false);

        mController.displayPreference(mScreen);
        verify(mPreference).setVisible(false);
    }

    @Test
    public void handlePreferenceTreeClick_launchActivity() {
        final String preferenceKey = mController.getPreferenceKey();
        when(mPreference.getKey()).thenReturn(preferenceKey);
        mController.handlePreferenceTreeClick(mPreference);

        verify(mFragment).startActivityForResult(any(Intent.class),
                eq(WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST));
    }
}