Merge "le advertisement address type settings"
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 41ce6f6..b4a82ff 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2264,6 +2264,25 @@
 
 package android.bluetooth.le {
 
+  public final class AdvertiseSettings implements android.os.Parcelable {
+    method public int getOwnAddressType();
+  }
+
+  public static final class AdvertiseSettings.Builder {
+    method @NonNull public android.bluetooth.le.AdvertiseSettings.Builder setOwnAddressType(int);
+  }
+
+  public final class AdvertisingSetParameters implements android.os.Parcelable {
+    method public int getOwnAddressType();
+    field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff
+    field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
+    field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
+  }
+
+  public static final class AdvertisingSetParameters.Builder {
+    method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int);
+  }
+
   public final class BluetoothLeScanner {
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java
index 7129d76..c52a6ee 100644
--- a/core/java/android/bluetooth/le/AdvertiseSettings.java
+++ b/core/java/android/bluetooth/le/AdvertiseSettings.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth.le;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.bluetooth.le.AdvertisingSetParameters.AddressTypeStatus;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -70,17 +73,21 @@
      */
     private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
 
+
     private final int mAdvertiseMode;
     private final int mAdvertiseTxPowerLevel;
     private final int mAdvertiseTimeoutMillis;
     private final boolean mAdvertiseConnectable;
+    private final int mOwnAddressType;
 
     private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel,
-            boolean advertiseConnectable, int advertiseTimeout) {
+            boolean advertiseConnectable, int advertiseTimeout,
+            @AddressTypeStatus int ownAddressType) {
         mAdvertiseMode = advertiseMode;
         mAdvertiseTxPowerLevel = advertiseTxPowerLevel;
         mAdvertiseConnectable = advertiseConnectable;
         mAdvertiseTimeoutMillis = advertiseTimeout;
+        mOwnAddressType = ownAddressType;
     }
 
     private AdvertiseSettings(Parcel in) {
@@ -88,6 +95,7 @@
         mAdvertiseTxPowerLevel = in.readInt();
         mAdvertiseConnectable = in.readInt() != 0;
         mAdvertiseTimeoutMillis = in.readInt();
+        mOwnAddressType = in.readInt();
     }
 
     /**
@@ -118,12 +126,23 @@
         return mAdvertiseTimeoutMillis;
     }
 
+    /**
+     * @return the own address type for advertising
+     *
+     * @hide
+     */
+    @SystemApi
+    public @AddressTypeStatus int getOwnAddressType() {
+        return mOwnAddressType;
+    }
+
     @Override
     public String toString() {
         return "Settings [mAdvertiseMode=" + mAdvertiseMode
                 + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel
                 + ", mAdvertiseConnectable=" + mAdvertiseConnectable
-                + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]";
+                + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis
+                + ", mOwnAddressType=" + mOwnAddressType + "]";
     }
 
     @Override
@@ -137,6 +156,7 @@
         dest.writeInt(mAdvertiseTxPowerLevel);
         dest.writeInt(mAdvertiseConnectable ? 1 : 0);
         dest.writeInt(mAdvertiseTimeoutMillis);
+        dest.writeInt(mOwnAddressType);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseSettings> CREATOR =
@@ -160,6 +180,7 @@
         private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM;
         private int mTimeoutMillis = 0;
         private boolean mConnectable = true;
+        private int mOwnAddressType = AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT;
 
         /**
          * Set advertise mode to control the advertising power and latency.
@@ -226,10 +247,31 @@
         }
 
         /**
+         * Set own address type for advertising to control public or privacy mode. If used to set
+         * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
+         * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
+         * time of starting advertising.
+         *
+         * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
+         *
+         * @hide
+         */
+        @SystemApi
+        public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
+            if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
+                    ||  ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
+                throw new IllegalArgumentException("unknown address type " + ownAddressType);
+            }
+            mOwnAddressType = ownAddressType;
+            return this;
+        }
+
+        /**
          * Build the {@link AdvertiseSettings} object.
          */
         public AdvertiseSettings build() {
-            return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis);
+            return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis,
+                mOwnAddressType);
         }
     }
 }
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index e39b198..5c8fae6 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -16,11 +16,17 @@
 
 package android.bluetooth.le;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * The {@link AdvertisingSetParameters} provide a way to adjust advertising
  * preferences for each
@@ -97,6 +103,39 @@
      */
     private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
 
+    /** @hide */
+    @IntDef(prefix = "ADDRESS_TYPE_", value = {
+        ADDRESS_TYPE_DEFAULT,
+        ADDRESS_TYPE_PUBLIC,
+        ADDRESS_TYPE_RANDOM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AddressTypeStatus {}
+
+    /**
+     * Advertise own address type that corresponds privacy settings of the device.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int ADDRESS_TYPE_DEFAULT = -1;
+
+    /**
+     * Advertise own public address type.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int ADDRESS_TYPE_PUBLIC = 0;
+
+    /**
+     * Generate and adverise own resolvable private address.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int ADDRESS_TYPE_RANDOM = 1;
+
     private final boolean mIsLegacy;
     private final boolean mIsAnonymous;
     private final boolean mIncludeTxPower;
@@ -106,11 +145,12 @@
     private final boolean mScannable;
     private final int mInterval;
     private final int mTxPowerLevel;
+    private final int mOwnAddressType;
 
     private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy,
             boolean isAnonymous, boolean includeTxPower,
             int primaryPhy, int secondaryPhy,
-            int interval, int txPowerLevel) {
+            int interval, int txPowerLevel, @AddressTypeStatus int ownAddressType) {
         mConnectable = connectable;
         mScannable = scannable;
         mIsLegacy = isLegacy;
@@ -120,6 +160,7 @@
         mSecondaryPhy = secondaryPhy;
         mInterval = interval;
         mTxPowerLevel = txPowerLevel;
+        mOwnAddressType = ownAddressType;
     }
 
     private AdvertisingSetParameters(Parcel in) {
@@ -132,6 +173,7 @@
         mSecondaryPhy = in.readInt();
         mInterval = in.readInt();
         mTxPowerLevel = in.readInt();
+        mOwnAddressType = in.readInt();
     }
 
     /**
@@ -197,6 +239,16 @@
         return mTxPowerLevel;
     }
 
+    /**
+     * @return the own address type for advertising
+     *
+     * @hide
+     */
+    @SystemApi
+    public @AddressTypeStatus int getOwnAddressType() {
+        return mOwnAddressType;
+    }
+
     @Override
     public String toString() {
         return "AdvertisingSetParameters [connectable=" + mConnectable
@@ -206,7 +258,8 @@
                 + ", primaryPhy=" + mPrimaryPhy
                 + ", secondaryPhy=" + mSecondaryPhy
                 + ", interval=" + mInterval
-                + ", txPowerLevel=" + mTxPowerLevel + "]";
+                + ", txPowerLevel=" + mTxPowerLevel
+                + ", ownAddressType=" + mOwnAddressType + "]";
     }
 
     @Override
@@ -225,6 +278,7 @@
         dest.writeInt(mSecondaryPhy);
         dest.writeInt(mInterval);
         dest.writeInt(mTxPowerLevel);
+        dest.writeInt(mOwnAddressType);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<AdvertisingSetParameters> CREATOR =
@@ -253,6 +307,7 @@
         private int mSecondaryPhy = BluetoothDevice.PHY_LE_1M;
         private int mInterval = INTERVAL_LOW;
         private int mTxPowerLevel = TX_POWER_MEDIUM;
+        private int mOwnAddressType = ADDRESS_TYPE_DEFAULT;
 
         /**
          * Set whether the advertisement type should be connectable or
@@ -399,6 +454,26 @@
         }
 
         /**
+         * Set own address type for advertising to control public or privacy mode. If used to set
+         * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
+         * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
+         * time of starting advertising.
+         *
+         * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
+         *
+         * @hide
+         */
+        @SystemApi
+        public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
+            if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
+                    ||  ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
+                throw new IllegalArgumentException("unknown address type " + ownAddressType);
+            }
+            mOwnAddressType = ownAddressType;
+            return this;
+        }
+
+        /**
          * Build the {@link AdvertisingSetParameters} object.
          *
          * @throws IllegalStateException if invalid combination of parameters is used.
@@ -431,7 +506,8 @@
             }
 
             return new AdvertisingSetParameters(mConnectable, mScannable, mIsLegacy, mIsAnonymous,
-                    mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel);
+                    mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel,
+                    mOwnAddressType);
         }
     }
 }
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index b9f8a57..879dcee 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -138,6 +138,7 @@
             parameters.setLegacyMode(true);
             parameters.setConnectable(isConnectable);
             parameters.setScannable(true); // legacy advertisements we support are always scannable
+            parameters.setOwnAddressType(settings.getOwnAddressType());
             if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
                 parameters.setInterval(1600); // 1s
             } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {