Merge "Expose WifiConfiguration @hide APIs as @SystemApi"
diff --git a/api/current.txt b/api/current.txt
index c2939fd..f1c03a4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30062,7 +30062,6 @@
     method @Deprecated public int addNetwork(android.net.wifi.WifiConfiguration);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void addScanResultsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
     method @Deprecated public static int calculateSignalLevel(int, int);
     method public int calculateSignalLevel(int);
@@ -30099,10 +30098,10 @@
     method @Deprecated public boolean pingSupplicant();
     method @Deprecated public boolean reassociate();
     method @Deprecated public boolean reconnect();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void registerScanResultsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsCallback);
     method @Deprecated public boolean removeNetwork(int);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_CARRIER_PROVISIONING"}) public void removePasspointConfiguration(String);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeScanResultsListener(@NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionConnectionStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
     method @Deprecated public boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
@@ -30111,6 +30110,7 @@
     method @RequiresPermission(allOf={android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, @Nullable android.os.Handler);
     method @Deprecated public boolean startScan();
     method @Deprecated public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void unregisterScanResultsCallback(@NonNull android.net.wifi.WifiManager.ScanResultsCallback);
     method @Deprecated public int updateNetwork(android.net.wifi.WifiConfiguration);
     field public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
@@ -30184,8 +30184,9 @@
     method public void setReferenceCounted(boolean);
   }
 
-  public static interface WifiManager.ScanResultsListener {
-    method public void onScanResultsAvailable();
+  public abstract static class WifiManager.ScanResultsCallback {
+    ctor public WifiManager.ScanResultsCallback();
+    method public abstract void onScanResultsAvailable();
   }
 
   public static interface WifiManager.SuggestionConnectionStatusListener {
@@ -44419,6 +44420,7 @@
     field public static final String KEY_CALL_BARRING_VISIBILITY_BOOL = "call_barring_visibility_bool";
     field public static final String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array";
     field public static final String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
+    field public static final String KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL = "carrier_app_required_during_setup_bool";
     field public static final String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app";
     field public static final String KEY_CARRIER_CONFIG_VERSION_STRING = "carrier_config_version_string";
     field public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings";
diff --git a/api/system-current.txt b/api/system-current.txt
index 5447b67..adfda2f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9153,6 +9153,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode();
     method public boolean isModemEnabledForSlot(int);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 484894f..d3367c10 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -106,6 +106,9 @@
     /**
      * Returns true if the key exists in the array. This is equivalent to
      * {@link #indexOfKey(int)} >= 0.
+     *
+     * @param key Potential key in the mapping
+     * @return true if the key is defined in the mapping
      */
     public boolean contains(int key) {
         return indexOfKey(key) >= 0;
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 0ff6063..cf39979 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -103,8 +103,7 @@
         }
 
         if (((attrs.inputFeatures &
-                WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) &&
-                (mHostInputToken != null)) {
+                WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
             try {
                 mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, outInputChannel);
             } catch (RemoteException e) {
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 41e9b4b..e53f3db 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -15,9 +15,8 @@
  */
 
 #include <DeviceInfo.h>
-#include <gui/SurfaceComposerClient.h>
 #include <log/log.h>
-#include <ui/GraphicTypes.h>
+#include <utils/Errors.h>
 
 #include <mutex>
 #include <thread>
@@ -32,44 +31,6 @@
     return &sDeviceInfo;
 }
 
-static void queryWideColorGamutPreference(sk_sp<SkColorSpace>* colorSpace, SkColorType* colorType) {
-    if (Properties::isolatedProcess) {
-        *colorSpace = SkColorSpace::MakeSRGB();
-        *colorType = SkColorType::kN32_SkColorType;
-        return;
-    }
-    ui::Dataspace defaultDataspace, wcgDataspace;
-    ui::PixelFormat defaultPixelFormat, wcgPixelFormat;
-    status_t status =
-        SurfaceComposerClient::getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
-                                                        &wcgDataspace, &wcgPixelFormat);
-    LOG_ALWAYS_FATAL_IF(status, "Failed to get composition preference, error %d", status);
-    switch (wcgDataspace) {
-        case ui::Dataspace::DISPLAY_P3:
-            *colorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
-            break;
-        case ui::Dataspace::V0_SCRGB:
-            *colorSpace = SkColorSpace::MakeSRGB();
-            break;
-        case ui::Dataspace::V0_SRGB:
-            // when sRGB is returned, it means wide color gamut is not supported.
-            *colorSpace = SkColorSpace::MakeSRGB();
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
-    }
-    switch (wcgPixelFormat) {
-        case ui::PixelFormat::RGBA_8888:
-            *colorType = SkColorType::kN32_SkColorType;
-            break;
-        case ui::PixelFormat::RGBA_FP16:
-            *colorType = SkColorType::kRGBA_F16_SkColorType;
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Unreachable: unsupported pixel format.");
-    }
-}
-
 DeviceInfo::DeviceInfo() {
 #if HWUI_NULL_GPU
         mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE;
@@ -77,7 +38,6 @@
         mMaxTextureSize = -1;
 #endif
         updateDisplayInfo();
-        queryWideColorGamutPreference(&mWideColorSpace, &mWideColorType);
 }
 DeviceInfo::~DeviceInfo() {
     ADisplay_release(mDisplays);
@@ -113,9 +73,45 @@
             }
         }
         LOG_ALWAYS_FATAL_IF(mPhysicalDisplayIndex < 0, "Failed to find a connected physical display!");
-        mMaxRefreshRate = ADisplay_getMaxSupportedFps(mDisplays[mPhysicalDisplayIndex]);
+
+
+        // Since we now just got the primary display for the first time, then
+        // store the primary display metadata here.
+        ADisplay* primaryDisplay = mDisplays[mPhysicalDisplayIndex];
+        mMaxRefreshRate = ADisplay_getMaxSupportedFps(primaryDisplay);
+        ADataSpace dataspace;
+        AHardwareBuffer_Format format;
+        ADisplay_getPreferredWideColorFormat(primaryDisplay, &dataspace, &format);
+        switch (dataspace) {
+            case ADATASPACE_DISPLAY_P3:
+                mWideColorSpace =
+                        SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+                break;
+            case ADATASPACE_SCRGB:
+                mWideColorSpace = SkColorSpace::MakeSRGB();
+                break;
+            case ADATASPACE_SRGB:
+                // when sRGB is returned, it means wide color gamut is not supported.
+                mWideColorSpace = SkColorSpace::MakeSRGB();
+                break;
+            default:
+                LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+        }
+        switch (format) {
+            case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
+                mWideColorType = SkColorType::kN32_SkColorType;
+                break;
+            case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+                mWideColorType = SkColorType::kRGBA_F16_SkColorType;
+                break;
+            default:
+                LOG_ALWAYS_FATAL("Unreachable: unsupported pixel format.");
+        }
     }
-    status_t status = ADisplay_getCurrentConfig(mDisplays[mPhysicalDisplayIndex], &mCurrentConfig);
+    // This method may have been called when the display config changed, so
+    // sync with the current configuration.
+    ADisplay* primaryDisplay = mDisplays[mPhysicalDisplayIndex];
+    status_t status = ADisplay_getCurrentConfig(primaryDisplay, &mCurrentConfig);
     LOG_ALWAYS_FATAL_IF(status, "Failed to get display config, error %d", status);
     mWidth = ADisplayConfig_getWidth(mCurrentConfig);
     mHeight = ADisplayConfig_getHeight(mCurrentConfig);
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 3431583..a420746 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -58,8 +58,8 @@
     ~DeviceInfo();
 
     int mMaxTextureSize;
-    sk_sp<SkColorSpace> mWideColorSpace;
-    SkColorType mWideColorType;
+    sk_sp<SkColorSpace> mWideColorSpace = SkColorSpace::MakeSRGB();
+    SkColorType mWideColorType = SkColorType::kN32_SkColorType;
     ADisplayConfig* mCurrentConfig = nullptr;
     ADisplay** mDisplays = nullptr;
     int mDisplaysSize = 0;
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index fe18fbf..fdb14be 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -400,13 +400,9 @@
          * Sends a command to the uncrypt service.
          *
          * @param command command to send to the uncrypt service
-         * @throws IOException if the socket is closed or there was an error writing to the socket
+         * @throws IOException if there was an error writing to the socket
          */
         public void sendCommand(String command) throws IOException {
-            if (mLocalSocket.isClosed()) {
-                throw new IOException("socket is closed");
-            }
-
             byte[] cmdUtf8 = command.getBytes(StandardCharsets.UTF_8);
             mOutputStream.writeInt(cmdUtf8.length);
             mOutputStream.write(cmdUtf8, 0, cmdUtf8.length);
@@ -415,25 +411,17 @@
         /**
          * Reads the status from the uncrypt service which is usually represented as a percentage.
          * @return an integer representing the percentage completed
-         * @throws IOException if the socket was closed or there was an error reading the socket
+         * @throws IOException if there was an error reading the socket
          */
         public int getPercentageUncrypted() throws IOException {
-            if (mLocalSocket.isClosed()) {
-                throw new IOException("socket is closed");
-            }
-
             return mInputStream.readInt();
         }
 
         /**
          * Sends a confirmation to the uncrypt service.
-         * @throws IOException if the socket was closed or there was an error writing to the socket
+         * @throws IOException if there was an error writing to the socket
          */
         public void sendAck() throws IOException {
-            if (mLocalSocket.isClosed()) {
-                throw new IOException("socket is closed");
-            }
-
             mOutputStream.writeInt(0);
         }
 
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 24948a2..0291017 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -16,8 +16,8 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.ActivityRecord.INVALID_PID;
 
+import android.annotation.Nullable;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.ArrayMap;
@@ -39,8 +39,21 @@
         mWmLock = wmLock;
     }
 
-    void add(IBinder inputToken, IWindow window, WindowState hostWindowState, int ownerUid,
-            int ownerPid) {
+    /**
+     * Adds a new embedded window.
+     *
+     * @param inputToken input channel token passed in by the embedding process when it requests
+     *                   the server to add an input channel to the embedded surface.
+     * @param window     client token used to clean up the map if the embedding process dies
+     * @param hostWindowState input channel token belonging to the host window. This is needed to
+     *                        handle input callbacks to wm. It's used when raising ANR and when
+     *                        the user taps out side of the focused region on screen. This can be
+     *                        null if there is no host window.
+     * @param ownerUid  calling uid
+     * @param ownerPid  calling pid used for anr blaming
+     */
+    void add(IBinder inputToken, IWindow window, @Nullable WindowState hostWindowState,
+            int ownerUid, int ownerPid) {
         EmbeddedWindow embeddedWindow = new EmbeddedWindow(window, hostWindowState, ownerUid,
                 ownerPid);
         try {
@@ -61,31 +74,30 @@
         return embeddedWindow != null ? embeddedWindow.mHostWindowState : null;
     }
 
-    int getOwnerPid(IBinder inputToken) {
-        EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
-        return embeddedWindow != null ? embeddedWindow.mOwnerPid : INVALID_PID;
-    }
-
     void remove(IWindow client) {
-        for (ArrayMap.Entry<IBinder, EmbeddedWindow> entry: mWindows.entrySet()) {
-            if (entry.getValue().mClient.asBinder() == client.asBinder()) {
-                mWindows.remove(entry.getKey());
+        for (int i = mWindows.size() - 1; i >= 0; i--) {
+            if (mWindows.valueAt(i).mClient.asBinder() == client.asBinder()) {
+                mWindows.removeAt(i);
                 return;
             }
         }
     }
 
     void removeWindowsWithHost(WindowState host) {
-        for (ArrayMap.Entry<IBinder, EmbeddedWindow> entry: mWindows.entrySet()) {
-            if (entry.getValue().mHostWindowState == host) {
-                mWindows.remove(entry.getKey());
+        for (int i = mWindows.size() - 1; i >= 0; i--) {
+            if (mWindows.valueAt(i).mHostWindowState == host) {
+                mWindows.removeAt(i);
             }
         }
     }
 
-    private static class EmbeddedWindow {
+    EmbeddedWindow get(IBinder inputToken) {
+        return mWindows.get(inputToken);
+    }
+
+    static class EmbeddedWindow {
         final IWindow mClient;
-        final WindowState mHostWindowState;
+        @Nullable final WindowState mHostWindowState;
         final int mOwnerUid;
         final int mOwnerPid;
 
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 2a6fb4a..1f9f883 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -20,6 +20,7 @@
 import android.view.WindowManager;
 
 import com.android.server.input.InputManagerService;
+import com.android.server.wm.EmbeddedWindowController.EmbeddedWindow;
 
 import java.io.PrintWriter;
 import java.util.concurrent.atomic.AtomicReference;
@@ -90,20 +91,39 @@
         int windowPid = INVALID_PID;
         //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
         synchronized (mService.mGlobalLock) {
+
+            // Check if we can blame a window
             if (token != null) {
                 windowState = mService.mInputToWindowMap.get(token);
                 if (windowState != null) {
                     activity = windowState.mActivityRecord;
                     windowPid = windowState.mSession.mPid;
-                } else {
-                    // Check if this is an embedded window and if so get the embedded app pid
-                    windowPid = mService.mEmbeddedWindowController.getOwnerPid(token);
-                    WindowState hostWindowState =
-                            mService.mEmbeddedWindowController.getHostWindow(token);
-                    aboveSystem = isWindowAboveSystem(hostWindowState);
+                    // Figure out whether this window is layered above system windows.
+                    // We need to do this here to help the activity manager know how to
+                    // layer its ANR dialog.
+                    aboveSystem = isWindowAboveSystem(windowState);
                 }
             }
 
+            // Check if we can blame an embedded window
+            if (token != null && windowState == null) {
+                EmbeddedWindow embeddedWindow = mService.mEmbeddedWindowController.get(token);
+                if (embeddedWindow != null) {
+                    windowPid = embeddedWindow.mOwnerPid;
+                    WindowState hostWindowState = embeddedWindow.mHostWindowState;
+                    if (hostWindowState == null) {
+                        // The embedded window has no host window and we cannot easily determine
+                        // its z order. Try to place the anr dialog as high as possible.
+                        aboveSystem = true;
+                    } else {
+                        aboveSystem = isWindowAboveSystem(hostWindowState);
+                    }
+                }
+            }
+
+            // Check if we can blame an activity. If we don't have an activity to blame, pull out
+            // the token passed in via input application handle. This can happen if there are no
+            // focused windows but input dispatcher knows the focused app.
             if (activity == null && inputApplicationHandle != null) {
                 activity = ActivityRecord.forTokenLocked(inputApplicationHandle.token);
             }
@@ -112,10 +132,6 @@
                 Slog.i(TAG_WM, "Input event dispatching timed out "
                         + "sending to " + windowState.mAttrs.getTitle()
                         + ".  Reason: " + reason);
-                // Figure out whether this window is layered above system windows.
-                // We need to do this here to help the activity manager know how to
-                // layer its ANR dialog.
-                aboveSystem = isWindowAboveSystem(windowState);
             } else if (activity != null) {
                 Slog.i(TAG_WM, "Input event dispatching timed out "
                         + "sending to application " + activity.stringName
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index c0432b6..a175d63 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -621,8 +621,15 @@
         return false;
     }
 
+    @Override
     public void grantInputChannel(int displayId, SurfaceControl surface,
             IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
+        if (hostInputToken == null && !mCanAddInternalSystemWindow) {
+            // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
+            // embedded windows without providing a host window input token
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
         final long identity = Binder.clearCallingIdentity();
         try {
             mService.grantInputChannel(mUid, mPid, displayId, surface, window,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a2467e6..5afcab0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7674,19 +7674,17 @@
      */
     void grantInputChannel(int callingUid, int callingPid, int displayId, SurfaceControl surface,
             IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
-        final InputApplicationHandle applicationHandle;
+        InputApplicationHandle applicationHandle = null;
         final String name;
         final InputChannel[] inputChannels;
         final InputChannel clientChannel;
         final InputChannel serverChannel;
         synchronized (mGlobalLock) {
             final WindowState hostWindow = mInputToWindowMap.get(hostInputToken);
-            if (hostWindow == null) {
-                Slog.e(TAG, "Failed to grant input channel");
-                return;
-            }
+            final String hostWindowName = (hostWindow != null)
+                    ? hostWindow.getWindowTag().toString() : "Internal";
             name = "EmbeddedWindow{ u" + UserHandle.getUserId(callingUid)
-                    + " " + hostWindow.getWindowTag() + "}";
+                    + " " + hostWindowName + "}";
 
             inputChannels = InputChannel.openInputChannelPair(name);
             serverChannel = inputChannels[0];
@@ -7694,8 +7692,10 @@
             mInputManager.registerInputChannel(serverChannel);
             mEmbeddedWindowController.add(serverChannel.getToken(), window, hostWindow, callingUid,
                     callingPid);
-            applicationHandle = new InputApplicationHandle(
-                hostWindow.mInputWindowHandle.inputApplicationHandle);
+            if (hostWindow != null) {
+                applicationHandle = new InputApplicationHandle(
+                        hostWindow.mInputWindowHandle.inputApplicationHandle);
+            }
         }
 
         clientChannel.transferTo(outInputChannel);
diff --git a/telephony/java/com/android/internal/telephony/SmsConstants.java b/telephony/common/com/android/internal/telephony/SmsConstants.java
similarity index 100%
rename from telephony/java/com/android/internal/telephony/SmsConstants.java
rename to telephony/common/com/android/internal/telephony/SmsConstants.java
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
index 0d33af6..367aad1 100644
--- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -359,15 +359,41 @@
         return NP_NONE;
     }
 
+    /**
+     * This function checks if the passed in string conforms to the NANP format
+     * i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9
+     */
     private static boolean isNANP(String number) {
+        boolean retVal = false;
+
         if (number.length() == NANP_MEDIUM_LENGTH
             || (number.length() == NANP_LONG_LENGTH  && number.startsWith(NANP_NDD))) {
+
             if (number.length() == NANP_LONG_LENGTH) {
                 number = number.substring(1);
             }
-            return (PhoneNumberUtils.isNanp(number));
+
+            if (isTwoToNine(number.charAt(0)) &&
+                isTwoToNine(number.charAt(3))) {
+                retVal = true;
+                for (int i=1; i<NANP_MEDIUM_LENGTH; i++ ) {
+                    char c=number.charAt(i);
+                    if (!PhoneNumberUtils.isISODigit(c)) {
+                        retVal = false;
+                        break;
+                    }
+                 }
+             }
         }
-        return false;
+        return retVal;
+    }
+
+    private static boolean isTwoToNine (char c) {
+        if (c >= '2' && c <= '9') {
+            return true;
+        } else {
+            return false;
+        }
     }
 
     /**
@@ -573,9 +599,9 @@
         int networkType = -1;
         int phoneType = telephonyManager.getPhoneType();
 
-        if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
+        if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
             networkType = GSM_UMTS_NETWORK;
-        } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
+        } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
             if (isInternationalRoaming(telephonyManager)) {
                 networkType = CDMA_ROAMING_NETWORK;
             } else {
diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java
index 95ae409..b237705 100755
--- a/telephony/common/com/google/android/mms/pdu/PduPersister.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java
@@ -291,15 +291,11 @@
     @UnsupportedAppUsage
     private final ContentResolver mContentResolver;
     private final DrmManagerClient mDrmManagerClient;
-    @UnsupportedAppUsage
-    private final TelephonyManager mTelephonyManager;
 
     private PduPersister(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
         mDrmManagerClient = new DrmManagerClient(context);
-        mTelephonyManager = (TelephonyManager)context
-                .getSystemService(Context.TELEPHONY_SERVICE);
      }
 
     /** Get(or create if not exist) an instance of PduPersister */
@@ -1453,7 +1449,8 @@
         if (excludeMyNumber) {
             // Build a list of my phone numbers from the various sims.
             for (int subid : subscriptionManager.getActiveSubscriptionIdList()) {
-                final String myNumber = mTelephonyManager.getLine1Number(subid);
+                final String myNumber = mContext.getSystemService(TelephonyManager.class).
+                        createForSubscriptionId(subid).getLine1Number();
                 if (myNumber != null) {
                     myPhoneNumbers.add(myNumber);
                 }
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 7ed37c4..add0316 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -25,7 +25,6 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
-import android.compat.annotation.ChangeId;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -4034,16 +4033,6 @@
         @Retention(RetentionPolicy.SOURCE)
         public @interface Skip464XlatStatus {}
 
-        /**
-         * Compat framework change ID for the APN db read permission change.
-         *
-         * In API level 30 and beyond, accessing the APN database will require the
-         * {@link android.Manifest.permission#WRITE_APN_SETTINGS} permission. This change ID tracks
-         * apps that are affected because they don't hold this permission.
-         * @hide
-         */
-        @ChangeId
-        public static final long APN_READING_PERMISSION_CHANGE_ID = 124107808L;
     }
 
     /**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f94c8e3..479b144 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1701,7 +1701,6 @@
     /**
      * Determines whether the carrier app needed to be involved when users try to finish setting up
      * the SIM card to get network service.
-     * @hide
      */
     public static final String KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL =
             "carrier_app_required_during_setup_bool";
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a55d166..9f8a213 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7747,20 +7747,20 @@
      * {@link CarrierConfigManager#KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT}. If
      * the carrier does not support this mode, this function will always return false.
      *
-     * @return true if this device is in emergency SMS mode, false otherwise.
+     * @return {@code true} if this device is in emergency SMS mode, {@code false} otherwise.
      *
      * @hide
      */
+    @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isInEmergencySmsMode() {
-
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony.isInEmergencySmsMode();
             }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "getNetworkSelectionMode RemoteException", ex);
+            Rlog.e(TAG, "isInEmergencySmsMode RemoteException", ex);
         }
         return false;
     }
diff --git a/wifi/java/android/net/wifi/IScanResultsCallback.aidl b/wifi/java/android/net/wifi/IScanResultsCallback.aidl
new file mode 100644
index 0000000..56f6025
--- /dev/null
+++ b/wifi/java/android/net/wifi/IScanResultsCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * Interface for Wi-Fi scan result available callback.
+ *
+ * @hide
+ */
+oneway interface IScanResultsCallback
+{
+    void onScanResultsAvailable();
+}
diff --git a/wifi/java/android/net/wifi/IScanResultsListener.aidl b/wifi/java/android/net/wifi/IScanResultsListener.aidl
index bec74a6..e7eaddd 100644
--- a/wifi/java/android/net/wifi/IScanResultsListener.aidl
+++ b/wifi/java/android/net/wifi/IScanResultsListener.aidl
@@ -16,11 +16,8 @@
 
 package android.net.wifi;
 
-/**
- * Interface for Wi-Fi scan result available callback.
- *
- * @hide
- */
+/** @hide */
+
 oneway interface IScanResultsListener
 {
     void onScanResultsAvailable();
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 4619372..4a89c66 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -28,7 +28,7 @@
 import android.net.wifi.IDppCallback;
 import android.net.wifi.ILocalOnlyHotspotCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
-import android.net.wifi.IScanResultsListener;
+import android.net.wifi.IScanResultsCallback;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ISuggestionConnectionStatusListener;
 import android.net.wifi.ITrafficStateCallback;
@@ -233,9 +233,9 @@
 
     oneway void getTxPacketCount(String packageName, in IBinder binder, in ITxPacketCountListener listener, int callbackIdentifier);
 
-    void registerScanResultsListener(in IBinder binder, in IScanResultsListener Listener, int listenerIdentifier);
+    void registerScanResultsCallback(in IScanResultsCallback callback);
 
-    void unregisterScanResultsListener(int listenerIdentifier);
+    void unregisterScanResultsCallback(in IScanResultsCallback callback);
 
     void registerSuggestionConnectionStatusListener(in IBinder binder, in ISuggestionConnectionStatusListener listener, int listenerIdentifier, String packageName, String featureId);
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 942d795..2a0211b 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -5453,40 +5453,76 @@
     }
 
     /**
-     * Interface for scan results listener. Should be implemented by applications and set when
-     * calling {@link WifiManager#addScanResultsListener(Executor, ScanResultsListener)}.
+     * Abstract class for scan results callback. Should be extended by applications and set when
+     * calling {@link WifiManager#registerScanResultsCallback(Executor, ScanResultsCallback)}.
      */
-    public interface ScanResultsListener {
+    public abstract static class ScanResultsCallback {
+        private final ScanResultsCallbackProxy mScanResultsCallbackProxy;
+
+        public ScanResultsCallback() {
+            mScanResultsCallbackProxy = new ScanResultsCallbackProxy();
+        }
 
         /**
-         * Called when new scan results available.
-         * Caller should use {@link WifiManager#getScanResults()} to get the scan results.
+         * Called when new scan results are available.
+         * Clients should use {@link WifiManager#getScanResults()} to get the scan results.
          */
-        void onScanResultsAvailable();
-    }
+        public abstract void onScanResultsAvailable();
 
-    private class ScanResultsListenerProxy extends IScanResultsListener.Stub {
-        private final Executor mExecutor;
-        private final ScanResultsListener mListener;
-
-        ScanResultsListenerProxy(Executor executor, ScanResultsListener listener) {
-            mExecutor = executor;
-            mListener = listener;
+        /*package*/ @NonNull ScanResultsCallbackProxy getProxy() {
+            return mScanResultsCallbackProxy;
         }
 
-        @Override
-        public void onScanResultsAvailable() {
-            mExecutor.execute(mListener::onScanResultsAvailable);
+        private static class ScanResultsCallbackProxy extends IScanResultsCallback.Stub {
+            private final Object mLock = new Object();
+            @Nullable @GuardedBy("mLock") private Executor mExecutor;
+            @Nullable @GuardedBy("mLock") private ScanResultsCallback mCallback;
+
+            ScanResultsCallbackProxy() {
+                mCallback = null;
+                mExecutor = null;
+            }
+
+            /*package*/ void initProxy(@NonNull Executor executor,
+                    @NonNull ScanResultsCallback callback) {
+                synchronized (mLock) {
+                    mExecutor = executor;
+                    mCallback = callback;
+                }
+            }
+
+            /*package*/ void cleanUpProxy() {
+                synchronized (mLock) {
+                    mExecutor = null;
+                    mCallback = null;
+                }
+            }
+
+            @Override
+            public void onScanResultsAvailable() {
+                ScanResultsCallback callback;
+                Executor executor;
+                synchronized (mLock) {
+                    executor = mExecutor;
+                    callback = mCallback;
+                }
+                if (callback == null || executor == null) {
+                    return;
+                }
+                Binder.clearCallingIdentity();
+                executor.execute(callback::onScanResultsAvailable);
+            }
         }
+
     }
 
     /**
-     * Add a listener for Scan Results. See {@link ScanResultsListener}.
+     * Register a callback for Scan Results. See {@link ScanResultsCallback}.
      * Caller will receive the event when scan results are available.
      * Caller should use {@link WifiManager#getScanResults()} requires
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results.
-     * Caller can remove a previously registered listener using
-     * {@link WifiManager#removeScanResultsListener(ScanResultsListener)}
+     * Caller can remove a previously registered callback using
+     * {@link WifiManager#unregisterScanResultsCallback(ScanResultsCallback)}
      * Same caller can add multiple listeners.
      * <p>
      * Applications should have the
@@ -5494,49 +5530,52 @@
      * without the permission will trigger a {@link java.lang.SecurityException}.
      * <p>
      *
-     * @param executor The executor to execute the listener of the {@code listener} object.
-     * @param listener listener for Scan Results events
+     * @param executor The executor to execute the callback of the {@code callback} object.
+     * @param callback callback for Scan Results events
      */
 
     @RequiresPermission(ACCESS_WIFI_STATE)
-    public void addScanResultsListener(@NonNull @CallbackExecutor Executor executor,
-            @NonNull ScanResultsListener listener) {
-        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+    public void registerScanResultsCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull ScanResultsCallback callback) {
         if (executor == null) throw new IllegalArgumentException("executor cannot be null");
-        Log.v(TAG, "addScanResultsListener: listener=" + listener + ", executor=" + executor);
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+
+        Log.v(TAG, "registerScanResultsCallback: callback=" + callback
+                + ", executor=" + executor);
+        ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy();
+        proxy.initProxy(executor, callback);
         try {
             IWifiManager iWifiManager = getIWifiManager();
             if (iWifiManager == null) {
                 throw new RemoteException("Wifi service is not running");
             }
-            iWifiManager.registerScanResultsListener(
-                    new Binder(),
-                    new ScanResultsListenerProxy(executor, listener),
-                    listener.hashCode());
+            iWifiManager.registerScanResultsCallback(proxy);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Allow callers to remove a previously added listener. After calling this method,
+     * Allow callers to unregister a previously registered callback. After calling this method,
      * applications will no longer receive Scan Results events.
      *
-     * @param listener listener to remove for Scan Results events
+     * @param callback callback to unregister for Scan Results events
      */
     @RequiresPermission(ACCESS_WIFI_STATE)
-    public void removeScanResultsListener(@NonNull ScanResultsListener listener) {
-        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
-        Log.v(TAG, "removeScanResultsListener: listener=" + listener);
-
+    public void unregisterScanResultsCallback(@NonNull ScanResultsCallback callback) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "unregisterScanResultsCallback: Callback=" + callback);
+        ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy();
         try {
             IWifiManager iWifiManager = getIWifiManager();
             if (iWifiManager == null) {
                 throw new RemoteException("Wifi service is not running");
             }
-            iWifiManager.unregisterScanResultsListener(listener.hashCode());
+            iWifiManager.unregisterScanResultsCallback(proxy);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } finally {
+            proxy.cleanUpProxy();
         }
     }
 
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index ee03c11..534e609 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -26,6 +26,7 @@
 import android.net.wifi.ILocalOnlyHotspotCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
 import android.net.wifi.IOnWifiUsabilityStatsListener;
+import android.net.wifi.IScanResultsCallback;
 import android.net.wifi.IScanResultsListener;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ISuggestionConnectionStatusListener;
@@ -512,18 +513,30 @@
         throw new UnsupportedOperationException();
     }
 
-    @Override
+    /** @deprecated replaced by {@link #registerScanResultsCallback(IScanResultsCallback)} */
+    @Deprecated
     public void registerScanResultsListener(
             IBinder binder, IScanResultsListener listener, int listenerIdentifier) {
         throw new UnsupportedOperationException();
     }
 
-    @Override
+    /** @deprecated replaced by {@link #unregisterScanResultsCallback(IScanResultsCallback)} */
+    @Deprecated
     public void unregisterScanResultsListener(int listenerIdentifier) {
         throw new UnsupportedOperationException();
     }
 
     @Override
+    public void registerScanResultsCallback(IScanResultsCallback callback) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterScanResultsCallback(IScanResultsCallback callback) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void registerSuggestionConnectionStatusListener(IBinder binder,
             ISuggestionConnectionStatusListener listener,
             int listenerIdentifier, String packageName, String featureId) {
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 507d502..8cdcba6 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -60,7 +60,7 @@
 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener;
-import android.net.wifi.WifiManager.ScanResultsListener;
+import android.net.wifi.WifiManager.ScanResultsCallback;
 import android.net.wifi.WifiManager.SoftApCallback;
 import android.net.wifi.WifiManager.SuggestionConnectionStatusListener;
 import android.net.wifi.WifiManager.TrafficStateCallback;
@@ -112,15 +112,16 @@
     @Mock TrafficStateCallback mTrafficStateCallback;
     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
     @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
-    @Mock ScanResultsListener mScanResultListener;
     @Mock SuggestionConnectionStatusListener mListener;
-    @Mock Executor mCallbackExecutor;
+    @Mock Runnable mRunnable;
     @Mock Executor mExecutor;
+    @Mock Executor mAnotherExecutor;
 
     private Handler mHandler;
     private TestLooper mLooper;
     private WifiManager mWifiManager;
     private WifiNetworkSuggestion mWifiNetworkSuggestion;
+    private ScanResultsCallback mScanResultsCallback;
 
     @Before
     public void setUp() throws Exception {
@@ -133,6 +134,12 @@
         mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
         verify(mWifiService).getVerboseLoggingLevel();
         mWifiNetworkSuggestion = new WifiNetworkSuggestion();
+        mScanResultsCallback = new ScanResultsCallback() {
+            @Override
+            public void onScanResultsAvailable() {
+                mRunnable.run();
+            }
+        };
     }
 
     /**
@@ -1778,65 +1785,81 @@
     }
 
     /**
-     * Verify an IllegalArgumentException is thrown if listener is not provided.
+     * Verify an IllegalArgumentException is thrown if callback is not provided.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testAddScanResultsListenerWithNullListener() throws Exception {
-        mWifiManager.addScanResultsListener(mCallbackExecutor, null);
+    public void testRegisterScanResultsCallbackWithNullCallback() throws Exception {
+        mWifiManager.registerScanResultsCallback(mExecutor, null);
     }
 
     /**
      * Verify an IllegalArgumentException is thrown if executor is not provided.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testAddScanResultsListenerWithNullExecutor() throws Exception {
-        mWifiManager.addScanResultsListener(null, mScanResultListener);
+    public void testRegisterCallbackWithNullExecutor() throws Exception {
+        mWifiManager.registerScanResultsCallback(null, mScanResultsCallback);
     }
 
     /**
-     * Verify client provided listener is being called to the right listener.
+     * Verify client provided callback is being called to the right callback.
      */
     @Test
-    public void testAddScanResultsListenerAndReceiveEvent() throws Exception {
-        ArgumentCaptor<IScanResultsListener.Stub> callbackCaptor =
-                ArgumentCaptor.forClass(IScanResultsListener.Stub.class);
-        Executor executor = new SynchronousExecutor();
-        mWifiManager.addScanResultsListener(executor, mScanResultListener);
-        verify(mWifiService).registerScanResultsListener(any(IBinder.class),
-                callbackCaptor.capture(), anyInt());
+    public void testAddScanResultsCallbackAndReceiveEvent() throws Exception {
+        ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
+        mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
+        verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
         callbackCaptor.getValue().onScanResultsAvailable();
-        verify(mScanResultListener).onScanResultsAvailable();
+        verify(mRunnable).run();
     }
 
     /**
-     * Verify client provided listener is being called on the right executor.
+     * Verify client provided callback is being called to the right executor.
      */
     @Test
-    public void testAddScanResultsListenerWithTheTargetExecutor() throws Exception {
-        ArgumentCaptor<IScanResultsListener.Stub> callbackCaptor =
-                ArgumentCaptor.forClass(IScanResultsListener.Stub.class);
-        mWifiManager.addScanResultsListener(mExecutor, mScanResultListener);
-        verify(mWifiService).registerScanResultsListener(any(IBinder.class),
-                callbackCaptor.capture(), anyInt());
+    public void testRegisterScanResultsCallbackWithTheTargetExecutor() throws Exception {
+        ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
+        mWifiManager.registerScanResultsCallback(mExecutor, mScanResultsCallback);
+        verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
+        mWifiManager.registerScanResultsCallback(mAnotherExecutor, mScanResultsCallback);
         callbackCaptor.getValue().onScanResultsAvailable();
-        verify(mExecutor).execute(any(Runnable.class));
+        verify(mExecutor, never()).execute(any(Runnable.class));
+        verify(mAnotherExecutor).execute(any(Runnable.class));
     }
 
     /**
-     * Verify client removeScanResultsListener.
+     * Verify client register unregister then register again, to ensure callback still works.
      */
     @Test
-    public void testRemoveScanResultsListener() throws Exception {
-        mWifiManager.removeScanResultsListener(mScanResultListener);
-        verify(mWifiService).unregisterScanResultsListener(anyInt());
+    public void testRegisterUnregisterThenRegisterAgainWithScanResultCallback() throws Exception {
+        ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
+        mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
+        verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
+        mWifiManager.unregisterScanResultsCallback(mScanResultsCallback);
+        callbackCaptor.getValue().onScanResultsAvailable();
+        verify(mRunnable, never()).run();
+        mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
+        callbackCaptor.getValue().onScanResultsAvailable();
+        verify(mRunnable).run();
     }
 
     /**
-     * Verify client removeScanResultsListener with null listener will cause an exception.
+     * Verify client unregisterScanResultsCallback.
+     */
+    @Test
+    public void testUnregisterScanResultsCallback() throws Exception {
+        mWifiManager.unregisterScanResultsCallback(mScanResultsCallback);
+        verify(mWifiService).unregisterScanResultsCallback(any());
+    }
+
+    /**
+     * Verify client unregisterScanResultsCallback with null callback will cause an exception.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testRemoveScanResultsListenerWithNullListener() throws Exception {
-        mWifiManager.removeScanResultsListener(null);
+    public void testUnregisterScanResultsCallbackWithNullCallback() throws Exception {
+        mWifiManager.unregisterScanResultsCallback(null);
     }
 
     /**