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

Commit 74e7cae6 authored by Hai Shalom's avatar Hai Shalom Committed by Android (Google) Code Review
Browse files

Merge "[DPP R2] Added support for DPP R2 events"

parents 7c52e663 e722cbd4
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -5392,11 +5392,15 @@ package android.net.wifi {
    ctor public EasyConnectStatusCallback();
    method public abstract void onConfiguratorSuccess(int);
    method public abstract void onEnrolleeSuccess(int);
    method public abstract void onFailure(int);
    method public void onFailure(int);
    method public void onFailure(int, @Nullable String, @NonNull android.util.SparseArray<int[]>, @NonNull int[]);
    method public abstract void onProgress(int);
    field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
    field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
    field public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10; // 0xfffffff6
    field public static final int EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc
    field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11; // 0xfffffff5
    field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12; // 0xfffffff4
    field public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; // 0xfffffff9
    field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7
    field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff
@@ -5404,7 +5408,10 @@ package android.net.wifi {
    field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
    field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
    field public static final int EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0; // 0x0
    field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3; // 0x3
    field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2; // 0x2
    field public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1; // 0x1
    field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1; // 0x1
    field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0; // 0x0
  }
+83 −19
Original line number Diff line number Diff line
@@ -17,32 +17,46 @@
package android.net.wifi;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Handler;
import android.util.SparseArray;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;

/**
 * Easy Connect (DPP) Status Callback. Use this callback to get status updates (success, failure,
 * progress) from the Easy Connect operation started with
 * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String,
 * int, int, Handler, EasyConnectStatusCallback)} or
 * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
 * Handler, EasyConnectStatusCallback)}
 * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int, int, Executor,
 * EasyConnectStatusCallback)} or {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
 * Executor, EasyConnectStatusCallback)}
 *
 * @hide
 */
@SystemApi
public abstract class EasyConnectStatusCallback {
    /**
     * Easy Connect Success event: Configuration sent (Configurator mode).
     * Easy Connect R1 Success event: Configuration sent (Configurator mode). This is the last
     * and final Easy Connect event when either the local device or remote device implement R1.
     * If both devices implement R2, this event will never be received, and the
     * {@link EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED} will be received.
     */
    public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0;

    /**
     * East Connect R2 Success event: Configuration applied by Enrollee (Configurator mode).
     * This is the last and final Easy Connect event when both the local device and remote device
     * implement R2. If either the local device or remote device implement R1, this event will never
     * be received, and the {@link EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT} will be received.
     */
    public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1;

    /** @hide */
    @IntDef(prefix = {"EASY_CONNECT_EVENT_SUCCESS_"}, value = {
            EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT,
            EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EasyConnectSuccessStatusCode {
@@ -58,10 +72,22 @@ public abstract class EasyConnectStatusCallback {
     */
    public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1;

    /**
     * Easy Connect R2 Progress event: Configuration sent to Enrollee, waiting for response
     */
    public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2;

    /**
     * Easy Connect R2 Progress event: Configuration accepted by Enrollee, waiting for response
     */
    public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3;

    /** @hide */
    @IntDef(prefix = {"EASY_CONNECT_EVENT_PROGRESS_"}, value = {
            EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS,
            EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING,
            EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE,
            EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EasyConnectProgressStatusCode {
@@ -114,6 +140,20 @@ public abstract class EasyConnectStatusCallback {
     */
    public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9;

    /**
     * Easy Connect R2 Failure event: Enrollee cannot find the network.
     */
    public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10;

    /**
     * Easy Connect R2 Failure event: Enrollee failed to authenticate with the network.
     */
    public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11;

    /**
     * Easy Connect R2 Failure event: Enrollee rejected the configuration.
     */
    public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12;

    /** @hide */
    @IntDef(prefix = {"EASY_CONNECT_EVENT_FAILURE_"}, value = {
@@ -126,6 +166,9 @@ public abstract class EasyConnectStatusCallback {
            EASY_CONNECT_EVENT_FAILURE_GENERIC,
            EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED,
            EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK,
            EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
            EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION,
            EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EasyConnectFailureStatusCode {
@@ -138,8 +181,7 @@ public abstract class EasyConnectStatusCallback {
     * current Easy Connect
     * session, and no further callbacks will be called. This callback is the successful outcome
     * of a Easy Connect flow starting with
     * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
     * Handler,
     * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String, Executor,
     * EasyConnectStatusCallback)} .
     *
     * @param newNetworkId New Wi-Fi configuration with a network ID received from the configurator
@@ -148,13 +190,11 @@ public abstract class EasyConnectStatusCallback {

    /**
     * Called when a Easy Connect success event takes place, except for when configuration is
     * received from
     * an external Configurator. The callback onSuccessConfigReceived will be used in this case.
     * This callback marks the successful end of the current Easy Connect session, and no further
     * callbacks will be called. This callback is the successful outcome of a Easy Connect flow
     * starting with
     * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int, int, Handler,
     * EasyConnectStatusCallback)}.
     * received from an external Configurator. The callback onSuccessConfigReceived will be used in
     * this case. This callback marks the successful end of the current Easy Connect session, and no
     * further callbacks will be called. This callback is the successful outcome of a Easy Connect
     * flow starting with {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int,
     * int, Executor,EasyConnectStatusCallback)}.
     *
     * @param code Easy Connect success status code.
     */
@@ -162,12 +202,36 @@ public abstract class EasyConnectStatusCallback {

    /**
     * Called when a Easy Connect Failure event takes place. This callback marks the unsuccessful
     * end of the
     * current Easy Connect session, and no further callbacks will be called.
     * end of the current Easy Connect session, and no further callbacks will be called.
     *
     * @param code Easy Connect failure status code.
     */
    public abstract void onFailure(@EasyConnectFailureStatusCode int code);
    public void onFailure(@EasyConnectFailureStatusCode int code) {}

    /**
     * Called when a Easy Connect Failure event takes place. This callback marks the unsuccessful
     * end of the current Easy Connect session, and no further callbacks will be called.
     *
     * Note: Easy Connect (DPP) R2, provides additional details for the Configurator when the
     * remote Enrollee is unable to connect to a network. The ssid, channelList and bandList
     * inputs are initialized only for the EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK failure
     * code, and the ssid and bandList are initialized for the
     * EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION failure code.
     *
     * @param code Easy Connect failure status code.
     * @param ssid SSID of the network the Enrollee tried to connect to.
     * @param channelListArray List of Global Operating classes and channel sets the Enrollee used
     *                         to scan to find the network, see the "DPP Connection Status Object"
     *                         section in the specification for the format, and Table E-4 in
     *                         IEEE Std 802.11-2016 - Global operating classes for more details.
     * @param operatingClassArray Array of bands the Enrollee supports as expressed as the Global
     *                            Operating Class, see Table E-4 in IEEE Std 802.11-2016 - Global
     *                            operating classes.
     */
    public void onFailure(@EasyConnectFailureStatusCode int code, @Nullable String ssid,
            @NonNull SparseArray<int[]> channelListArray, @NonNull int[] operatingClassArray) {
        onFailure(code);
    }

    /**
     * Called when Easy Connect events that indicate progress take place. Can be used by UI elements
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ oneway interface IDppCallback
    /**
     * Called when DPP Failure events take place.
     */
    void onFailure(int status);
    void onFailure(int status, String ssid, String channelList, in int[] bandArray);

    /**
     * Called when DPP events that indicate progress take place. Can be used by UI elements
+84 −2
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.text.TextUtils;
import android.util.CloseGuard;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -70,6 +71,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.Executor;

/**
@@ -5177,6 +5179,7 @@ public class WifiManager {
        @Override
        public void onSuccessConfigReceived(int newNetworkId) {
            Log.d(TAG, "Easy Connect onSuccessConfigReceived callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId);
            });
@@ -5185,22 +5188,28 @@ public class WifiManager {
        @Override
        public void onSuccess(int status) {
            Log.d(TAG, "Easy Connect onSuccess callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onConfiguratorSuccess(status);
            });
        }

        @Override
        public void onFailure(int status) {
        public void onFailure(int status, String ssid, String channelList,
                int[] operatingClassArray) {
            Log.d(TAG, "Easy Connect onFailure callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onFailure(status);
                SparseArray<int[]> channelListArray = parseDppChannelList(channelList);
                mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray,
                        operatingClassArray);
            });
        }

        @Override
        public void onProgress(int status) {
            Log.d(TAG, "Easy Connect onProgress callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onProgress(status);
            });
@@ -5532,4 +5541,77 @@ public class WifiManager {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Parse the list of channels the DPP enrollee reports when it fails to find an AP.
     *
     * @param channelList List of channels in the format defined in the DPP specification.
     * @return A parsed sparse array, where the operating class is the key.
     * @hide
     */
    @VisibleForTesting
    public static SparseArray<int[]> parseDppChannelList(String channelList) {
        SparseArray<int[]> channelListArray = new SparseArray<>();

        if (TextUtils.isEmpty(channelList)) {
            return channelListArray;
        }
        StringTokenizer str = new StringTokenizer(channelList, ",");
        String classStr = null;
        List<Integer> channelsInClass = new ArrayList<>();

        try {
            while (str.hasMoreElements()) {
                String cur = str.nextToken();

                /**
                 * Example for a channel list:
                 *
                 * 81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48,118/52,56,60,64,121/100,104,108,112,
                 * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165
                 *
                 * Detect operating class by the delimiter of '/' and use a string tokenizer with
                 * ',' as a delimiter.
                 */
                int classDelim = cur.indexOf('/');
                if (classDelim != -1) {
                    if (classStr != null) {
                        // Store the last channel array in the sparse array, where the operating
                        // class is the key (as an integer).
                        int[] channelsArray = new int[channelsInClass.size()];
                        for (int i = 0; i < channelsInClass.size(); i++) {
                            channelsArray[i] = channelsInClass.get(i);
                        }
                        channelListArray.append(Integer.parseInt(classStr), channelsArray);
                        channelsInClass = new ArrayList<>();
                    }

                    // Init a new operating class and store the first channel
                    classStr = cur.substring(0, classDelim);
                    String channelStr = cur.substring(classDelim + 1);
                    channelsInClass.add(Integer.parseInt(channelStr));
                } else {
                    if (classStr == null) {
                        // Invalid format
                        Log.e(TAG, "Cannot parse DPP channel list");
                        return new SparseArray<>();
                    }
                    channelsInClass.add(Integer.parseInt(cur));
                }
            }

            // Store the last array
            if (classStr != null) {
                int[] channelsArray = new int[channelsInClass.size()];
                for (int i = 0; i < channelsInClass.size(); i++) {
                    channelsArray[i] = channelsInClass.get(i);
                }
                channelListArray.append(Integer.parseInt(classStr), channelsArray);
            }
            return channelListArray;
        } catch (NumberFormatException e) {
            Log.e(TAG, "Cannot parse DPP channel list");
            return new SparseArray<>();
        }
    }
}
+84 −0
Original line number 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.
 */

package android.net.wifi;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import android.util.SparseArray;

import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;

/**
 * Unit tests for {@link android.net.wifi.EasyConnectStatusCallbackTest}.
 */
@SmallTest
public class EasyConnectStatusCallbackTest {
    private EasyConnectStatusCallback mEasyConnectStatusCallback = new EasyConnectStatusCallback() {
        @Override
        public void onEnrolleeSuccess(int newNetworkId) {

        }

        @Override
        public void onConfiguratorSuccess(int code) {

        }

        @Override
        public void onProgress(int code) {

        }

        @Override
        public void onFailure(int code) {
            mOnFailureR1EventReceived = true;
            mLastCode = code;
        }
    };
    private boolean mOnFailureR1EventReceived;
    private int mLastCode;

    @Before
    public void setUp() {
        mOnFailureR1EventReceived = false;
        mLastCode = 0;
    }

    /**
     * Test that the legacy R1 onFailure is called by default if the R2 onFailure is not overridden
     * by the app.
     */
    @Test
    public void testR1OnFailureCalled() {

        SparseArray<int[]> channelList = new SparseArray<>();
        int[] channelArray = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

        channelList.append(81, channelArray);
        mEasyConnectStatusCallback.onFailure(
                EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
                "SomeSSID", channelList, new int[] {81});

        assertTrue(mOnFailureR1EventReceived);
        assertEquals(mLastCode,
                EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK);
    }
}
Loading