wifi: Add bssid mac randomization control

Bug: 151189102
Test: atest frameworks/base/wifi/tests
Change-Id: I61db2a5d540fafd4cb8b2a05ddffc79538223417
diff --git a/api/system-current.txt b/api/system-current.txt
index d95eade..ec4422b 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7059,6 +7059,7 @@
     method public int getBand();
     method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList();
     method public int getChannel();
+    method public int getMacRandomizationSetting();
     method public int getMaxNumberOfClients();
     method public long getShutdownTimeoutMillis();
     method public boolean isAutoShutdownEnabled();
@@ -7068,6 +7069,8 @@
     field public static final int BAND_5GHZ = 2; // 0x2
     field public static final int BAND_6GHZ = 4; // 0x4
     field public static final int BAND_ANY = 7; // 0x7
+    field public static final int RANDOMIZATION_NONE = 0; // 0x0
+    field public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
   }
 
   public static final class SoftApConfiguration.Builder {
@@ -7082,6 +7085,7 @@
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setClientControlByUserEnabled(boolean);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMacRandomizationSetting(int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setPassphrase(@Nullable String, int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setShutdownTimeoutMillis(@IntRange(from=0) long);
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index e96365b..cbf5d77 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -253,6 +253,7 @@
     method public int getBand();
     method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList();
     method public int getChannel();
+    method public int getMacRandomizationSetting();
     method public int getMaxNumberOfClients();
     method public long getShutdownTimeoutMillis();
     method public boolean isAutoShutdownEnabled();
@@ -262,6 +263,8 @@
     field public static final int BAND_5GHZ = 2; // 0x2
     field public static final int BAND_6GHZ = 4; // 0x4
     field public static final int BAND_ANY = 7; // 0x7
+    field public static final int RANDOMIZATION_NONE = 0; // 0x0
+    field public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
   }
 
   public static final class SoftApConfiguration.Builder {
@@ -276,6 +279,7 @@
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setClientControlByUserEnabled(boolean);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMacRandomizationSetting(int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setPassphrase(@Nullable String, int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setShutdownTimeoutMillis(@IntRange(from=0) long);
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 2bcd4f4..68c35d3 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.MacAddress;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -217,6 +218,34 @@
      */
     private final long mShutdownTimeoutMillis;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"RANDOMIZATION_"}, value = {
+            RANDOMIZATION_NONE,
+            RANDOMIZATION_PERSISTENT})
+    public @interface MacRandomizationSetting {}
+
+    /**
+     * Use factory MAC as BSSID for the AP
+     * @hide
+     */
+    @SystemApi
+    public static final int RANDOMIZATION_NONE = 0;
+    /**
+     * Generate a randomized MAC as BSSID for the AP
+     * @hide
+     */
+    @SystemApi
+    public static final int RANDOMIZATION_PERSISTENT = 1;
+
+    /**
+     * Level of MAC randomization for the AP BSSID.
+     * @hide
+     */
+    @MacRandomizationSetting
+    private int mMacRandomizationSetting;
+
+
     /**
      * THe definition of security type OPEN.
      */
@@ -252,7 +281,8 @@
             @Nullable String passphrase, boolean hiddenSsid, @BandType int band, int channel,
             @SecurityType int securityType, int maxNumberOfClients, boolean shutdownTimeoutEnabled,
             long shutdownTimeoutMillis, boolean clientControlByUser,
-            @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList) {
+            @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList,
+            int macRandomizationSetting) {
         mSsid = ssid;
         mBssid = bssid;
         mPassphrase = passphrase;
@@ -266,6 +296,7 @@
         mClientControlByUser = clientControlByUser;
         mBlockedClientList = new ArrayList<>(blockedList);
         mAllowedClientList = new ArrayList<>(allowedList);
+        mMacRandomizationSetting = macRandomizationSetting;
     }
 
     @Override
@@ -289,7 +320,8 @@
                 && mShutdownTimeoutMillis == other.mShutdownTimeoutMillis
                 && mClientControlByUser == other.mClientControlByUser
                 && Objects.equals(mBlockedClientList, other.mBlockedClientList)
-                && Objects.equals(mAllowedClientList, other.mAllowedClientList);
+                && Objects.equals(mAllowedClientList, other.mAllowedClientList)
+                && mMacRandomizationSetting == other.mMacRandomizationSetting;
     }
 
     @Override
@@ -297,7 +329,7 @@
         return Objects.hash(mSsid, mBssid, mPassphrase, mHiddenSsid,
                 mBand, mChannel, mSecurityType, mMaxNumberOfClients, mAutoShutdownEnabled,
                 mShutdownTimeoutMillis, mClientControlByUser, mBlockedClientList,
-                mAllowedClientList);
+                mAllowedClientList, mMacRandomizationSetting);
     }
 
     @Override
@@ -317,6 +349,7 @@
         sbuf.append(" \n ClientControlByUser=").append(mClientControlByUser);
         sbuf.append(" \n BlockedClientList=").append(mBlockedClientList);
         sbuf.append(" \n AllowedClientList=").append(mAllowedClientList);
+        sbuf.append(" \n MacRandomizationSetting=").append(mMacRandomizationSetting);
         return sbuf.toString();
     }
 
@@ -335,6 +368,7 @@
         dest.writeBoolean(mClientControlByUser);
         dest.writeTypedList(mBlockedClientList);
         dest.writeTypedList(mAllowedClientList);
+        dest.writeInt(mMacRandomizationSetting);
     }
 
     @Override
@@ -352,7 +386,7 @@
                     in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(),
                     in.readInt(), in.readBoolean(), in.readLong(), in.readBoolean(),
                     in.createTypedArrayList(MacAddress.CREATOR),
-                    in.createTypedArrayList(MacAddress.CREATOR));
+                    in.createTypedArrayList(MacAddress.CREATOR), in.readInt());
         }
 
         @Override
@@ -509,6 +543,21 @@
     }
 
     /**
+     * Returns the level of MAC randomization for the AP BSSID.
+     * {@link Builder#setMacRandomizationSetting(int)}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @MacRandomizationSetting
+    public int getMacRandomizationSetting() {
+        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
+            throw new UnsupportedOperationException();
+        }
+        return mMacRandomizationSetting;
+    }
+
+    /**
      * Returns a {@link WifiConfiguration} representation of this {@link SoftApConfiguration}.
      * Note that SoftApConfiguration may contain configuration which is cannot be represented
      * by the legacy WifiConfiguration, in such cases a null will be returned.
@@ -584,6 +633,7 @@
         private boolean mClientControlByUser;
         private List<MacAddress> mBlockedClientList;
         private List<MacAddress> mAllowedClientList;
+        private int mMacRandomizationSetting;
 
         /**
          * Constructs a Builder with default values (see {@link Builder}).
@@ -602,6 +652,7 @@
             mClientControlByUser = false;
             mBlockedClientList = new ArrayList<>();
             mAllowedClientList = new ArrayList<>();
+            mMacRandomizationSetting = RANDOMIZATION_PERSISTENT;
         }
 
         /**
@@ -623,6 +674,7 @@
             mClientControlByUser = other.mClientControlByUser;
             mBlockedClientList = new ArrayList<>(other.mBlockedClientList);
             mAllowedClientList = new ArrayList<>(other.mAllowedClientList);
+            mMacRandomizationSetting = other.mMacRandomizationSetting;
         }
 
         /**
@@ -640,7 +692,7 @@
             return new SoftApConfiguration(mSsid, mBssid, mPassphrase,
                     mHiddenSsid, mBand, mChannel, mSecurityType, mMaxNumberOfClients,
                     mAutoShutdownEnabled, mShutdownTimeoutMillis, mClientControlByUser,
-                    mBlockedClientList, mAllowedClientList);
+                    mBlockedClientList, mAllowedClientList, mMacRandomizationSetting);
         }
 
         /**
@@ -969,5 +1021,30 @@
             mBlockedClientList = new ArrayList<>(blockedClientList);
             return this;
         }
+
+        /**
+         * Specifies the level of MAC randomization for the AP BSSID.
+         * The Soft AP BSSID will be randomized only if the BSSID isn't set
+         * {@link #setBssid(MacAddress)} and this method is either uncalled
+         * or called with {@link #RANDOMIZATION_PERSISTENT}.
+         *
+         * <p>
+         * <li>If not set, defaults to {@link #RANDOMIZATION_PERSISTENT}</li>
+         *
+         * @param macRandomizationSetting One of the following setting:.
+         * {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}.
+         * @return Builder for chaining.
+         *
+         * @see #setBssid(MacAddress)
+         */
+        @NonNull
+        public Builder setMacRandomizationSetting(
+                @MacRandomizationSetting int macRandomizationSetting) {
+            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
+                throw new UnsupportedOperationException();
+            }
+            mMacRandomizationSetting = macRandomizationSetting;
+            return this;
+        }
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index 1a44270..40f5c3e 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertNull;
 
 import android.net.MacAddress;
+import android.os.Build;
 import android.os.Parcel;
 
 import androidx.test.filters.SmallTest;
@@ -78,6 +79,10 @@
         assertThat(original.getChannel()).isEqualTo(0);
         assertThat(original.isHiddenSsid()).isEqualTo(false);
         assertThat(original.getMaxNumberOfClients()).isEqualTo(0);
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+            assertThat(original.getMacRandomizationSetting())
+                    .isEqualTo(SoftApConfiguration.RANDOMIZATION_PERSISTENT);
+        }
 
         SoftApConfiguration unparceled = parcelUnparcel(original);
         assertThat(unparceled).isNotSameAs(original);
@@ -120,7 +125,7 @@
         List<MacAddress> testAllowedClientList = new ArrayList<>();
         testBlockedClientList.add(MacAddress.fromString("11:22:33:44:55:66"));
         testAllowedClientList.add(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
-        SoftApConfiguration original = new SoftApConfiguration.Builder()
+        SoftApConfiguration.Builder originalBuilder = new SoftApConfiguration.Builder()
                 .setPassphrase("secretsecret", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
                 .setChannel(149, SoftApConfiguration.BAND_5GHZ)
                 .setHiddenSsid(true)
@@ -129,8 +134,11 @@
                 .setShutdownTimeoutMillis(500000)
                 .setClientControlByUserEnabled(true)
                 .setBlockedClientList(testBlockedClientList)
-                .setAllowedClientList(testAllowedClientList)
-                .build();
+                .setAllowedClientList(testAllowedClientList);
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+            originalBuilder.setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE);
+        }
+        SoftApConfiguration original = originalBuilder.build();
         assertThat(original.getPassphrase()).isEqualTo("secretsecret");
         assertThat(original.getSecurityType()).isEqualTo(
                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
@@ -143,6 +151,10 @@
         assertThat(original.isClientControlByUserEnabled()).isEqualTo(true);
         assertThat(original.getBlockedClientList()).isEqualTo(testBlockedClientList);
         assertThat(original.getAllowedClientList()).isEqualTo(testAllowedClientList);
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+            assertThat(original.getMacRandomizationSetting())
+                    .isEqualTo(SoftApConfiguration.RANDOMIZATION_NONE);
+        }
 
         SoftApConfiguration unparceled = parcelUnparcel(original);
         assertThat(unparceled).isNotSameAs(original);