Merge "Unit test for CastControllerImp"
diff --git a/api/test-current.txt b/api/test-current.txt
index 3fa202f..35c6c48 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -8,6 +8,8 @@
     field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
     field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
+    field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
+    field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
   }
 
 }
@@ -30,6 +32,8 @@
     method public long getTotalRam();
     method public int getUidImportance(int);
     method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
+    method public void forceStopPackage(java.lang.String);
+    method public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
   }
 
   public static abstract interface ActivityManager.OnUidImportanceListener {
@@ -56,6 +60,14 @@
     method public void setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) throws java.lang.SecurityException;
     method public static boolean supportsMultiWindow(android.content.Context);
     method public static boolean supportsSplitScreenMultiWindow(android.content.Context);
+    method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
+    method public void startSystemLockTaskMode(int);
+    method public void stopSystemLockTaskMode();
+    method public void moveTaskToStack(int, int, boolean);
+    method public void resizeStack(int, android.graphics.Rect, boolean);
+    method public void resizeTask(int, android.graphics.Rect);
+    method public void resizeDockedStack(android.graphics.Rect,android.graphics.Rect);
+    method public java.lang.String listAllStacks();
     field public static final int INVALID_STACK_ID = -1; // 0xffffffff
     field public static final int SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT = 1; // 0x1
     field public static final int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT = 0; // 0x0
@@ -1456,6 +1468,7 @@
   public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public void setActionButton(int);
     method public void setButtonState(int);
+    method public void setDisplayId(int);
   }
 
   public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 63ffa8b..c12d8e2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3360,7 +3360,7 @@
      * @see #forceStopPackageAsUser(String, int)
      * @hide
      */
-    @SystemApi
+    @SystemApi @TestApi
     @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
     public void forceStopPackage(String packageName) {
         forceStopPackageAsUser(packageName, mContext.getUserId());
@@ -3987,6 +3987,19 @@
     }
 
     /**
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.CHANGE_CONFIGURATION)
+    public void scheduleApplicationInfoChanged(List<String> packages, int userId) {
+        try {
+            getService().scheduleApplicationInfoChanged(packages, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * The AppTask allows you to manage your own application's tasks.
      * See {@link android.app.ActivityManager#getAppTasks()}
      */
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 2f18b89..af8aa4e 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -29,6 +29,8 @@
 import android.os.ServiceManager;
 import android.util.Singleton;
 
+import java.util.List;
+
 /**
  * This class gives information about, and interacts with activities and their containers like task,
  * stacks, and displays.
@@ -263,4 +265,140 @@
                 && Resources.getSystem().getBoolean(
                 com.android.internal.R.bool.config_supportsSplitScreenMultiWindow);
     }
+
+    /**
+     * Moves the top activity in the input stackId to the pinned stack.
+     * @param stackId Id of stack to move the top activity to pinned stack.
+     * @param bounds Bounds to use for pinned stack.
+     * @return True if the top activity of stack was successfully moved to the pinned stack.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
+        try {
+            return getService().moveTopActivityToPinnedStack(stackId, bounds);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Start to enter lock task mode for given task by system(UI).
+     * @param taskId Id of task to lock.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void startSystemLockTaskMode(int taskId) {
+        try {
+            getService().startSystemLockTaskMode(taskId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Stop lock task mode by system(UI).
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void stopSystemLockTaskMode() {
+        try {
+            getService().stopSystemLockTaskMode();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Move task to stack with given id.
+     * @param taskId Id of the task to move.
+     * @param stackId Id of the stack for task moving.
+     * @param toTop Whether the given task should shown to top of stack.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+        try {
+            getService().moveTaskToStack(taskId, stackId, toTop);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resize the input stack id to the given bounds with animate setting.
+     * @param stackId Id of the stack to resize.
+     * @param bounds Bounds to resize the stack to or {@code null} for fullscreen.
+     * @param animate Whether we should play an animation for resizing stack.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void resizeStack(int stackId, Rect bounds, boolean animate) {
+        try {
+            getService().resizeStack(stackId, bounds, false, false, animate /* animate */,
+                    -1 /* animationDuration */);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resize task to given bounds.
+     * @param taskId Id of task to resize.
+     * @param bounds Bounds to resize task.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void resizeTask(int taskId, Rect bounds) {
+        try {
+            getService().resizeTask(taskId, bounds, RESIZE_MODE_SYSTEM);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resize docked stack & its task to given stack & task bounds.
+     * @param stackBounds Bounds to resize stack.
+     * @param taskBounds Bounds to resize task.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void resizeDockedStack(Rect stackBounds, Rect taskBounds) {
+        try {
+            getService().resizeDockedStack(stackBounds, taskBounds, null, null, null);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * List all activity stacks information.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public String listAllStacks() {
+        final List<ActivityManager.StackInfo> stacks;
+        try {
+            stacks = getService().getAllStackInfos();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        final StringBuilder sb = new StringBuilder();
+        if (stacks != null) {
+            for (ActivityManager.StackInfo info : stacks) {
+                sb.append(info).append("\n");
+            }
+        }
+        return sb.toString();
+    }
 }
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 6d1383a..2d9fbf9 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -125,7 +125,7 @@
         }
     }
 
-    private static final boolean ENABLE_APK_ASSETS_CACHE = true;
+    private static final boolean ENABLE_APK_ASSETS_CACHE = false;
 
     /**
      * The ApkAssets we are caching and intend to hold strong references to.
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index cde9ec4..29c58dc 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1956,6 +1956,7 @@
     }
 
     /** @hide */
+    @TestApi
     @Override
     public void setDisplayId(int displayId) {
         nativeSetDisplayId(mNativePtr, displayId);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5b36d7c..8f176e8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -359,6 +359,7 @@
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_ICON" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
+    <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW" />
     <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
@@ -2150,11 +2151,11 @@
 
     <!-- @SystemApi @TestApi @hide Allows an application to create/manage/remove stacks -->
     <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
-        android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @TestApi @hide Allows an application to embed other activities -->
     <permission android:name="android.permission.ACTIVITY_EMBEDDING"
-                android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start any activity, regardless of permission
          protection or exported state.
@@ -2387,7 +2388,7 @@
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows an application to modify the current configuration, such
+    <!-- @SystemApi @TestApi Allows an application to modify the current configuration, such
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
         android:protectionLevel="signature|privileged|development" />
@@ -2414,7 +2415,7 @@
     <permission android:name="android.permission.WRITE_GSERVICES"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi Allows an application to call
+    <!-- @SystemApi @TestApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
     <permission android:name="android.permission.FORCE_STOP_PACKAGES"
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 5ecbe80..c511589 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1189,7 +1189,7 @@
     /**
      * @return {@code true} if {@code cachedBluetoothDevice} is a2dp device
      */
-    public boolean isA2dpDevice() {
+    public boolean isConnectedA2dpDevice() {
         A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
         return a2dpProfile != null && a2dpProfile.getConnectionStatus(mDevice) ==
                 BluetoothProfile.STATE_CONNECTED;
@@ -1198,7 +1198,7 @@
     /**
      * @return {@code true} if {@code cachedBluetoothDevice} is HFP device
      */
-    public boolean isHfpDevice() {
+    public boolean isConnectedHfpDevice() {
         HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile();
         return headsetProfile != null && headsetProfile.getConnectionStatus(mDevice) ==
                 BluetoothProfile.STATE_CONNECTED;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 034574f..5e417c3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -538,7 +538,7 @@
         when(mA2dpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
 
-        assertThat(mCachedDevice.isA2dpDevice()).isTrue();
+        assertThat(mCachedDevice.isConnectedA2dpDevice()).isTrue();
     }
 
     @Test
@@ -547,7 +547,7 @@
         when(mA2dpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
 
-        assertThat(mCachedDevice.isA2dpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedA2dpDevice()).isFalse();
     }
 
     @Test
@@ -556,7 +556,7 @@
         when(mHfpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
 
-        assertThat(mCachedDevice.isHfpDevice()).isTrue();
+        assertThat(mCachedDevice.isConnectedHfpDevice()).isTrue();
     }
 
     @Test
@@ -565,7 +565,7 @@
         when(mHfpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
 
-        assertThat(mCachedDevice.isHfpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedHfpDevice()).isFalse();
     }
 
     @Test
@@ -590,14 +590,14 @@
     public void isConnectedHfpDevice_profileIsNull_returnFalse() {
         when(mProfileManager.getHeadsetProfile()).thenReturn(null);
 
-        assertThat(mCachedDevice.isHfpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedHfpDevice()).isFalse();
     }
 
     @Test
     public void isConnectedA2dpDevice_profileIsNull_returnFalse() {
         when(mProfileManager.getA2dpProfile()).thenReturn(null);
 
-        assertThat(mCachedDevice.isA2dpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedA2dpDevice()).isFalse();
     }
 
     @Test
diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp
index 739555c..d4b4571 100644
--- a/tools/aapt2/format/Container.cpp
+++ b/tools/aapt2/format/Container.cpp
@@ -270,7 +270,8 @@
   }
 
   if (magic != kContainerFormatMagic) {
-    error_ = "magic value doesn't match AAPT";
+    error_ =
+        StringPrintf("magic value is 0x%08x but AAPT expects 0x%08x", magic, kContainerFormatMagic);
     return;
   }
 
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 6fd4c8d..8641a7c 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -133,11 +133,10 @@
   }
 
   void Visit(Array* array) override {
-    for (auto& item : array->elements) {
-      ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>();
-      FlattenValue(item.get(), out_entry);
-      out_entry->value.size = util::HostToDevice16(sizeof(out_entry->value));
-      entry_count_++;
+    const size_t count = array->elements.size();
+    for (size_t i = 0; i < count; i++) {
+      Reference key(android::ResTable_map::ATTR_MIN + i);
+      FlattenEntry(&key, array->elements[i].get());
     }
   }
 
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index bab7010..af19b98 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -17,7 +17,9 @@
 #include "format/binary/TableFlattener.h"
 
 #include "android-base/stringprintf.h"
+#include "androidfw/TypeWrappers.h"
 
+#include "ResChunkPullParser.h"
 #include "ResourceUtils.h"
 #include "SdkConstants.h"
 #include "format/binary/BinaryResourceParser.h"
@@ -236,6 +238,62 @@
   EXPECT_EQ(attr.max_int, actual_attr->max_int);
 }
 
+TEST_F(TableFlattenerTest, FlattenArray) {
+  auto array = util::make_unique<Array>();
+  array->elements.push_back(util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC),
+                                                               1u));
+  array->elements.push_back(util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC),
+                                                               2u));
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("android", 0x01)
+          .AddValue("android:array/foo", ResourceId(0x01010000), std::move(array))
+          .Build();
+
+  std::string result;
+  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &result));
+
+  // Parse the flattened resource table
+  ResChunkPullParser parser(result.data(), result.size());
+  ASSERT_TRUE(parser.IsGoodEvent(parser.Next()));
+  ASSERT_EQ(util::DeviceToHost16(parser.chunk()->type), RES_TABLE_TYPE);
+
+  // Retrieve the package of the entry
+  ResChunkPullParser table_parser(GetChunkData(parser.chunk()), GetChunkDataLen(parser.chunk()));
+  const ResChunk_header* package_chunk = nullptr;
+  while (table_parser.IsGoodEvent(table_parser.Next())) {
+    if (util::DeviceToHost16(table_parser.chunk()->type) == RES_TABLE_PACKAGE_TYPE) {
+      package_chunk = table_parser.chunk();
+      break;
+    }
+  }
+
+  // Retrieve the type that proceeds the array entry
+  ASSERT_NE(package_chunk, nullptr);
+  ResChunkPullParser package_parser(GetChunkData(table_parser.chunk()),
+                                    GetChunkDataLen(table_parser.chunk()));
+  const ResChunk_header* type_chunk = nullptr;
+  while (package_parser.IsGoodEvent(package_parser.Next())) {
+    if (util::DeviceToHost16(package_parser.chunk()->type) == RES_TABLE_TYPE_TYPE) {
+      type_chunk = package_parser.chunk();
+      break;
+    }
+  }
+
+  // Retrieve the array entry
+  ASSERT_NE(type_chunk, nullptr);
+  TypeVariant typeVariant((const ResTable_type*) type_chunk);
+  auto entry = (const ResTable_map_entry*)*typeVariant.beginEntries();
+  ASSERT_EQ(util::DeviceToHost16(entry->count), 2u);
+
+  // Check that the value and name of the array entries are correct
+  auto values = (const ResTable_map*)(((const uint8_t *)entry) + entry->size);
+  ASSERT_EQ(values->value.data, 1u);
+  ASSERT_EQ(values->name.ident, android::ResTable_map::ATTR_MIN);
+  ASSERT_EQ((values+1)->value.data, 2u);
+  ASSERT_EQ((values+1)->name.ident, android::ResTable_map::ATTR_MIN + 1);
+}
+
 static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
     IAaptContext* context, const ConfigDescription& sparse_config, float load) {
   std::unique_ptr<ResourceTable> table =
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 5631919..12f50c8 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -126,7 +126,7 @@
 
     void acquireMulticastLock(IBinder binder, String tag);
 
-    void releaseMulticastLock();
+    void releaseMulticastLock(String tag);
 
     void updateInterfaceIpState(String ifaceName, int mode);
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index f7de370..b56a758 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -318,6 +318,31 @@
             "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
 
     /**
+     * Activity Action: lunch OSU (Online Sign Up) view.
+     * Included extras:
+     *
+     * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP.
+     * {@link #EXTRA_URL}: String representation of a server URL used for OSU process.
+     *
+     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * components will be launched.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW =
+            "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW";
+
+    /**
+     * The lookup key for a {@link android.net.Network} associated with OSU server.
+     *
+     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK";
+
+    /**
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
      * enabling, disabling, or unknown. One extra provides this state as an int.
      * Another extra provides the previous state, if available.
@@ -3409,7 +3434,7 @@
                         mService.acquireMulticastLock(mBinder, mTag);
                         synchronized (WifiManager.this) {
                             if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
-                                mService.releaseMulticastLock();
+                                mService.releaseMulticastLock(mTag);
                                 throw new UnsupportedOperationException(
                                         "Exceeded maximum number of wifi locks");
                             }
@@ -3451,7 +3476,7 @@
             synchronized (mBinder) {
                 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
                     try {
-                        mService.releaseMulticastLock();
+                        mService.releaseMulticastLock(mTag);
                         synchronized (WifiManager.this) {
                             mActiveLockCount--;
                         }
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index 66297fc..ef9c59f 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -85,6 +85,17 @@
     public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11;
 
     /**
+     * The reason code for provisioning failure when a redirect server fails to start.
+     */
+    public static final int OSU_FAILURE_START_REDIRECT_SERVER = 12;
+
+    /**
+     * The reason code for provisioning failure when there is no OSU activity to listen to
+     * {@link WifiManager#ACTION_PASSPOINT_LAUNCH_OSU_VIEW} intent.
+     */
+    public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 13;
+
+    /**
      * The status code for provisioning flow to indicate connecting to OSU AP
      */
     public static final int OSU_STATUS_AP_CONNECTING = 1;
@@ -115,6 +126,16 @@
     public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6;
 
     /**
+     * The status code for provisioning flow to indicate waiting for a HTTP redirect response.
+     */
+    public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7;
+
+    /**
+     * The status code for provisioning flow to indicate a HTTP redirect response is received.
+     */
+    public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8;
+
+    /**
      * Provisioning status for OSU failure
      *
      * @param status indicates error condition