Merge "Allow some app windows to display above the IME."
diff --git a/Android.bp b/Android.bp
index 010b2b4..dba49ce 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 subdirs = [
+    "libs/*",
     "native/android",
     "native/graphics/jni",
 ]
diff --git a/api/current.txt b/api/current.txt
index 304ccf8..bab071b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20199,8 +20199,8 @@
   }
 
   public class AudioTrack implements android.media.AudioRouting {
-    ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
-    ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -21489,7 +21489,7 @@
     method public void selectTrack(int) throws java.lang.IllegalStateException;
     method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
-    method public void setAudioStreamType(int);
+    method public deprecated void setAudioStreamType(int);
     method public void setAuxEffectSendLevel(float);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
diff --git a/api/system-current.txt b/api/system-current.txt
index d54e6a9..4a2f2d5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21766,8 +21766,8 @@
   }
 
   public class AudioTrack implements android.media.AudioRouting {
-    ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
-    ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -23056,7 +23056,7 @@
     method public void selectTrack(int) throws java.lang.IllegalStateException;
     method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
-    method public void setAudioStreamType(int);
+    method public deprecated void setAudioStreamType(int);
     method public void setAuxEffectSendLevel(float);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
diff --git a/api/test-current.txt b/api/test-current.txt
index f269479..b888911 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -20286,8 +20286,8 @@
   }
 
   public class AudioTrack implements android.media.AudioRouting {
-    ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
-    ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -21576,7 +21576,7 @@
     method public void selectTrack(int) throws java.lang.IllegalStateException;
     method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
-    method public void setAudioStreamType(int);
+    method public deprecated void setAudioStreamType(int);
     method public void setAuxEffectSendLevel(float);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 65f74d1..312d3a5 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -561,8 +561,11 @@
         /** ID of stack that always on top (always visible) when it exist. */
         public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
 
+        /** Recents activity stack ID. */
+        public static final int RECENTS_STACK_ID = PINNED_STACK_ID + 1;
+
         /** Last static stack stack ID. */
-        public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
+        public static final int LAST_STATIC_STACK_ID = RECENTS_STACK_ID;
 
         /** Start of ID range used by stacks that are created dynamically. */
         public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
@@ -735,6 +738,13 @@
         }
 
         /**
+         * Returns true if the input {@param stackId} is HOME_STACK_ID or RECENTS_STACK_ID
+         */
+        public static boolean isHomeOrRecentsStack(int stackId) {
+            return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID;
+        }
+
+        /**
          * Returns true if activities contained in this stack can request visible behind by
          * calling {@link Activity#requestVisibleBehind}.
          */
@@ -760,7 +770,8 @@
 
         /** Returns true if the input stack and its content can affect the device orientation. */
         public static boolean canSpecifyOrientation(int stackId) {
-            return stackId == HOME_STACK_ID || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
+            return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID
+                    || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
         }
     }
 
@@ -1509,7 +1520,7 @@
      * Ignores all tasks that are on the home stack.
      * @hide
      */
-    public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008;
+    public static final int RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS = 0x0008;
 
     /**
      * Ignores the top task in the docked stack.
@@ -2052,15 +2063,6 @@
         }
     }
 
-    /** @hide */
-    public boolean isInHomeStack(int taskId) {
-        try {
-            return getService().isInHomeStack(taskId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
     /**
      * Flag for {@link #moveTaskToFront(int, int)}: also move the "home"
      * activity along with the task, so it is positioned immediately behind
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 1a36d1a..640ca6c 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -370,7 +370,6 @@
     // Start of L transactions
     String getTagForIntentSender(in IIntentSender sender, in String prefix);
     boolean startUserInBackground(int userid);
-    boolean isInHomeStack(int taskId);
     void startLockTaskModeById(int taskId);
     void startLockTaskModeByToken(in IBinder token);
     void stopLockTaskMode();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1fd082f4..c1e2072 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
+import android.media.PlayerBase;
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.BadParcelableException;
@@ -2821,6 +2822,7 @@
          */
         @Deprecated
         public Builder setSound(Uri sound, int streamType) {
+            PlayerBase.deprecateStreamTypeForPlayback(streamType, "Notification", "setSound()");
             mN.sound = sound;
             mN.audioStreamType = streamType;
             return this;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index a854b89..56f914e 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -314,9 +314,11 @@
      *
      * @hide
      */
-    public void enforceMandatoryFields() {
+    public void enforceMandatoryFields(boolean forPinned) {
         Preconditions.checkStringNotEmpty(mId, "Shortcut ID must be provided");
-        Preconditions.checkNotNull(mActivity, "Activity must be provided");
+        if (!forPinned) {
+            Preconditions.checkNotNull(mActivity, "Activity must be provided");
+        }
         if (mTitle == null && mTitleResId == 0) {
             throw new IllegalArgumentException("Short label must be provided");
         }
@@ -1055,6 +1057,11 @@
      * Launcher apps should show the launcher icon for the returned activity alongside
      * this shortcut.
      *
+     * <p>When a shortcut is dynamic or manifest
+     * (i.e. either {@link #isDynamic()} or {@link #isDeclaredInManifest()} returns {@code TRUE}),
+     * then it should always have a non-null target activity.
+     * Otherwise it will return null.
+     *
      * @see Builder#setActivity
      */
     @Nullable
@@ -1361,7 +1368,7 @@
     }
 
     /**
-     * @return true if pinned but neither static nor dynamic.
+     * Return {@code TRUE} if a shortcut is pinned but neither manifest nor dynamic.
      * @hide
      */
     public boolean isFloating() {
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index c206974..e0d589a 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -53,6 +53,10 @@
         return sPackage.packageName;
     }
 
+    public static boolean isMultiprocessEnabled() {
+        return sMultiprocessEnabled && sPackage != null;
+    }
+
     public static void setMultiprocessEnabled(boolean enabled) {
         sMultiprocessEnabled = enabled;
 
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 069f81b..9490436 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -155,7 +155,7 @@
 
     @VisibleForTesting
     public static int makeTag(char c1, char c2, char c3, char c4) {
-        return (c1 << 24) + (c2 << 16) + (c3 << 8) + c4;
+        return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
     }
 
     private static boolean isSpacer(char c) {
@@ -228,8 +228,10 @@
         return new Font(fullFilename, index, axes, weight, isItalic);
     }
 
-    /** The 'tag' attribute value is read as four character values between 0 and 255 inclusive. */
-    private static final Pattern TAG_PATTERN = Pattern.compile("[\\x00-\\xFF]{4}");
+    /** The 'tag' attribute value is read as four character values between U+0020 and U+007E
+     *  inclusive.
+     */
+    private static final Pattern TAG_PATTERN = Pattern.compile("[\\x20-\\x7E]{4}");
 
     /** The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
      *  '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
index e4d6aa8..d046c11 100644
--- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
@@ -105,9 +105,18 @@
     }
 
     @SmallTest
+    public void testInvalidTagCharacters() {
+        FontListParser.Axis[] axis =
+                FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
+        assertEquals(0, axis.length);
+    }
+
+    @SmallTest
     public void testMakeTag() {
       assertEquals(0x77647468, FontListParser.makeTag('w', 'd', 't', 'h'));
       assertEquals(0x41582020, FontListParser.makeTag('A', 'X', ' ', ' '));
       assertEquals(0x20202020, FontListParser.makeTag(' ', ' ', ' ', ' '));
     }
-}
\ No newline at end of file
+}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
new file mode 100644
index 0000000..d501d25
--- /dev/null
+++ b/libs/androidfw/Android.bp
@@ -0,0 +1,74 @@
+// Copyright (C) 2010 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.
+
+// libandroidfw is partially built for the host (used by obbtool, aapt, and others)
+
+cc_library {
+    name: "libandroidfw",
+    host_supported: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+    srcs: [
+        "Asset.cpp",
+        "AssetDir.cpp",
+        "AssetManager.cpp",
+        "AttributeResolution.cpp",
+        "LocaleData.cpp",
+        "misc.cpp",
+        "ObbFile.cpp",
+        "ResourceTypes.cpp",
+        "StreamingZipInflater.cpp",
+        "TypeWrappers.cpp",
+        "ZipFileRO.cpp",
+        "ZipUtils.cpp",
+    ],
+    export_include_dirs: ["include"],
+    target: {
+        android: {
+            srcs: [
+                "BackupData.cpp",
+                "BackupHelpers.cpp",
+                "CursorWindow.cpp",
+                "DisplayEventDispatcher.cpp",
+            ],
+            shared_libs: [
+                "libziparchive",
+                "libbase",
+                "libbinder",
+                "liblog",
+                "libcutils",
+                "libgui",
+                "libutils",
+                "libz",
+            ],
+            static: {
+                enabled: false,
+            },
+        },
+        host: {
+            cflags: ["-DSTATIC_ANDROIDFW_FOR_TOOLS"],
+            shared: {
+                enabled: false,
+            },
+            shared_libs: ["libz-host"],
+        },
+        windows: {
+            enabled: true,
+        },
+    },
+}
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 7689256..68c51ef 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -14,74 +14,6 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# libandroidfw is partially built for the host (used by obbtool, aapt, and others)
-# These files are common to host and target builds.
-
-commonSources := \
-    Asset.cpp \
-    AssetDir.cpp \
-    AssetManager.cpp \
-    AttributeResolution.cpp \
-    LocaleData.cpp \
-    misc.cpp \
-    ObbFile.cpp \
-    ResourceTypes.cpp \
-    StreamingZipInflater.cpp \
-    TypeWrappers.cpp \
-    ZipFileRO.cpp \
-    ZipUtils.cpp
-
-deviceSources := \
-    $(commonSources) \
-    BackupData.cpp \
-    BackupHelpers.cpp \
-    CursorWindow.cpp \
-    DisplayEventDispatcher.cpp
-
-hostSources := $(commonSources)
-
-# For the host
-# =====================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= libandroidfw
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-LOCAL_SRC_FILES:= $(hostSources)
-LOCAL_C_INCLUDES := external/zlib
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-
-# For the device
-# =====================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= libandroidfw
-LOCAL_SRC_FILES:= $(deviceSources)
-LOCAL_C_INCLUDES := \
-    system/core/include
-LOCAL_SHARED_LIBRARIES := \
-    libziparchive \
-    libbase \
-    libbinder \
-    liblog \
-    libcutils \
-    libgui \
-    libutils \
-    libz
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
-
-
 # Include subdirectory makefiles
 # ============================================================
 
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 93e86af..4c39c30 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -131,14 +131,11 @@
         public String text;
         public int requestorIdEncoding;
         public int textEncoding;
-        public Bundle extras;
     };
 
     public static class GpsNiResponse {
         /* User response, one of the values in GpsUserResponseType */
         int userResponse;
-        /* Optional extra data to pass with the user response */
-        Bundle extras;
     };
 
     private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index dd5f6ba..c1a178a 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.media.PlayerBase;
 import android.net.Uri;
 import android.os.PowerManager;
 import android.os.SystemClock;
@@ -163,6 +164,7 @@
      * @deprecated use {@link #play(Context, Uri, boolean, AudioAttributes)} instead
      */
     public void play(Context context, Uri uri, boolean looping, int stream) {
+        PlayerBase.deprecateStreamTypeForPlayback(stream, "AsyncPlayer", "play()");
         if (context == null || uri == null) {
             return;
         }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 43fb4b9..16b3315 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -359,6 +359,9 @@
      *   for an AudioTrack instance in streaming mode.
      * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
      * @throws java.lang.IllegalArgumentException
+     * @deprecated use {@link Builder} or
+     *   {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
+     *   {@link AudioAttributes} instead of the stream type which is only for volume control.
      */
     public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
             int bufferSizeInBytes, int mode)
@@ -414,6 +417,9 @@
      * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
      * @param sessionId Id of audio session the AudioTrack must be attached to
      * @throws java.lang.IllegalArgumentException
+     * @deprecated use {@link Builder} or
+     *   {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
+     *   {@link AudioAttributes} instead of the stream type which is only for volume control.
      */
     public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
             int bufferSizeInBytes, int mode, int sessionId)
@@ -429,6 +435,7 @@
                     .build(),
                 bufferSizeInBytes,
                 mode, sessionId);
+        deprecateStreamTypeForPlayback(streamType, "AudioTrack", "AudioTrack()");
     }
 
     /**
@@ -1044,11 +1051,12 @@
     }
 
     /**
-     * Returns the type of audio stream this AudioTrack is configured for.
+     * Returns the volume stream type of this AudioTrack.
      * Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
      * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
      * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
-     * {@link AudioManager#STREAM_NOTIFICATION}, or {@link AudioManager#STREAM_DTMF}.
+     * {@link AudioManager#STREAM_NOTIFICATION}, {@link AudioManager#STREAM_DTMF} or
+     * {@link AudioManager#STREAM_ACCESSIBILITY}.
      */
     public int getStreamType() {
         return mStreamType;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index eff5aac..78da59c 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -124,7 +124,7 @@
  *         is called. It is a programming error to invoke methods such
  *         as {@link #getCurrentPosition()},
  *         {@link #getDuration()}, {@link #getVideoHeight()},
- *         {@link #getVideoWidth()}, {@link #setAudioStreamType(int)},
+ *         {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)},
  *         {@link #setLooping(boolean)},
  *         {@link #setVolume(float, float)}, {@link #pause()}, {@link #start()},
  *         {@link #stop()}, {@link #seekTo(int, int)}, {@link #prepare()} or
@@ -410,7 +410,7 @@
  *          Error} </p></td>
  *     <td>This method must be called in idle state as the audio session ID must be known before
  *         calling setDataSource. Calling it does not change the object state. </p></td></tr>
- * <tr><td>setAudioStreamType </p></td>
+ * <tr><td>setAudioStreamType (deprecated)</p></td>
  *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
  *          PlaybackCompleted}</p></td>
  *     <td>{Error}</p></td>
@@ -822,7 +822,7 @@
      * to free the resources. If not released, too many MediaPlayer instances will
      * result in an exception.</p>
      * <p>Note that since {@link #prepare()} is called automatically in this method,
-     * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+     * you cannot change the audio
      * session ID (see {@link #setAudioSessionId(int)}) or audio attributes
      * (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
      *
@@ -841,7 +841,7 @@
      * to free the resources. If not released, too many MediaPlayer instances will
      * result in an exception.</p>
      * <p>Note that since {@link #prepare()} is called automatically in this method,
-     * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+     * you cannot change the audio
      * session ID (see {@link #setAudioSessionId(int)}) or audio attributes
      * (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
      *
@@ -904,7 +904,7 @@
      * to free the resources. If not released, too many MediaPlayer instances will
      * result in an exception.</p>
      * <p>Note that since {@link #prepare()} is called automatically in this method,
-     * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+     * you cannot change the audio
      * session ID (see {@link #setAudioSessionId(int)}) or audio attributes
      * (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
      *
@@ -1843,9 +1843,11 @@
      * thereafter.
      *
      * @param streamtype the audio stream type
+     * @deprecated use {@link #setAudioAttributes(AudioAttributes)}
      * @see android.media.AudioManager
      */
     public void setAudioStreamType(int streamtype) {
+        deprecateStreamTypeForPlayback(streamtype, "MediaPlayer", "setAudioStreamType()");
         baseUpdateAudioAttributes(
                 new AudioAttributes.Builder().setInternalLegacyStreamType(streamtype).build());
         _setAudioStreamType(streamtype);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 690a553..42f6b83 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -236,4 +236,28 @@
      */
     abstract void playerSetVolume(boolean muting, float leftVolume, float rightVolume);
     abstract int playerSetAuxEffectSendLevel(boolean muting, float level);
+
+    //=====================================================================
+    // Utilities
+
+    /**
+     * Use to generate warning or exception in legacy code paths that allowed passing stream types
+     * to qualify audio playback.
+     * @param streamType the stream type to check
+     * @throws IllegalArgumentException
+     */
+    public static void deprecateStreamTypeForPlayback(int streamType, String className,
+            String opName) throws IllegalArgumentException {
+        // STREAM_ACCESSIBILITY was introduced at the same time the use of stream types
+        // for audio playback was deprecated, so it is not allowed at all to qualify a playback
+        // use case
+        if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
+            throw new IllegalArgumentException("Use of STREAM_ACCESSIBILITY is reserved for "
+                    + "volume control");
+        }
+        Log.e(className, "Use of stream types is deprecated for operations other than " +
+                "volume control.");
+        Log.e(className, "See the documentation of " + opName + " for what to use instead with " +
+                "android.media.AudioAttributes to qualify your playback use case");
+    }
 }
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 7767712..209ec42 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -103,6 +103,7 @@
      */
     @Deprecated
     public void setStreamType(int streamType) {
+        PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", "setStreamType()");
         setAudioAttributes(new AudioAttributes.Builder()
                 .setInternalLegacyStreamType(streamType)
                 .build());
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 3cb01de..de9f020 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -297,7 +297,7 @@
     }
 
     /**
-     * Infers the playback stream type based on what type of ringtones this
+     * Infers the volume stream type based on what type of ringtones this
      * manager is returning.
      * 
      * @return The stream type.
@@ -616,6 +616,7 @@
         return getRingtone(context, ringtoneUri, -1);
     }
 
+    //FIXME bypass the notion of stream types within the class
     /**
      * Returns a {@link Ringtone} for a given sound URI on the given stream
      * type. Normally, if you change the stream type on the returned
@@ -630,6 +631,7 @@
         try {
             final Ringtone r = new Ringtone(context, true);
             if (streamType >= 0) {
+                //FIXME deprecated call
                 r.setStreamType(streamType);
             }
             r.setUri(ringtoneUri);
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index b429e22..838767c 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -24,6 +24,7 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
+import android.media.PlayerBase;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -146,6 +147,7 @@
     public SoundPool(int maxStreams, int streamType, int srcQuality) {
         this(maxStreams,
                 new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
+        PlayerBase.deprecateStreamTypeForPlayback(streamType, "SoundPool", "SoundPool()");
     }
 
     private SoundPool(int maxStreams, AudioAttributes attributes) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 7655e6c..790f3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -438,9 +438,9 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
         boolean screenPinningActive = ssp.isScreenPinningActive();
-        boolean isRunningTaskInHomeStack = runningTask != null &&
-                SystemServicesProxy.isHomeStack(runningTask.stackId);
-        if (runningTask != null && !isRunningTaskInHomeStack && !screenPinningActive) {
+        boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
+                ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
+        if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
             logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
             if (runningTask.isDockable) {
                 if (metricsDockAction != -1) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index abde44e..c9c4f2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -18,6 +18,8 @@
 
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.isHomeOrRecentsStack;
 import static android.view.View.MeasureSpec;
 
 import android.app.ActivityManager;
@@ -460,8 +462,8 @@
         // Return early if there is no running task (can't determine affiliated tasks in this case)
         ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
         if (runningTask == null) return;
-        // Return early if the running task is in the home stack (optimization)
-        if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;
+        // Return early if the running task is in the home/recents stack (optimization)
+        if (isHomeOrRecentsStack(runningTask.stackId)) return;
 
         // Find the task in the recents list
         ArrayList<Task> tasks = focusedStack.getStackTasks();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 2272a72..ea50d89 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -321,7 +321,7 @@
         // Remove home/recents/excluded tasks
         int minNumTasksToQuery = 10;
         int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
-        int flags = ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+        int flags = ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
                 ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK |
                 ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS |
                 ActivityManager.RECENT_IGNORE_UNAVAILABLE |
@@ -399,21 +399,23 @@
         if (mIam == null) return false;
 
         try {
-            ActivityManager.StackInfo stackInfo = mIam.getStackInfo(
+            ActivityManager.StackInfo homeStackInfo = mIam.getStackInfo(
                     ActivityManager.StackId.HOME_STACK_ID);
             ActivityManager.StackInfo fullscreenStackInfo = mIam.getStackInfo(
                     ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID);
-            ComponentName topActivity = stackInfo.topActivity;
-            boolean homeStackVisibleNotOccluded = stackInfo.visible;
-            if (fullscreenStackInfo != null) {
-                boolean isFullscreenStackOccludingHome = fullscreenStackInfo.visible &&
-                        fullscreenStackInfo.position > stackInfo.position;
-                homeStackVisibleNotOccluded &= !isFullscreenStackOccludingHome;
-            }
+            ActivityManager.StackInfo recentsStackInfo = mIam.getStackInfo(
+                    ActivityManager.StackId.RECENTS_STACK_ID);
+
+            boolean homeStackVisibleNotOccluded = isStackNotOccluded(homeStackInfo,
+                    fullscreenStackInfo);
+            boolean recentsStackVisibleNotOccluded = isStackNotOccluded(recentsStackInfo,
+                    fullscreenStackInfo);
             if (isHomeStackVisible != null) {
                 isHomeStackVisible.value = homeStackVisibleNotOccluded;
             }
-            return (homeStackVisibleNotOccluded && topActivity != null
+            ComponentName topActivity = recentsStackInfo != null ?
+                    recentsStackInfo.topActivity : null;
+            return (recentsStackVisibleNotOccluded && topActivity != null
                     && topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE)
                     && Recents.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
         } catch (RemoteException e) {
@@ -422,6 +424,17 @@
         return false;
     }
 
+    private boolean isStackNotOccluded(ActivityManager.StackInfo stackInfo,
+            ActivityManager.StackInfo fullscreenStackInfo) {
+        boolean stackVisibleNotOccluded = stackInfo == null || stackInfo.visible;
+        if (fullscreenStackInfo != null && stackInfo != null) {
+            boolean isFullscreenStackOccludingg = fullscreenStackInfo.visible &&
+                    fullscreenStackInfo.position > stackInfo.position;
+            stackVisibleNotOccluded &= !isFullscreenStackOccludingg;
+        }
+        return stackVisibleNotOccluded;
+    }
+
     /**
      * Returns whether this device has freeform workspaces.
      */
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 136e02c..7661127 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -75,6 +75,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
+import android.webkit.WebViewZygote;
 
 public final class ActiveServices {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
@@ -1704,6 +1705,7 @@
 
         final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
         final String procName = r.processName;
+        String hostingType = "service";
         ProcessRecord app;
 
         if (!isolated) {
@@ -1732,13 +1734,17 @@
             // in the service any current isolated process it is running in or
             // waiting to have come up.
             app = r.isolatedProc;
+            if (WebViewZygote.isMultiprocessEnabled()
+                    && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
+                hostingType = "webview_service";
+            }
         }
 
         // Not running -- get it started, and enqueue this service record
         // to be executed when the app comes up.
         if (app == null && !permissionsReviewRequired) {
             if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
-                    "service", r.name, false, isolated, false)) == null) {
+                    hostingType, r.name, false, isolated, false)) == null) {
                 String msg = "Unable to launch app "
                         + r.appInfo.packageName + "/"
                         + r.appInfo.uid + " for service "
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 229a68b..6aa0dc9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -272,6 +272,7 @@
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -362,7 +363,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
@@ -3695,10 +3695,18 @@
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                     app.processName);
             checkTime(startTime, "startProcess: asking zygote to start proc");
-            Process.ProcessStartResult startResult = Process.start(entryPoint,
-                    app.processName, uid, uid, gids, debugFlags, mountExternal,
-                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
-                    app.info.dataDir, entryPointArgs);
+            Process.ProcessStartResult startResult;
+            if (hostingType.equals("webview_service")) {
+                startResult = Process.startWebView(entryPoint,
+                        app.processName, uid, uid, gids, debugFlags, mountExternal,
+                        app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+                        app.info.dataDir, entryPointArgs);
+            } else {
+                startResult = Process.start(entryPoint,
+                        app.processName, uid, uid, gids, debugFlags, mountExternal,
+                        app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+                        app.info.dataDir, entryPointArgs);
+            }
             checkTime(startTime, "startProcess: returned from zygote!");
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
@@ -9183,10 +9191,10 @@
                         }
                     }
                     final ActivityStack stack = tr.getStack();
-                    if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
-                        if (stack != null && stack.isHomeStack()) {
+                    if ((flags & ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS) != 0) {
+                        if (stack != null && stack.isHomeOrRecentsStack()) {
                             if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
-                                    "Skipping, home stack task: " + tr);
+                                    "Skipping, home or recents stack task: " + tr);
                             continue;
                         }
                     }
@@ -9608,8 +9616,8 @@
     @Override
     public void removeStack(int stackId) {
         enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
-        if (stackId == HOME_STACK_ID) {
-            throw new IllegalArgumentException("Removing home stack is not allowed.");
+        if (StackId.isHomeOrRecentsStack(stackId)) {
+            throw new IllegalArgumentException("Removing home or recents stack is not allowed.");
         }
 
         synchronized (this) {
@@ -9837,9 +9845,9 @@
     @Override
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
-        if (stackId == HOME_STACK_ID) {
+        if (StackId.isHomeOrRecentsStack(stackId)) {
             throw new IllegalArgumentException(
-                    "moveTaskToStack: Attempt to move task " + taskId + " to home stack");
+                    "moveTaskToStack: Attempt to move task " + taskId + " to stack " + stackId);
         }
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
@@ -9854,8 +9862,7 @@
                         !FORCE_FOCUS, "moveTaskToStack", ANIMATE);
                 if (result && stackId == DOCKED_STACK_ID) {
                     // If task moved to docked stack - show recents if needed.
-                    mStackSupervisor.moveHomeStackTaskToTop(RECENTS_ACTIVITY_TYPE,
-                            "moveTaskToDockedStack");
+                    mWindowManager.showRecentApps(false /* fromHome */);
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -10039,10 +10046,10 @@
     @Override
     public void positionTaskInStack(int taskId, int stackId, int position) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
-        if (stackId == HOME_STACK_ID) {
+        if (StackId.isHomeOrRecentsStack(stackId)) {
             throw new IllegalArgumentException(
                     "positionTaskInStack: Attempt to change the position of task "
-                    + taskId + " in/to home stack");
+                    + taskId + " in/to home/recents stack");
         }
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
@@ -10084,22 +10091,6 @@
     }
 
     @Override
-    public boolean isInHomeStack(int taskId) {
-        enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (this) {
-                final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
-                        taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
-                final ActivityStack stack = tr != null ? tr.getStack() : null;
-                return stack != null && stack.isHomeStack();
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    @Override
     public int getTaskForActivity(IBinder token, boolean onlyRoot) {
         synchronized(this) {
             return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
@@ -18845,8 +18836,8 @@
     @Override
     public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
-        if (fromStackId == HOME_STACK_ID) {
-            throw new IllegalArgumentException("You can't move tasks from the home stack.");
+        if (StackId.isHomeOrRecentsStack(fromStackId)) {
+            throw new IllegalArgumentException("You can't move tasks from the home/recents stack.");
         }
         synchronized (this) {
             final long origId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index facfeb6..32dec96 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -5,6 +5,8 @@
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
@@ -78,7 +80,7 @@
         if (stack.mStackId == PINNED_STACK_ID) {
             stack = mSupervisor.findStackBehind(stack);
         }
-        if (stack.mStackId == HOME_STACK_ID
+        if (StackId.isHomeOrRecentsStack(stack.mStackId)
                 || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
             mWindowState = WINDOW_STATE_STANDARD;
         } else if (stack.mStackId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 214a357..d2a560f 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -19,7 +19,9 @@
 import static android.app.ActivityManager.StackId;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
@@ -1197,10 +1199,11 @@
         }
 
         final ActivityStack stack = getStack();
-        if (stack.isHomeStack()) {
+        if (stack.isHomeOrRecentsStack()) {
             // This is an optimization -- since we never show Home or Recents within Recents itself,
             // we can just go ahead and skip taking the screenshot if this is the home stack.
-            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tHome stack");
+            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, stack.getStackId() == HOME_STACK_ID ?
+                        "\tHome stack" : "\tRecents stack");
             return null;
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 005b8aa..b2adc73 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -22,6 +22,7 @@
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
@@ -690,6 +691,10 @@
         return mStackId == HOME_STACK_ID;
     }
 
+    final boolean isHomeOrRecentsStack() {
+        return StackId.isHomeOrRecentsStack(mStackId);
+    }
+
     final boolean isDockedStack() {
         return mStackId == DOCKED_STACK_ID;
     }
@@ -1450,10 +1455,10 @@
                     return false;
                 }
 
-                if (!isHomeStack() && r.frontOfTask
-                        && task.isOverHomeStack() && stackBehindId != HOME_STACK_ID) {
+                if (!isHomeOrRecentsStack() && r.frontOfTask
+                        && task.isOverHomeStack() && !StackId.isHomeOrRecentsStack(stackBehindId)) {
                     // Stack isn't translucent if it's top activity should have the home stack
-                    // behind it and the stack currently behind it isn't the home stack.
+                    // behind it and the stack currently behind it isn't the home or recents stack.
                     return false;
                 }
             }
@@ -1519,10 +1524,10 @@
         }
 
         if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID
-                && hasVisibleBehindActivity() && focusedStackId == HOME_STACK_ID
+                && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(focusedStackId)
                 && !focusedStack.topActivity().fullscreen) {
             // The fullscreen stack should be visible if it has a visible behind activity behind
-            // the home stack that is translucent.
+            // the home or recents stack that is translucent.
             return STACK_VISIBLE_ACTIVITY_BEHIND;
         }
 
@@ -1922,7 +1927,7 @@
                         + " behindFullscreenActivity=" + behindFullscreenActivity);
             // At this point, nothing else needs to be shown in this task.
             behindFullscreenActivity = true;
-        } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
+        } else if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()) {
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r
                     + " stackInvisible=" + stackInvisible
                     + " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2096,9 +2101,7 @@
         if (next == null) {
             // There are no more activities!
             final String reason = "noMoreActivities";
-            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack()
-                    ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
-            if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
+            if (!mFullscreen && adjustFocusToNextFocusableStackLocked(reason)) {
                 // Try to move focus to the next visible stack with a running activity if this
                 // stack is not covering the entire screen.
                 return mStackSupervisor.resumeFocusedStackTopActivityLocked(
@@ -2112,7 +2115,7 @@
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
             // Only resume home if on home display
             return isOnHomeDisplay() &&
-                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
+                    mStackSupervisor.resumeHomeStackTask(prev, reason);
         }
 
         next.delayedResume = false;
@@ -2147,10 +2150,8 @@
             } else if (!isHomeStack()){
                 if (DEBUG_STATES) Slog.d(TAG_STATES,
                         "resumeTopActivityLocked: Launching home next");
-                final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
-                        HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
                 return isOnHomeDisplay() &&
-                        mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
+                        mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
             }
         }
 
@@ -2567,7 +2568,7 @@
         // activity, set mTaskToReturnTo accordingly.
         if (isOnHomeDisplay()) {
             ActivityStack lastStack = mStackSupervisor.getLastStack();
-            final boolean fromHome = lastStack.isHomeStack();
+            final boolean fromHomeOrRecents = lastStack.isHomeOrRecentsStack();
             final boolean fromOnTopLauncher = lastStack.topTask() != null &&
                     lastStack.topTask().isOnTopLauncher();
             if (fromOnTopLauncher) {
@@ -2576,12 +2577,12 @@
                 // This also makes sure that non-home activities are visible under a transparent
                 // non-home activity.
                 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
-            } else if (!isHomeStack() && (fromHome || topTask() != task)) {
+            } else if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
                 // If it's a last task over home - we default to keep its return to type not to
                 // make underlying task focused when this one will be finished.
                 int returnToType = isLastTaskOverHome
                         ? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
-                if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
+                if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
                     returnToType = lastStack.topTask() == null
                             ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
                 }
@@ -2675,7 +2676,7 @@
         task.setFrontOfTask();
 
         r.putInHistory();
-        if (!isHomeStack() || numActivities() > 0) {
+        if (!isHomeOrRecentsStack() || numActivities() > 0) {
             // We want to show the starting preview window if we are
             // switching to a new task, or the next activity's process is
             // not currently running.
@@ -3114,18 +3115,16 @@
             } else {
                 final TaskRecord task = r.task;
                 if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
-                    final int taskToReturnTo = task.getTaskToReturnTo();
-
                     // For non-fullscreen stack, we want to move the focus to the next visible
                     // stack to prevent the home screen from moving to the top and obscuring
                     // other visible stacks.
                     if (!mFullscreen
-                            && adjustFocusToNextFocusableStackLocked(taskToReturnTo, myReason)) {
+                            && adjustFocusToNextFocusableStackLocked(myReason)) {
                         return;
                     }
                     // Move the home stack to the top if this stack is fullscreen or there is no
                     // other visible stack.
-                    if (mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, myReason)) {
+                    if (mStackSupervisor.moveHomeStackTaskToTop(myReason)) {
                         // Activity focus was already adjusted. Nothing else to do...
                         return;
                     }
@@ -3137,7 +3136,7 @@
                 mStackSupervisor.topRunningActivityLocked(), myReason);
     }
 
-    private boolean adjustFocusToNextFocusableStackLocked(int taskToReturnTo, String reason) {
+    private boolean adjustFocusToNextFocusableStackLocked(String reason) {
         final ActivityStack stack = getNextFocusableStackLocked();
         final String myReason = reason + " adjustFocusToNextFocusableStack";
         if (stack == null) {
@@ -3146,10 +3145,10 @@
 
         final ActivityRecord top = stack.topRunningActivityLocked();
 
-        if (stack.isHomeStack() && (top == null || !top.visible)) {
+        if (stack.isHomeOrRecentsStack() && (top == null || !top.visible)) {
             // If we will be focusing on the home stack next and its current top activity isn't
             // visible, then use the task return to value to determine the home task to display next.
-            return mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, reason);
+            return mStackSupervisor.moveHomeStackTaskToTop(reason);
         }
 
         stack.moveToFront(myReason);
@@ -3754,7 +3753,7 @@
                     "removeActivityFromHistoryLocked: last activity removed from " + this);
             if (mStackSupervisor.isFocusedStack(this) && task == topTask() &&
                     task.isOverHomeStack()) {
-                mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
+                mStackSupervisor.moveHomeStackTaskToTop(reason);
             }
             removeTask(task, reason);
         }
@@ -4176,11 +4175,11 @@
         mStackSupervisor.invalidateTaskLayers();
     }
 
-    void moveHomeStackTaskToTop(int homeStackTaskType) {
+    void moveHomeStackTaskToTop() {
         final int top = mTaskHistory.size() - 1;
         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            if (task.taskType == homeStackTaskType) {
+            if (task.taskType == HOME_ACTIVITY_TYPE) {
                 if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
                         "moveHomeStackTaskToTop: moving " + task);
                 mTaskHistory.remove(taskNdx);
@@ -4306,7 +4305,7 @@
                 moveToBack(topTask());
 
                 // Resume an activity in the next focusable stack.
-                adjustFocusToNextFocusableStackLocked(APPLICATION_ACTIVITY_TYPE, "moveTaskToBack");
+                adjustFocusToNextFocusableStackLocked("moveTaskToBack");
                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
                 return true;
             }
@@ -4365,9 +4364,8 @@
                 // Not ready yet!
                 return false;
             }
-            final int taskToReturnTo = tr.getTaskToReturnTo();
             tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
-            return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack");
+            return mStackSupervisor.resumeHomeStackTask(null, "moveTaskToBack");
         }
 
         mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -4840,9 +4838,7 @@
             if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
                     && mStackSupervisor.isFocusedStack(this)) {
                 String myReason = reason + " leftTaskHistoryEmpty";
-                if (mFullscreen
-                        || !adjustFocusToNextFocusableStackLocked(
-                        task.getTaskToReturnTo(), myReason)) {
+                if (mFullscreen || !adjustFocusToNextFocusableStackLocked(myReason)) {
                     mStackSupervisor.moveHomeStackToFront(myReason);
                 }
             }
@@ -4850,7 +4846,7 @@
                 mStacks.remove(this);
                 mStacks.add(0, this);
             }
-            if (!isHomeStack()) {
+            if (!isHomeOrRecentsStack()) {
                 mActivityContainer.onTaskListEmptyLocked();
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 48108fe..e3212c2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -33,6 +33,7 @@
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -72,7 +73,6 @@
 import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
@@ -661,13 +661,8 @@
     }
 
     /** Returns true if the focus activity was adjusted to the home stack top activity. */
-    boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
-        if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
-            mWindowManager.showRecentApps(false /* fromHome */);
-            return false;
-        }
-
-        mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
+    boolean moveHomeStackTaskToTop(String reason) {
+        mHomeStack.moveHomeStackTaskToTop();
 
         final ActivityRecord top = getHomeActivity();
         if (top == null) {
@@ -677,22 +672,17 @@
         return true;
     }
 
-    boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
+    boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
         if (!mService.mBooting && !mService.mBooted) {
             // Not ready yet!
             return false;
         }
 
-        if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
-            mWindowManager.showRecentApps(false /* fromHome */);
-            return false;
-        }
-
         if (prev != null) {
             prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
         }
 
-        mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
+        mHomeStack.moveHomeStackTaskToTop();
         ActivityRecord r = getHomeActivity();
         final String myReason = reason + " resumeHomeStackTask";
 
@@ -2754,7 +2744,7 @@
             final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
-                if (!r.isApplicationActivity() && !stack.isHomeStack()) {
+                if (!r.isApplicationActivity() && !stack.isHomeOrRecentsStack()) {
                     if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (home activity) " + stack);
                     continue;
                 }
@@ -3178,7 +3168,7 @@
             stack.moveToFront("switchUserOnHomeDisplay");
         } else {
             // Stack was moved to another display while user was swapped out.
-            resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
+            resumeHomeStackTask(null, "switchUserOnOtherDisplay");
         }
         return homeInFront;
     }
@@ -4597,9 +4587,9 @@
                 ? new ActivityOptions(bOptions) : null;
         final int launchStackId = (activityOptions != null)
                 ? activityOptions.getLaunchStackId() : INVALID_STACK_ID;
-        if (launchStackId == HOME_STACK_ID) {
+        if (StackId.isHomeOrRecentsStack(launchStackId)) {
             throw new IllegalArgumentException("startActivityFromRecentsInner: Task "
-                    + taskId + " can't be launch in the home stack.");
+                    + taskId + " can't be launch in the home/recents stack.");
         }
 
         if (launchStackId == DOCKED_STACK_ID) {
@@ -4609,13 +4599,13 @@
             // Defer updating the stack in which recents is until the app transition is done, to
             // not run into issues where we still need to draw the task in recents but the
             // docked stack is already created.
-            deferUpdateBounds(HOME_STACK_ID);
+            deferUpdateBounds(RECENTS_STACK_ID);
             mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false);
         }
 
         task = anyTaskForIdLocked(taskId, RESTORE_FROM_RECENTS, launchStackId);
         if (task == null) {
-            continueUpdateBounds(HOME_STACK_ID);
+            continueUpdateBounds(RECENTS_STACK_ID);
             mWindowManager.executeAppTransition();
             throw new IllegalArgumentException(
                     "startActivityFromRecentsInner: Task " + taskId + " not found.");
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index dff7cef..64bf3ad 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -32,6 +32,7 @@
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.isStaticStack;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -589,7 +590,7 @@
     }
 
     void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
-        mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
+        mSupervisor.moveHomeStackTaskToTop(reason);
         startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
                 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
                 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
@@ -1524,8 +1525,8 @@
 
     private void updateTaskReturnToType(
             TaskRecord task, int launchFlags, ActivityStack focusedStack) {
-        if (focusedStack != null && focusedStack.isHomeStack() && focusedStack.topTask() != null
-                && focusedStack.topTask().isOnTopLauncher()) {
+        if (focusedStack != null && focusedStack.isHomeOrRecentsStack()
+                && focusedStack.topTask() != null && focusedStack.topTask().isOnTopLauncher()) {
             // Since an on-top launcher will is moved to back when tasks are launched from it,
             // those tasks should first try to return to a non-home activity.
             // This also makes sure that non-home activities are visible under a transparent
@@ -1869,7 +1870,10 @@
     private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
             int launchFlags, ActivityOptions aOptions) {
         final TaskRecord task = r.task;
-        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
+        if (r.isRecentsActivity()) {
+            return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
+        }
+        if (r.isHomeActivity()) {
             return mSupervisor.mHomeStack;
         }
 
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index bc9bda2f..6a13d36 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -130,8 +130,8 @@
 
     void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
         final ActivityStack stack = task != null ? task.getStack() : null;
-        if (stack != null && stack.isHomeStack()) {
-            // Never persist the home stack.
+        if (stack != null && stack.isHomeOrRecentsStack()) {
+            // Never persist the home or recents stack.
             return;
         }
         syncPersistentTaskIdsLocked();
@@ -150,7 +150,7 @@
         for (int i = size() - 1; i >= 0; i--) {
             final TaskRecord task = get(i);
             final ActivityStack stack = task.getStack();
-            if (task.isPersistable && (stack == null || !stack.isHomeStack())) {
+            if (task.isPersistable && (stack == null || !stack.isHomeOrRecentsStack())) {
                 // Set of persisted taskIds for task.userId should not be null here
                 // TODO Investigate why it can happen. For now initialize with an empty set
                 if (mPersistedTaskIds.get(task.userId) == null) {
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 1ecb2e9..7a62f2c 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -643,7 +643,7 @@
                                     " persistable=" + task.isPersistable);
                             final ActivityStack stack = task.getStack();
                             if ((task.isPersistable || task.inRecents)
-                                    && (stack == null || !stack.isHomeStack())) {
+                                    && (stack == null || !stack.isHomeOrRecentsStack())) {
                                 if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
                                 persistentTaskIds.add(task.taskId);
                             } else {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0bc12ee..5c352e1 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -64,6 +64,7 @@
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
@@ -1068,7 +1069,7 @@
     }
 
     boolean isOverHomeStack() {
-        return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE;
+        return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
     }
 
     boolean isResizeable() {
@@ -1685,7 +1686,10 @@
      * The task will be moved (and stack focus changed) later if necessary.
      */
     int getLaunchStackId() {
-        if (!isApplicationTask()) {
+        if (isRecentsTask()) {
+            return RECENTS_STACK_ID;
+        }
+        if (isHomeTask()) {
             return HOME_STACK_ID;
         }
         if (mBounds != null) {
@@ -1707,6 +1711,7 @@
 
         final int stackId = mStack.mStackId;
         if (stackId == HOME_STACK_ID
+                || stackId == RECENTS_STACK_ID
                 || stackId == FULLSCREEN_WORKSPACE_STACK_ID
                 || (stackId == DOCKED_STACK_ID && !isResizeable())) {
             return isResizeable() ? mStack.mBounds : null;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 45f54a9..54366e6 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -95,7 +95,8 @@
 import java.util.Date;
 import java.util.Map.Entry;
 import java.util.Properties;
-
+import java.util.Map;
+import java.util.HashMap;
 import libcore.io.IoUtils;
 
 /**
@@ -211,24 +212,18 @@
     private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
     private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
 
-    // Request ref location
-    private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
-    private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
+    //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
+    private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
 
     // ref. location info
     private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
     private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
-    private static final int AGPS_REG_LOCATION_TYPE_MAC        = 3;
 
     // set id info
     private static final int AGPS_SETID_TYPE_NONE = 0;
     private static final int AGPS_SETID_TYPE_IMSI = 1;
     private static final int AGPS_SETID_TYPE_MSISDN = 2;
 
-    private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
-    private static final String PROPERTIES_FILE_SUFFIX = ".conf";
-    private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
-
     private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
     private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
 
@@ -501,10 +496,6 @@
                 startNavigating(false);
             } else if (action.equals(ALARM_TIMEOUT)) {
                 hibernate();
-            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
-                checkSmsSuplInit(intent);
-            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
-                checkWapSuplInit(intent);
             } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
                     || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
                     || Intent.ACTION_SCREEN_OFF.equals(action)
@@ -557,31 +548,6 @@
         }
     }
 
-    private void checkSmsSuplInit(Intent intent) {
-        SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
-        if (messages == null) {
-            Log.e(TAG, "Message does not exist in the intent.");
-            return;
-        }
-
-        for (SmsMessage message : messages) {
-            if (message != null && message.mWrappedSmsMessage != null) {
-                byte[] suplInit = message.getUserData();
-                if (suplInit != null) {
-                    native_agps_ni_message(suplInit, suplInit.length);
-                }
-            }
-        }
-    }
-
-    private void checkWapSuplInit(Intent intent) {
-        byte[] suplInit = intent.getByteArrayExtra("data");
-        if (suplInit == null) {
-            return;
-        }
-        native_agps_ni_message(suplInit,suplInit.length);
-    }
-
     private void updateLowPowerMode() {
         // Disable GPS if we are in device idle mode.
         boolean disableGps = mPowerManager.isDeviceIdleMode();
@@ -602,23 +568,14 @@
         return native_is_supported();
     }
 
+    interface SetCarrierProperty {
+        public boolean set(int value);
+    }
+
     private void reloadGpsProperties(Context context, Properties properties) {
         if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
         loadPropertiesFromResource(context, properties);
 
-        boolean isPropertiesLoadedFromFile = false;
-        final String gpsHardware = SystemProperties.get("ro.hardware.gps");
-
-        if (!TextUtils.isEmpty(gpsHardware)) {
-            final String propFilename =
-                    PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
-            isPropertiesLoadedFromFile =
-                    loadPropertiesFromFile(propFilename, properties);
-        }
-        if (!isPropertiesLoadedFromFile) {
-            loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
-        }
-        if (DEBUG) Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
         String lpp_prof = SystemProperties.get(LPP_PROFILE);
         if (!TextUtils.isEmpty(lpp_prof)) {
                 // override default value of this if lpp_prof is not empty
@@ -636,16 +593,37 @@
                 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
             }
         }
-
+        /*
+         * Allow carrier properties to be loaded from a  debug configuration file.
+         */
+        loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
         if (native_is_gnss_configuration_supported()) {
-            try {
-                // Convert properties to string contents and send it to HAL.
-                ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
-                properties.store(baos, null);
-                native_configuration_update(baos.toString());
-                if (DEBUG) Log.d(TAG, "final config = " + baos.toString());
-            } catch (IOException ex) {
-                Log.e(TAG, "failed to dump properties contents");
+            Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
+                {
+                    put("SUPL_VER", (val) -> native_set_supl_version(val));
+                    put("SUPL_MODE", (val) -> native_set_supl_mode(val));
+                    put("SUPL_ES", (val) -> native_set_supl_es(val));
+                    put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
+                    put("A_GLONASS_POS_PROTOCOL_SELECT", (val) -> native_set_gnss_pos_protocol_select(val));
+                    put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", (val) -> native_set_emergency_supl_pdn(val));
+                    put("GPS_LOCK", (val) -> native_set_gps_lock(val));
+                }
+            };
+
+            for(Entry<String, SetCarrierProperty> entry : map.entrySet()) {
+                String propertyName = entry.getKey();
+                String propertyValueString = properties.getProperty(propertyName);
+                if (propertyValueString != null) {
+                    try {
+                          int propertyValueInt = Integer.decode(propertyValueString);
+                          boolean result = entry.getValue().set(propertyValueInt);
+                          if (result == false) {
+                              Log.e(TAG, "Unable to set " + propertyName);
+                          }
+                    } catch (NumberFormatException e) {
+                          Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
+                    }
+                }
             }
         } else if (DEBUG) {
             Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
@@ -692,7 +670,7 @@
             }
 
         } catch (IOException e) {
-            Log.w(TAG, "Could not open GPS configuration file " + filename);
+            Log.v(TAG, "Could not open GPS configuration file " + filename);
             return false;
         }
         return true;
@@ -1973,8 +1951,7 @@
             String requestorId,
             String text,
             int requestorIdEncoding,
-            int textEncoding,
-            String extras  // Encoded extra data
+            int textEncoding
         )
     {
         Log.i(TAG, "reportNiNotification: entered");
@@ -2003,28 +1980,6 @@
         notification.requestorIdEncoding = requestorIdEncoding;
         notification.textEncoding = textEncoding;
 
-        // Process extras, assuming the format is
-        // one of more lines of "key = value"
-        Bundle bundle = new Bundle();
-
-        if (extras == null) extras = "";
-        Properties extraProp = new Properties();
-
-        try {
-            extraProp.load(new StringReader(extras));
-        }
-        catch (IOException e)
-        {
-            Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
-        }
-
-        for (Entry<Object, Object> ent : extraProp.entrySet())
-        {
-            bundle.putString((String) ent.getKey(), (String) ent.getValue());
-        }
-
-        notification.extras = bundle;
-
         mNIHandler.handleNiNotification(notification);
     }
 
@@ -2075,7 +2030,7 @@
      * Called from native code to request reference location info
      */
 
-    private void requestRefLocation(int flags) {
+    private void requestRefLocation() {
         TelephonyManager phone = (TelephonyManager)
                 mContext.getSystemService(Context.TELEPHONY_SERVICE);
         final int phoneType = phone.getPhoneType();
@@ -2547,5 +2502,12 @@
     private native boolean native_stop_navigation_message_collection();
 
     // GNSS Configuration
-    private static native void native_configuration_update(String configData);
+    private static native boolean native_set_supl_version(int version);
+    private static native boolean native_set_supl_mode(int mode);
+    private static native boolean native_set_supl_es(int es);
+    private static native boolean native_set_lpp_profile(int lppProfile);
+    private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
+    private static native boolean native_set_gps_lock(int gpsLock);
+    private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
+
 }
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 9740935..d8fd6e2 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -74,7 +74,7 @@
         try {
             List<ActivityManager.RecentTaskInfo> tasks =
                     ActivityManager.getService().getRecentTasks(1,
-                            ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+                            ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
                             ActivityManager.RECENT_IGNORE_UNAVAILABLE |
                             ActivityManager.RECENT_INCLUDE_PROFILES |
                             ActivityManager.RECENT_WITH_EXCLUDED, record.getUserId()).getList();
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fd2b504..7938a12 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -51,9 +51,11 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.PrintWriterPrinter;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.SizedInputStream;
+import com.android.server.SystemConfig;
 
 import dalvik.system.DexFile;
 
@@ -135,6 +137,8 @@
                     return runSuspend(false);
                 case "set-home-activity":
                     return runSetHomeActivity();
+                case "get-privapp-permissions":
+                    return runGetPrivappPermissions();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -1164,6 +1168,18 @@
         }
     }
 
+    private int runGetPrivappPermissions() {
+        final String pkg = getNextArg();
+        if (pkg == null) {
+            System.err.println("Error: no package specified.");
+            return 1;
+        }
+        ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+        getOutPrintWriter().println(privAppPermissions == null
+                ? "{}" : privAppPermissions.toString());
+        return 0;
+    }
+
     private static String checkAbiArgument(String abi) {
         if (TextUtils.isEmpty(abi)) {
             throw new IllegalArgumentException("Missing ABI argument");
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d558b07..2eb0778 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -259,6 +259,11 @@
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
 
+            if (si.isFloating()) {
+                si.setRank(0);
+                si.setActivity(null);
+            }
+
             if (si.isAlive()) continue;
 
             if (removeList == null) {
@@ -288,6 +293,7 @@
                 si.setTimestamp(now);
                 si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
                 si.setRank(0); // It may still be pinned, so clear the rank.
+                si.setActivity(null);
             }
         }
         if (changed) {
@@ -355,6 +361,7 @@
         if (oldShortcut.isPinned()) {
 
             oldShortcut.setRank(0);
+            oldShortcut.setActivity(null);
             oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
             if (disable) {
                 oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
@@ -595,6 +602,10 @@
 
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
+
+            if (si.isFloating()) {
+                continue; // Ignore floating shortcuts, which are not tied to any activities.
+            }
             final ComponentName activity = si.getActivity();
 
             if (checked.contains(activity)) {
@@ -1356,6 +1367,10 @@
                     case TAG_SHORTCUT:
                         final ShortcutInfo si = parseShortcut(parser, packageName,
                                 shortcutUser.getUserId());
+                        // Floating shortcut used to have target activities, but not anymore.
+                        if (si.isFloating()) { // Not really needed by just in case.
+                            si.setActivity(null);
+                        }
 
                         // Don't use addShortcut(), we don't need to save the icon.
                         ret.mShortcuts.put(si.getId(), si);
@@ -1462,7 +1477,6 @@
             intents.clear();
             intents.add(intentLegacy);
         }
-
         return new ShortcutInfo(
                 userId, id, packageName, activityComponent, /* icon =*/ null,
                 title, titleResId, titleResName, text, textResId, textResName,
@@ -1553,12 +1567,17 @@
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is both dynamic and manifest at the same time.");
             }
-            if (si.getActivity() == null) {
+            if (!si.isFloating() && si.getActivity() == null) {
                 failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
-                        + " has null activity.");
+                        + " is not floating, but has null activity.");
             }
-            if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
+            if (si.isFloating() && si.getActivity() != null) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " is floating, but has non-null activity.");
+            }
+            if (!si.isFloating() && !si.isEnabled()) {
                 failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is not floating, but is disabled.");
@@ -1581,7 +1600,7 @@
         }
 
         if (failed) {
-            throw new IllegalStateException("See logcat for errors");
+            mShortcutUser.mService.verifyError();
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 16f209b..c5c1c0c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -124,6 +124,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -401,6 +402,9 @@
 
     @VisibleForTesting
     ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) {
+        if (DEBUG) {
+            Binder.LOG_RUNTIME_EXCEPTION = true;
+        }
         mContext = Preconditions.checkNotNull(context);
         LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
         mHandler = new Handler(looper);
@@ -1604,7 +1608,7 @@
         }
 
         if (!forUpdate) {
-            shortcut.enforceMandatoryFields();
+            shortcut.enforceMandatoryFields(/* forPinned= */ false);
             Preconditions.checkArgument(
                     injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()),
                     "Cannot publish shortcut: " + shortcut.getActivity() + " is not main activity");
@@ -1752,6 +1756,9 @@
 
                 // Note copyNonNullFieldsFrom() does the "updatable with?" check too.
                 target.copyNonNullFieldsFrom(source);
+                if (target.isFloating()) {
+                    target.setActivity(null);
+                }
                 target.setTimestamp(injectCurrentTimeMillis());
 
                 if (replacingIcon) {
@@ -2320,8 +2327,7 @@
                             return false;
                         }
                         if (componentName != null) {
-                            if (si.getActivity() != null
-                                    && !si.getActivity().equals(componentName)) {
+                            if (!Objects.equals(componentName, si.getActivity())) {
                                 return false;
                             }
                         }
@@ -3771,4 +3777,8 @@
             forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
         }
     }
+
+    void verifyError() {
+        Slog.e(TAG, "See logcat for errors");
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DragResizeMode.java b/services/core/java/com/android/server/wm/DragResizeMode.java
index 08acf9d..8ab0406 100644
--- a/services/core/java/com/android/server/wm/DragResizeMode.java
+++ b/services/core/java/com/android/server/wm/DragResizeMode.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 
 /**
  * Describes the mode in which a window is drag resizing.
@@ -45,7 +46,8 @@
             case DRAG_RESIZE_MODE_DOCKED_DIVIDER:
                 return stackId == DOCKED_STACK_ID
                         || stackId == FULLSCREEN_WORKSPACE_STACK_ID
-                        || stackId == HOME_STACK_ID;
+                        || stackId == HOME_STACK_ID
+                        || stackId == RECENTS_STACK_ID;
             default:
                 return false;
         }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b889db2..d33ae48 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -19,7 +19,7 @@
 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -526,10 +526,6 @@
         return (tokensCount != 0) && mChildren.get(tokensCount - 1).showForAllUsers;
     }
 
-    boolean inHomeStack() {
-        return mStack != null && mStack.mStackId == HOME_STACK_ID;
-    }
-
     boolean inFreeformWorkspace() {
         return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
     }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 203ba72..a90b615 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1183,7 +1183,7 @@
 
     @Override
     public boolean dimFullscreen() {
-        return mStackId == HOME_STACK_ID || fillsParent();
+        return StackId.isHomeOrRecentsStack(mStackId) || fillsParent();
     }
 
     @Override
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index ac0e622..50a6095 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -73,6 +73,7 @@
     libhwbinder \
     libutils \
     android.hardware.audio.common@2.0 \
+    android.hardware.gnss@1.0 \
     android.hardware.light@2.0 \
     android.hardware.power@1.0 \
     android.hardware.thermal@1.0 \
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 25e819c..b0a4297 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -18,10 +18,13 @@
 
 #define LOG_NDEBUG 0
 
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+
 #include "JNIHelp.h"
 #include "jni.h"
-#include "hardware/hardware.h"
-#include "hardware/gps_internal.h"
 #include "hardware_legacy/power.h"
 #include "utils/Log.h"
 #include "utils/misc.h"
@@ -34,6 +37,7 @@
 #include <linux/in6.h>
 #include <pthread.h>
 #include <string.h>
+#include <cinttypes>
 
 static jobject mCallbacksObj = NULL;
 
@@ -58,978 +62,65 @@
 static jmethodID method_reportMeasurementData;
 static jmethodID method_reportNavigationMessages;
 
-static const GpsInterface* sGpsInterface = NULL;
-static const GpsXtraInterface* sGpsXtraInterface = NULL;
-static const AGpsInterface* sAGpsInterface = NULL;
-static const GpsNiInterface* sGpsNiInterface = NULL;
-static const GpsDebugInterface* sGpsDebugInterface = NULL;
-static const AGpsRilInterface* sAGpsRilInterface = NULL;
-static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
-static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
-static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
-static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::String16;
 
-#define GPS_MAX_SATELLITE_COUNT 32
-#define GNSS_MAX_SATELLITE_COUNT 64
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::hidl_vec;
 
-// Let these through, with ID remapped down to 1, 2... by offset
-#define GLONASS_SVID_OFFSET 64
-#define GLONASS_SVID_COUNT 24
-#define BEIDOU_SVID_OFFSET 200
-#define BEIDOU_SVID_COUNT 35
+using android::hardware::gnss::V1_0::IAGnss;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssRil;
+using android::hardware::gnss::V1_0::IAGnssRilCallback;
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::gnss::V1_0::IGnssCallback;
+using android::hardware::gnss::V1_0::IGnssConfiguration;
+using android::hardware::gnss::V1_0::IGnssDebug;
+using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using android::hardware::gnss::V1_0::IGnssGeofencing;
+using android::hardware::gnss::V1_0::IGnssMeasurement;
+using android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::V1_0::IGnssNiCallback;
+using android::hardware::gnss::V1_0::IGnssXtra;
+using android::hardware::gnss::V1_0::IGnssXtraCallback;
 
-// Let these through, with ID remapped up (33->120 ... 64->151, etc.)
-#define SBAS_SVID_MIN 33
-#define SBAS_SVID_MAX 64
-#define SBAS_SVID_ADD 87
 
-// Let these through, with no ID remapping
-#define QZSS_SVID_MIN 193
-#define QZSS_SVID_MAX 200
-
-#define SVID_SHIFT_WIDTH 7
-#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
-
-// temporary storage for GPS callbacks
-static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
-static size_t sGnssSvListSize;
-static const char* sNmeaString;
-static int sNmeaStringLength;
+sp<IGnss> gnssHal = nullptr;
+sp<IGnssXtra> gnssXtraIface = nullptr;
+sp<IAGnssRil> agnssRilIface = nullptr;
+sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
+sp<IAGnss> agnssIface = nullptr;
+sp<IGnssDebug> gnssDebugIface = nullptr;
+sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
+sp<IGnssNi> gnssNiIface = nullptr;
+sp<IGnssMeasurement> gnssMeasurementIface = nullptr;
+sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
 
 namespace android {
 
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-static void location_callback(GpsLocation* location)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
-            (jdouble)location->latitude, (jdouble)location->longitude,
-            (jdouble)location->altitude,
-            (jfloat)location->speed, (jfloat)location->bearing,
-            (jfloat)location->accuracy, (jlong)location->timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void status_callback(GpsStatus* status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void sv_status_callback(GpsSvStatus* sv_status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    size_t status_size = sv_status->size;
-    // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
-    // if it doesn't provide a valid size.
-    if (status_size == 0) {
-        ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
-    }
-    sGnssSvListSize = sv_status->num_svs;
-    // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
-    if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
-        ALOGW("Too many satellites %zd. Clamps to %d.",
-              sGnssSvListSize,
-              GPS_MAX_SATELLITE_COUNT);
-        sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
-    }
-    uint32_t ephemeris_mask = sv_status->ephemeris_mask;
-    uint32_t almanac_mask = sv_status->almanac_mask;
-    uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
-    for (size_t i = 0; i < sGnssSvListSize; i++) {
-        GnssSvInfo& info = sGnssSvList[i];
-        info.svid = sv_status->sv_list[i].prn;
-        // Defacto mapping from the overused API that was designed for GPS-only
-        if (info.svid >=1 && info.svid <= 32) {
-            info.constellation = GNSS_CONSTELLATION_GPS;
-        } else if (info.svid > GLONASS_SVID_OFFSET &&
-                   info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
-            info.constellation = GNSS_CONSTELLATION_GLONASS;
-            info.svid -= GLONASS_SVID_OFFSET;
-        } else if (info.svid > BEIDOU_SVID_OFFSET &&
-                   info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
-            info.constellation = GNSS_CONSTELLATION_BEIDOU;
-            info.svid -= BEIDOU_SVID_OFFSET;
-        } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
-            info.constellation = GNSS_CONSTELLATION_SBAS;
-            info.svid += SBAS_SVID_ADD;
-        } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
-            info.constellation = GNSS_CONSTELLATION_QZSS;
-        } else {
-            ALOGD("Unknown constellation type with Svid = %d.", info.svid);
-            info.constellation = GNSS_CONSTELLATION_UNKNOWN;
-        }
-        info.c_n0_dbhz = sv_status->sv_list[i].snr;
-        info.elevation = sv_status->sv_list[i].elevation;
-        info.azimuth = sv_status->sv_list[i].azimuth;
-        info.flags = GNSS_SV_FLAGS_NONE;
-        // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
-        if (info.constellation == GNSS_CONSTELLATION_GPS) {
-            int32_t this_svid_mask = (1 << (info.svid - 1));
-            if ((ephemeris_mask & this_svid_mask) != 0) {
-                info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
-            }
-            if ((almanac_mask & this_svid_mask) != 0) {
-                info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
-            }
-            if ((used_in_fix_mask & this_svid_mask) != 0) {
-                info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
-            }
-        }
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    size_t status_size = sv_status->size;
-    // Check the size, and reject the object that has invalid size.
-    if (status_size != sizeof(GnssSvStatus)) {
-        ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
-        return;
-    }
-    sGnssSvListSize = sv_status->num_svs;
-    // Clamp the list size
-    if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
-        ALOGD("Too many satellites %zd. Clamps to %d.",
-              sGnssSvListSize,
-              GNSS_MAX_SATELLITE_COUNT);
-        sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
-    }
-    // Copy GNSS SV info into sGnssSvList, if any.
-    if (sGnssSvListSize > 0) {
-        memcpy(sGnssSvList,
-               sv_status->gnss_sv_list,
-               sizeof(GnssSvInfo) * sGnssSvListSize);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    // The Java code will call back to read these values
-    // We do this to avoid creating unnecessary String objects
-    sNmeaString = nmea;
-    sNmeaStringLength = length;
-    env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_system_info_callback(const GnssSystemInfo* info) {
-    ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
-                        info->year_of_hw);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_capabilities_callback(uint32_t capabilities)
-{
-    ALOGD("set_capabilities_callback: %du\n", capabilities);
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void acquire_wakelock_callback()
-{
-    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
-}
-
-static void release_wakelock_callback()
-{
-    release_wake_lock(WAKE_LOCK_NAME);
-}
-
-static void request_utc_time_callback()
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
-{
-    return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
-}
-
-GpsCallbacks sGpsCallbacks = {
-    sizeof(GpsCallbacks),
-    location_callback,
-    status_callback,
-    sv_status_callback,
-    nmea_callback,
-    set_capabilities_callback,
-    acquire_wakelock_callback,
-    release_wakelock_callback,
-    create_thread_callback,
-    request_utc_time_callback,
-    set_system_info_callback,
-    gnss_sv_status_callback,
-};
-
-static void xtra_download_request_callback()
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsXtraCallbacks sGpsXtraCallbacks = {
-    xtra_download_request_callback,
-    create_thread_callback,
-};
-
-static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
-{
-    if (INADDR_NONE == ip) {
-        return NULL;
-    }
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jbyteArray byteArray = env->NewByteArray(4);
-    if (byteArray == NULL) {
-        ALOGE("Unable to allocate byte array for IPv4 address");
-        return NULL;
-    }
-
-    jbyte ipv4[4];
-    if (net_order) {
-        ALOGV("Converting IPv4 address(net_order) %x", ip);
-        memcpy(ipv4, &ip, sizeof(ipv4));
-    } else {
-        ALOGV("Converting IPv4 address(host_order) %x", ip);
-        //endianess transparent conversion from int to char[]
-        ipv4[0] = (jbyte) (ip & 0xFF);
-        ipv4[1] = (jbyte)((ip>>8) & 0xFF);
-        ipv4[2] = (jbyte)((ip>>16) & 0xFF);
-        ipv4[3] = (jbyte) (ip>>24);
-    }
-
-    env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
-    return byteArray;
-}
-
-static void agps_status_callback(AGpsStatus* agps_status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jbyteArray byteArray = NULL;
-    bool isSupported = false;
-
-    size_t status_size = agps_status->size;
-    if (status_size == sizeof(AGpsStatus)) {
-      ALOGV("AGpsStatus is V3: %zd", status_size);
-      switch (agps_status->addr.ss_family)
-      {
-      case AF_INET:
-          {
-            struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
-            uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
-            byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
-            if (ipAddr == INADDR_NONE || byteArray != NULL) {
-                isSupported = true;
-            }
-            IF_ALOGD() {
-                // log the IP for reference in case there is a bogus value pushed by HAL
-                char str[INET_ADDRSTRLEN];
-                inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
-                ALOGD("AGPS IP is v4: %s", str);
-            }
-          }
-          break;
-      case AF_INET6:
-          {
-            struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
-            byteArray = env->NewByteArray(16);
-            if (byteArray != NULL) {
-                env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
-                isSupported = true;
-            } else {
-                ALOGE("Unable to allocate byte array for IPv6 address.");
-            }
-            IF_ALOGD() {
-                // log the IP for reference in case there is a bogus value pushed by HAL
-                char str[INET6_ADDRSTRLEN];
-                inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
-                ALOGD("AGPS IP is v6: %s", str);
-            }
-          }
-          break;
-      default:
-          ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
-          break;
-      }
-    } else if (status_size >= sizeof(AGpsStatus_v2)) {
-      ALOGV("AGpsStatus is V2+: %zd", status_size);
-      // for back-compatibility reasons we check in v2 that the data structure size is greater or
-      // equal to the declared size in gps.h
-      uint32_t ipaddr = agps_status->ipaddr;
-      ALOGV("AGPS IP is v4: %x", ipaddr);
-      byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
-      if (ipaddr == INADDR_NONE || byteArray != NULL) {
-          isSupported = true;
-      }
-    } else if (status_size >= sizeof(AGpsStatus_v1)) {
-        ALOGV("AGpsStatus is V1+: %zd", status_size);
-        // because we have to check for >= with regards to v2, we also need to relax the check here
-        // and only make sure that the size is at least what we expect
-        isSupported = true;
-    } else {
-        ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
-    }
-
-    if (isSupported) {
-        jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
-        ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
-        env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
-                            agps_status->status, byteArray);
-
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    } else {
-        ALOGD("Skipping calling method_reportAGpsStatus.");
-    }
-
-    if (byteArray) {
-        env->DeleteLocalRef(byteArray);
-    }
-}
-
-AGpsCallbacks sAGpsCallbacks = {
-    agps_status_callback,
-    create_thread_callback,
-};
-
-static void gps_ni_notify_callback(GpsNiNotification *notification)
-{
-    ALOGD("gps_ni_notify_callback\n");
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jstring requestor_id = env->NewStringUTF(notification->requestor_id);
-    jstring text = env->NewStringUTF(notification->text);
-    jstring extras = env->NewStringUTF(notification->extras);
-
-    if (requestor_id && text && extras) {
-        env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
-            notification->notification_id, notification->ni_type,
-            notification->notify_flags, notification->timeout,
-            notification->default_response, requestor_id, text,
-            notification->requestor_id_encoding,
-            notification->text_encoding, extras);
-    } else {
-        ALOGE("out of memory in gps_ni_notify_callback\n");
-    }
-
-    if (requestor_id)
-        env->DeleteLocalRef(requestor_id);
-    if (text)
-        env->DeleteLocalRef(text);
-    if (extras)
-        env->DeleteLocalRef(extras);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsNiCallbacks sGpsNiCallbacks = {
-    gps_ni_notify_callback,
-    create_thread_callback,
-};
-
-static void agps_request_set_id(uint32_t flags)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void agps_request_ref_location(uint32_t flags)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-AGpsRilCallbacks sAGpsRilCallbacks = {
-    agps_request_set_id,
-    agps_request_ref_location,
-    create_thread_callback,
-};
-
-static void gps_geofence_transition_callback(int32_t geofence_id,  GpsLocation* location,
-        int32_t transition, GpsUtcTime timestamp)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
-            location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
-            (jdouble)location->altitude,
-            (jfloat)location->speed, (jfloat)location->bearing,
-            (jfloat)location->accuracy, (jlong)location->timestamp,
-            transition, timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jint flags = 0;
-    jdouble latitude = 0;
-    jdouble longitude = 0;
-    jdouble altitude = 0;
-    jfloat speed = 0;
-    jfloat bearing = 0;
-    jfloat accuracy = 0;
-    jlong timestamp = 0;
-    if (location != NULL) {
-        flags = location->flags;
-        latitude = location->latitude;
-        longitude = location->longitude;
-        altitude = location->altitude;
-        speed = location->speed;
-        bearing = location->bearing;
-        accuracy = location->accuracy;
-        timestamp = location->timestamp;
-    }
-
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
-            flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_add_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_remove_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_resume_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_pause_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
-    gps_geofence_transition_callback,
-    gps_geofence_status_callback,
-    gps_geofence_add_callback,
-    gps_geofence_remove_callback,
-    gps_geofence_pause_callback,
-    gps_geofence_resume_callback,
-    create_thread_callback,
-};
-
-static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
-    int err;
-    hw_module_t* module;
-
-    method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
-    method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
-    method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
-    method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
-    method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
-    method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
-    method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
-    method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
-    method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
-            "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
-    method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
-    method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
-    method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
-    method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
-            "(IIDDDFFFJIJ)V");
-    method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
-            "(IIDDDFFFJ)V");
-    method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
-            "(II)V");
-    method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
-            "(II)V");
-    method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
-            "(II)V");
-    method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
-            "(II)V");
-    method_reportMeasurementData = env->GetMethodID(
-            clazz,
-            "reportMeasurementData",
-            "(Landroid/location/GnssMeasurementsEvent;)V");
-    method_reportNavigationMessages = env->GetMethodID(
-            clazz,
-            "reportNavigationMessage",
-            "(Landroid/location/GnssNavigationMessage;)V");
-
-    err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
-    if (err == 0) {
-        hw_device_t* device;
-        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
-        if (err == 0) {
-            gps_device_t* gps_device = (gps_device_t *)device;
-            sGpsInterface = gps_device->get_gps_interface(gps_device);
-        }
-    }
-    if (sGpsInterface) {
-        sGpsXtraInterface =
-            (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
-        sAGpsInterface =
-            (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
-        sGpsNiInterface =
-            (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
-        sGpsDebugInterface =
-            (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
-        sAGpsRilInterface =
-            (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
-        sGpsGeofencingInterface =
-            (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
-        sGpsMeasurementInterface =
-            (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
-        sGpsNavigationMessageInterface =
-            (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
-                    GPS_NAVIGATION_MESSAGE_INTERFACE);
-        sGnssConfigurationInterface =
-            (const GnssConfigurationInterface*)sGpsInterface->get_extension(
-                    GNSS_CONFIGURATION_INTERFACE);
-    }
-}
-
-static jboolean android_location_GnssLocationProvider_is_supported(
-        JNIEnv* /* env */, jclass /* clazz */)
-{
-    return (sGpsInterface != NULL) ?  JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
-        JNIEnv* /* env */, jclass /* clazz */)
-{
-    return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
-        JNIEnv* /* env */, jclass /* jclazz */)
-{
-    return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
-{
-    // this must be set before calling into the HAL library
-    if (!mCallbacksObj)
-        mCallbacksObj = env->NewGlobalRef(obj);
-
-    // fail if the main interface fails to initialize
-    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
-        return JNI_FALSE;
-
-    // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
-    // but continue to allow the rest of the GPS interface to work.
-    if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
-        sGpsXtraInterface = NULL;
-    if (sAGpsInterface)
-        sAGpsInterface->init(&sAGpsCallbacks);
-    if (sGpsNiInterface)
-        sGpsNiInterface->init(&sGpsNiCallbacks);
-    if (sAGpsRilInterface)
-        sAGpsRilInterface->init(&sAGpsRilCallbacks);
-    if (sGpsGeofencingInterface)
-        sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
-
-    return JNI_TRUE;
-}
-
-static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
-{
-    if (sGpsInterface)
-        sGpsInterface->cleanup();
-}
-
-static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
-        jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
-        jint preferred_time)
-{
-    if (sGpsInterface) {
-        if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
-                preferred_time) == 0) {
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    }
-    else
-        return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
-{
-    if (sGpsInterface) {
-        if (sGpsInterface->start() == 0) {
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    }
-    else
-        return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
-{
-    if (sGpsInterface) {
-        if (sGpsInterface->stop() == 0) {
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    }
-    else
-        return JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
-                                                                    jobject /* obj */,
-                                                                    jint flags)
-{
-    if (sGpsInterface)
-        sGpsInterface->delete_aiding_data(flags);
-}
-
-static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
-        jfloatArray azumArray)
-{
-    // this should only be called from within a call to reportSvStatus
-    jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
-    jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
-    jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
-    jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-
-    // GNSS SV info.
-    for (size_t i = 0; i < sGnssSvListSize; ++i) {
-        const GnssSvInfo& info = sGnssSvList[i];
-        svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
-            (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
-            info.flags;
-        cn0s[i] = info.c_n0_dbhz;
-        elev[i] = info.elevation;
-        azim[i] = info.azimuth;
-    }
-
-    env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
-    env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
-    env->ReleaseFloatArrayElements(elevArray, elev, 0);
-    env->ReleaseFloatArrayElements(azumArray, azim, 0);
-    return (jint) sGnssSvListSize;
-}
-
-static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
-        JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
-{
-    AGpsRefLocation location;
-
-    if (!sAGpsRilInterface) {
-        ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
-        return;
-    }
-
-    switch(type) {
-        case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
-        case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
-            location.type = type;
-            location.u.cellID.mcc = mcc;
-            location.u.cellID.mnc = mnc;
-            location.u.cellID.lac = lac;
-            location.u.cellID.cid = cid;
-            break;
-        default:
-            ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
-            return;
-            break;
-    }
-    sAGpsRilInterface->set_ref_location(&location, sizeof(location));
-}
-
-static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
-        jobject /* obj */, jbyteArray ni_msg, jint size)
-{
-    size_t sz;
-
-    if (!sAGpsRilInterface) {
-        ALOGE("no AGPS RIL interface in send_ni_message");
-        return;
-    }
-    if (size < 0)
-        return;
-    sz = (size_t)size;
-    jbyte* b = env->GetByteArrayElements(ni_msg, 0);
-    sAGpsRilInterface->ni_message((uint8_t *)b,sz);
-    env->ReleaseByteArrayElements(ni_msg,b,0);
-}
-
-static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
-                                                             jint type, jstring  setid_string)
-{
-    if (!sAGpsRilInterface) {
-        ALOGE("no AGPS RIL interface in agps_set_id");
-        return;
-    }
-
-    const char *setid = env->GetStringUTFChars(setid_string, NULL);
-    sAGpsRilInterface->set_set_id(type, setid);
-    env->ReleaseStringUTFChars(setid_string, setid);
-}
-
-static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
-                                            jbyteArray nmeaArray, jint buffer_size)
-{
-    // this should only be called from within a call to reportNmea
-    jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
-    int length = sNmeaStringLength;
-    if (length > buffer_size)
-        length = buffer_size;
-    memcpy(nmea, sNmeaString, length);
-    env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
-    return (jint) length;
-}
-
-static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
-        jlong time, jlong timeReference, jint uncertainty)
-{
-    if (sGpsInterface)
-        sGpsInterface->inject_time(time, timeReference, uncertainty);
-}
-
-static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
-        jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
-{
-    if (sGpsInterface)
-        sGpsInterface->inject_location(latitude, longitude, accuracy);
-}
-
-static jboolean android_location_GnssLocationProvider_supports_xtra(
-        JNIEnv* /* env */, jobject /* obj */)
-{
-    return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
-        jbyteArray data, jint length)
-{
-    if (!sGpsXtraInterface) {
-        ALOGE("no XTRA interface in inject_xtra_data");
-        return;
-    }
-
-    jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
-    sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
-    env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_open(
-        JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in agps_data_conn_open");
-        return;
-    }
-    if (apn == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return;
-    }
-
-    const char *apnStr = env->GetStringUTFChars(apn, NULL);
-
-    size_t interface_size = sAGpsInterface->size;
-    if (interface_size == sizeof(AGpsInterface)) {
-        sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
-    } else if (interface_size == sizeof(AGpsInterface_v1)) {
-        sAGpsInterface->data_conn_open(apnStr);
-    } else {
-        ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
-    }
-
-    env->ReleaseStringUTFChars(apn, apnStr);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
-                                                                       jobject /* obj */)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in agps_data_conn_closed");
-        return;
-    }
-    sAGpsInterface->data_conn_closed();
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
-                                                                       jobject /* obj */)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in agps_data_conn_failed");
-        return;
-    }
-    sAGpsInterface->data_conn_failed();
-}
-
-static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
-        jint type, jstring hostname, jint port)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in set_agps_server");
-        return;
-    }
-    const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
-    sAGpsInterface->set_server(type, c_hostname, port);
-    env->ReleaseStringUTFChars(hostname, c_hostname);
-}
-
-static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
-      jobject /* obj */, jint notifId, jint response)
-{
-    if (!sGpsNiInterface) {
-        ALOGE("no NI interface in send_ni_response");
-        return;
-    }
-
-    sGpsNiInterface->respond(notifId, response);
-}
-
-static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
-                                                                       jobject /* obj */) {
-    jstring result = NULL;
-    if (sGpsDebugInterface) {
-        const size_t maxLength = 2047;
-        char buffer[maxLength+1];
-        size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
-        if (length > maxLength) length = maxLength;
-        buffer[length] = 0;
-        result = env->NewStringUTF(buffer);
-    }
-    return result;
-}
-
-static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
-        jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
-{
-
-    if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
-        if (extraInfo) {
-            const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
-            sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
-            env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
-        } else {
-            sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
-        }
-
-        // update_network_availability callback was not included in original AGpsRilInterface
-        if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
-                && sAGpsRilInterface->update_network_availability) {
-            const char *c_apn = env->GetStringUTFChars(apn, NULL);
-            sAGpsRilInterface->update_network_availability(available, c_apn);
-            env->ReleaseStringUTFChars(apn, c_apn);
-        }
-    }
-}
-
-static jboolean android_location_GnssLocationProvider_is_geofence_supported(
-        JNIEnv* /* env */, jobject /* obj */)
-{
-    return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
-        jint last_transition, jint monitor_transition, jint notification_responsiveness,
-        jint unknown_timer) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
-                radius, last_transition, monitor_transition, notification_responsiveness,
-                unknown_timer);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->remove_geofence_area(geofence_id);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->pause_geofence(geofence_id);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id, jint monitor_transition) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
 template<class T>
 class JavaMethodHelper {
-  public:
-   // Helper function to call setter on a Java object.
-   static void callJavaMethod(
+ public:
+    // Helper function to call setter on a Java object.
+    static void callJavaMethod(
            JNIEnv* env,
            jclass clazz,
            jobject object,
            const char* method_name,
            T value);
 
-  private:
+ private:
     static const char *const signature_;
 };
 
@@ -1045,20 +136,20 @@
 }
 
 class JavaObject {
-  public:
-   JavaObject(JNIEnv* env, const char* class_name);
-   virtual ~JavaObject();
+ public:
+    JavaObject(JNIEnv* env, const char* class_name);
+    virtual ~JavaObject();
 
-   template<class T>
-   void callSetter(const char* method_name, T value);
-   template<class T>
-   void callSetter(const char* method_name, T* value, size_t size);
-   jobject get();
+    template<class T>
+    void callSetter(const char* method_name, T value);
+    template<class T>
+    void callSetter(const char* method_name, T* value, size_t size);
+    jobject get();
 
-  private:
-   JNIEnv* env_;
-   jclass clazz_;
-   jobject object_;
+ private:
+    JNIEnv* env_;
+    jclass clazz_;
+    jobject object_;
 };
 
 JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
@@ -1081,7 +172,7 @@
 void JavaObject::callSetter(
         const char* method_name, uint8_t* value, size_t size) {
     jbyteArray array = env_->NewByteArray(size);
-    env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
+    env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
     jmethodID method = env_->GetMethodID(
             clazz_,
             method_name,
@@ -1095,7 +186,6 @@
 }
 
 // Define Java method signatures for all known types.
-
 template<>
 const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
 template<>
@@ -1119,209 +209,460 @@
 
 #define SET(setter, value) object.callSetter("set" # setter, (value))
 
-// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
-// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
-//
-// This macros generates compilation error if the provided 'flag' is not a
-// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
-// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
-#define SET_IF(flag, setter, value) do { \
-        if (flags & flag) { \
-            JavaObject& name_check_##flag = object; \
-            name_check_##flag.callSetter("set" # setter, (value)); \
-        } \
-    } while (false)
-#define SET_IF_NOT(flag, setter, value) do { \
-        if (!(flags & flag)) { \
-            JavaObject& name_check_##flag = object; \
-            name_check_##flag.callSetter("set" # setter, (value)); \
-        } \
-    } while (false)
+static inline jboolean boolToJbool(bool value) {
+    return value ? JNI_TRUE : JNI_FALSE;
+}
 
-static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
-    static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
-    JavaObject object(env, "android/location/GnssClock");
-    GpsClockFlags flags = clock->flags;
+static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        ALOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+    }
+}
 
-    SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
-           LeapSecond,
-           static_cast<int32_t>(clock->leap_second));
+/*
+ * GnssCallback class implements the callback methods for IGnss interface.
+ */
+struct GnssCallback : public IGnssCallback {
+    Return<void> gnssLocationCb(
+          const android::hardware::gnss::V1_0::GnssLocation& location) override;
+    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
+    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
+    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
+    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+    Return<void> gnssAcquireWakelockCb() override;
+    Return<void> gnssReleaseWakelockCb() override;
+    Return<void> gnssRequestTimeCb() override;
+    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
 
-    // GnssClock only supports the more effective HW_CLOCK type, so type
-    // handling and documentation complexity has been removed.  To convert the
-    // old GPS_CLOCK types (active only in a limited number of older devices),
-    // the GPS time information is handled as an always discontinuous HW clock,
-    // with the GPS time information put into the full_bias_ns instead - so that
-    // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
-    // sign of full_bias_ns and bias_ns has flipped between GpsClock &
-    // GnssClock, so that is also handled below.
-    switch (clock->type) {
-      case GPS_CLOCK_TYPE_UNKNOWN:
-        // Clock type unsupported.
-        ALOGE("Unknown clock type provided.");
-        break;
-      case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
-        // Already local hardware time. No need to do anything.
-        break;
-      case GPS_CLOCK_TYPE_GPS_TIME:
-        // GPS time, need to convert.
-        flags |= GPS_CLOCK_HAS_FULL_BIAS;
-        clock->full_bias_ns = clock->time_ns;
-        clock->time_ns = 0;
-        SET(HardwareClockDiscontinuityCount,
-            discontinuity_count_to_handle_old_clock_type++);
-        break;
+    static GnssSvInfo sGnssSvList[static_cast<uint32_t>(
+            android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+    static size_t sGnssSvListSize;
+
+    static const char* sNmeaString;
+    static size_t sNmeaStringLength;
+};
+
+IGnssCallback::GnssSvInfo GnssCallback::sGnssSvList[static_cast<uint32_t>(
+        android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+const char* GnssCallback::sNmeaString = nullptr;
+size_t GnssCallback::sNmeaStringLength = 0;
+size_t GnssCallback::sGnssSvListSize = 0;
+
+Return<void> GnssCallback::gnssLocationCb(
+        const ::android::hardware::gnss::V1_0::GnssLocation& location) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportLocation,
+                        location.gnssLocationFlags,
+                        static_cast<jdouble>(location.latitudeDegrees),
+                        static_cast<jdouble>(location.longitudeDegrees),
+                        static_cast<jdouble>(location.altitudeMeters),
+                        static_cast<jfloat>(location.speedMetersPerSec),
+                        static_cast<jfloat>(location.bearingDegrees),
+                        static_cast<jfloat>(location.accuracyMeters),
+                        static_cast<jlong>(location.timestamp));
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssStatusCb(const IGnssCallback::GnssStatusValue status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    sGnssSvListSize = svStatus.numSvs;
+    if (sGnssSvListSize > static_cast<uint32_t>(
+            android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) {
+        ALOGD("Too many satellites %zd. Clamps to %u.", sGnssSvListSize,
+              static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT));
+        sGnssSvListSize = static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT);
     }
 
-    SET(TimeNanos, clock->time_ns);
-    SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyNanos,
-           clock->time_uncertainty_ns);
-
-    // Definition of sign for full_bias_ns & bias_ns has been changed since N,
-    // so flip signs here.
-    SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
-    SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
-
-    SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyNanos,
-           clock->bias_uncertainty_ns);
-    SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
-    SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyNanosPerSecond,
-           clock->drift_uncertainty_nsps);
-
-    return object.get();
-}
-
-static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
-    JavaObject object(env, "android/location/GnssClock");
-    GnssClockFlags flags = clock->flags;
-
-    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
-           LeapSecond,
-           static_cast<int32_t>(clock->leap_second));
-    SET(TimeNanos, clock->time_ns);
-    SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyNanos,
-           clock->time_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyNanos,
-           clock->bias_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyNanosPerSecond,
-           clock->drift_uncertainty_nsps);
-
-    SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
-
-    return object.get();
-}
-
-static jobject translate_gps_measurement(JNIEnv* env,
-                                         GpsMeasurement* measurement) {
-    JavaObject object(env, "android/location/GnssMeasurement");
-    GpsMeasurementFlags flags = measurement->flags;
-    SET(Svid, static_cast<int32_t>(measurement->prn));
-    if (measurement->prn >= 1 && measurement->prn <= 32) {
-        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
-    } else {
-        ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
-        SET(ConstellationType,
-            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+    // Copy GNSS SV info into sGnssSvList, if any.
+    if (svStatus.numSvs > 0) {
+        memcpy(sGnssSvList, svStatus.gnssSvList.data(), sizeof(GnssSvInfo) * sGnssSvListSize);
     }
-    SET(TimeOffsetNanos, measurement->time_offset_ns);
-    SET(State, static_cast<int32_t>(measurement->state));
-    SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
-    SET(ReceivedSvTimeUncertaintyNanos,
-        measurement->received_gps_tow_uncertainty_ns);
-    SET(Cn0DbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
-    SET(PseudorangeRateUncertaintyMetersPerSecond,
-        measurement->pseudorange_rate_uncertainty_mps);
-    SET(AccumulatedDeltaRangeState,
-        static_cast<int32_t>(measurement->accumulated_delta_range_state));
-    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
-    SET(AccumulatedDeltaRangeUncertaintyMeters,
-        measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyHz,
-           measurement->carrier_frequency_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
-           CarrierCycles,
-           measurement->carrier_cycles);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
-           CarrierPhase,
-           measurement->carrier_phase);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
-           CarrierPhaseUncertainty,
-           measurement->carrier_phase_uncertainty);
-    SET(MultipathIndicator,
-        static_cast<int32_t>(measurement->multipath_indicator));
-    SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
 
-    return object.get();
+    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
 }
 
-static jobject translate_gnss_measurement(JNIEnv* env,
-                                          GnssMeasurement* measurement) {
+Return<void> GnssCallback::gnssNmeaCb(
+    int64_t timestamp, const ::android::hardware::hidl_string& nmea) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    /*
+     * The Java code will call back to read these values.
+     * We do this to avoid creating unnecessary String objects.
+     */
+    sNmeaString = nmea.c_str();
+    sNmeaStringLength = nmea.size();
+
+    env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+    ALOGD("%s: %du\n", __func__, capabilities);
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssAcquireWakelockCb() {
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssReleaseWakelockCb() {
+    release_wake_lock(WAKE_LOCK_NAME);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssRequestTimeCb() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) {
+    ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
+                        info.yearOfHw);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+class GnssXtraCallback : public IGnssXtraCallback {
+    Return<void> downloadRequestCb() override;
+};
+
+/*
+ * GnssXtraCallback class implements the callback methods for the IGnssXtra
+ * interface.
+ */
+Return<void> GnssXtraCallback::downloadRequestCb() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
+ * GnssGeofenceCallback class implements the callback methods for the
+ * IGnssGeofence interface.
+ */
+struct GnssGeofenceCallback : public IGnssGeofenceCallback {
+    // Methods from ::android::hardware::gps::V1_0::IGnssGeofenceCallback follow.
+    Return<void> gnssGeofenceTransitionCb(
+            int32_t geofenceId,
+            const android::hardware::gnss::V1_0::GnssLocation& location,
+            GeofenceTransition transition,
+            hardware::gnss::V1_0::GnssUtcTime timestamp) override;
+    Return<void> gnssGeofenceStatusCb(
+            GeofenceAvailability status,
+            const android::hardware::gnss::V1_0::GnssLocation& location) override;
+    Return<void> gnssGeofenceAddCb(int32_t geofenceId,
+                                   GeofenceStatus status) override;
+    Return<void> gnssGeofenceRemoveCb(int32_t geofenceId,
+                                      GeofenceStatus status) override;
+    Return<void> gnssGeofencePauseCb(int32_t geofenceId,
+                                     GeofenceStatus status) override;
+    Return<void> gnssGeofenceResumeCb(int32_t geofenceId,
+                                      GeofenceStatus status) override;
+};
+
+Return<void> GnssGeofenceCallback::gnssGeofenceTransitionCb(
+        int32_t geofenceId,
+        const android::hardware::gnss::V1_0::GnssLocation& location,
+        GeofenceTransition transition,
+        hardware::gnss::V1_0::GnssUtcTime timestamp) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceTransition,
+                        geofenceId,
+                        location.gnssLocationFlags,
+                        static_cast<jdouble>(location.latitudeDegrees),
+                        static_cast<jdouble>(location.longitudeDegrees),
+                        static_cast<jdouble>(location.altitudeMeters),
+                        static_cast<jfloat>(location.speedMetersPerSec),
+                        static_cast<jfloat>(location.bearingDegrees),
+                        static_cast<jfloat>(location.accuracyMeters),
+                        static_cast<jlong>(location.timestamp),
+                        transition,
+                        timestamp);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceStatusCb(
+        GeofenceAvailability status,
+        const android::hardware::gnss::V1_0::GnssLocation& location) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceStatus,
+                        status,
+                        location.gnssLocationFlags,
+                        static_cast<jdouble>(location.latitudeDegrees),
+                        static_cast<jdouble>(location.longitudeDegrees),
+                        static_cast<jdouble>(location.altitudeMeters),
+                        static_cast<jfloat>(location.speedMetersPerSec),
+                        static_cast<jfloat>(location.bearingDegrees),
+                        static_cast<jfloat>(location.accuracyMeters),
+                        static_cast<jlong>(location.timestamp));
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId,
+                                                    GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in adding a Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceAddStatus,
+                        geofenceId,
+                        status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId,
+                                                       GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in removing a Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceRemoveStatus,
+                        geofenceId, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId,
+                                                      GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in pausing Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofencePauseStatus,
+                        geofenceId, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId,
+                                                       GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in resuming Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceResumeStatus,
+                        geofenceId, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
+ * GnssNavigationMessageCallback interface implements the callback methods
+ * required by the IGnssNavigationMessage interface.
+ */
+struct GnssNavigationMessageCallback : public IGnssNavigationMessageCallback {
+  /*
+   * Methods from ::android::hardware::gps::V1_0::IGnssNavigationMessageCallback
+   * follow.
+   */
+  Return<void> gnssNavigationMessageCb(
+          const IGnssNavigationMessageCallback::GnssNavigationMessage& message) override;
+};
+
+Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
+        const IGnssNavigationMessageCallback::GnssNavigationMessage& message) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    size_t dataLength = message.data.size();
+
+    std::vector<uint8_t> navigationData = message.data;
+    uint8_t* data = &(navigationData[0]);
+    if (dataLength == 0 || data == NULL) {
+      ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data,
+            dataLength);
+      return Void();
+    }
+
+    JavaObject object(env, "android/location/GnssNavigationMessage");
+    SET(Type, static_cast<int32_t>(message.type));
+    SET(Svid, static_cast<int32_t>(message.svid));
+    SET(MessageId, static_cast<int32_t>(message.messageId));
+    SET(SubmessageId, static_cast<int32_t>(message.submessageId));
+    object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message.status));
+
+    jobject navigationMessage = object.get();
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportNavigationMessages,
+                        navigationMessage);
+    env->DeleteLocalRef(navigationMessage);
+    return Void();
+}
+
+/*
+ * GnssMeasurementCallback implements the callback methods required for the
+ * GnssMeasurement interface.
+ */
+struct GnssMeasurementCallback : public IGnssMeasurementCallback {
+    Return<void> GnssMeasurementCb(const IGnssMeasurementCallback::GnssData& data);
+ private:
+    jobject translateGnssMeasurement(
+            JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement);
+    jobject translateGnssClock(
+            JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock);
+    jobjectArray translateGnssMeasurements(
+            JNIEnv* env,
+            const IGnssMeasurementCallback::GnssMeasurement* measurements,
+            size_t count);
+    void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
+};
+
+
+Return<void> GnssMeasurementCallback::GnssMeasurementCb(
+        const IGnssMeasurementCallback::GnssData& data) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    jobject clock;
+    jobjectArray measurementArray;
+
+    clock = translateGnssClock(env, &data.clock);
+    measurementArray = translateGnssMeasurements(
+        env, data.measurements.data(), data.measurementCount);
+    setMeasurementData(env, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+    return Void();
+}
+
+jobject GnssMeasurementCallback::translateGnssMeasurement(
+        JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement) {
     JavaObject object(env, "android/location/GnssMeasurement");
 
-    GnssMeasurementFlags flags = measurement->flags;
+    uint32_t flags = static_cast<uint32_t>(measurement->flags);
 
     SET(Svid, static_cast<int32_t>(measurement->svid));
     SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
-    SET(TimeOffsetNanos, measurement->time_offset_ns);
+    SET(TimeOffsetNanos, measurement->timeOffsetNs);
     SET(State, static_cast<int32_t>(measurement->state));
-    SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+    SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
     SET(ReceivedSvTimeUncertaintyNanos,
-        measurement->received_sv_time_uncertainty_in_ns);
-    SET(Cn0DbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+        measurement->receivedSvTimeUncertaintyInNs);
+    SET(Cn0DbHz, measurement->cN0DbHz);
+    SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
     SET(PseudorangeRateUncertaintyMetersPerSecond,
-        measurement->pseudorange_rate_uncertainty_mps);
+        measurement->pseudorangeRateUncertaintyMps);
     SET(AccumulatedDeltaRangeState,
-        static_cast<int32_t>(measurement->accumulated_delta_range_state));
-    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+        (static_cast<int32_t>(measurement->accumulatedDeltaRangeState)));
+    SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
     SET(AccumulatedDeltaRangeUncertaintyMeters,
-        measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyHz,
-           measurement->carrier_frequency_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
-           CarrierCycles,
-           measurement->carrier_cycles);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
-           CarrierPhase,
-           measurement->carrier_phase);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
-           CarrierPhaseUncertainty,
-           measurement->carrier_phase_uncertainty);
-    SET(MultipathIndicator,
-        static_cast<int32_t>(measurement->multipath_indicator));
-    SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+        measurement->accumulatedDeltaRangeUncertaintyM);
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
+        SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE)) {
+        SET(CarrierPhase, measurement->carrierPhase);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY)) {
+        SET(CarrierPhaseUncertainty, measurement->carrierPhaseUncertainty);
+    }
+
+    SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
+        SET(SnrInDb, measurement->snrDb);
+    }
 
     return object.get();
 }
 
-static jobjectArray translate_gps_measurements(JNIEnv* env,
-                                               GpsMeasurement* measurements,
-                                               size_t count) {
+jobject GnssMeasurementCallback::translateGnssClock(
+       JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock) {
+    JavaObject object(env, "android/location/GnssClock");
+
+    uint32_t flags = static_cast<uint32_t>(clock->gnssClockFlags);
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
+        SET(LeapSecond, static_cast<int32_t>(clock->leapSecond));
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
+        SET(TimeUncertaintyNanos, clock->timeUncertaintyNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
+        SET(FullBiasNanos, clock->fullBiasNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
+        SET(BiasNanos, clock->biasNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
+        SET(BiasUncertaintyNanos, clock->biasUncertaintyNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
+        SET(DriftNanosPerSecond, clock->driftNsps);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
+        SET(DriftUncertaintyNanosPerSecond, clock->driftUncertaintyNsps);
+    }
+
+    SET(TimeNanos, clock->timeNs);
+    SET(HardwareClockDiscontinuityCount, clock->hwClockDiscontinuityCount);
+
+    return object.get();
+}
+
+jobjectArray GnssMeasurementCallback::translateGnssMeasurements(JNIEnv* env,
+                                       const IGnssMeasurementCallback::GnssMeasurement*
+                                       measurements, size_t count) {
     if (count == 0) {
         return NULL;
     }
 
-    jclass gnssMeasurementClass = env->FindClass(
-            "android/location/GnssMeasurement");
+    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
     jobjectArray gnssMeasurementArray = env->NewObjectArray(
             count,
             gnssMeasurementClass,
             NULL /* initialElement */);
 
     for (uint16_t i = 0; i < count; ++i) {
-        jobject gnssMeasurement = translate_gps_measurement(
+        jobject gnssMeasurement = translateGnssMeasurement(
             env,
             &measurements[i]);
         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
@@ -1332,130 +673,789 @@
     return gnssMeasurementArray;
 }
 
-static jobjectArray translate_gnss_measurements(JNIEnv* env,
-                                                GnssMeasurement* measurements,
-                                                size_t count) {
-    if (count == 0) {
-        return NULL;
-    }
+void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
+                             jobjectArray measurementArray) {
+    jclass gnssMeasurementsEventClass =
+            env->FindClass("android/location/GnssMeasurementsEvent");
+    jmethodID gnssMeasurementsEventCtor =
+            env->GetMethodID(
+                    gnssMeasurementsEventClass,
+                    "<init>",
+                    "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
 
-    jclass gnssMeasurementClass = env->FindClass(
-            "android/location/GnssMeasurement");
-    jobjectArray gnssMeasurementArray = env->NewObjectArray(
-            count,
-            gnssMeasurementClass,
-            NULL /* initialElement */);
+    jobject gnssMeasurementsEvent = env->NewObject(gnssMeasurementsEventClass,
+                                                   gnssMeasurementsEventCtor,
+                                                   clock,
+                                                   measurementArray);
 
-    for (uint16_t i = 0; i < count; ++i) {
-        jobject gnssMeasurement = translate_gnss_measurement(
-            env,
-            &measurements[i]);
-        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
-        env->DeleteLocalRef(gnssMeasurement);
-    }
-
-    env->DeleteLocalRef(gnssMeasurementClass);
-    return gnssMeasurementArray;
-}
-
-static void set_measurement_data(JNIEnv *env,
-                                 jobject clock,
-                                 jobjectArray measurementArray) {
-    jclass gnssMeasurementsEventClass = env->FindClass(
-            "android/location/GnssMeasurementsEvent");
-    jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
-        gnssMeasurementsEventClass,
-        "<init>",
-        "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
-
-    jobject gnssMeasurementsEvent = env->NewObject(
-        gnssMeasurementsEventClass,
-        gnssMeasurementsEventCtor,
-        clock,
-        measurementArray);
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportMeasurementData,
-                        gnssMeasurementsEvent);
+    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
+                      gnssMeasurementsEvent);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     env->DeleteLocalRef(gnssMeasurementsEventClass);
     env->DeleteLocalRef(gnssMeasurementsEvent);
 }
 
-static void measurement_callback(GpsData* data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (data == NULL) {
-        ALOGE("Invalid data provided to gps_measurement_callback");
-        return;
-    }
-    if (data->size != sizeof(GpsData)) {
-        ALOGE("Invalid GpsData size found in gps_measurement_callback, "
-              "size=%zd",
-              data->size);
-        return;
-    }
-
-    jobject clock;
-    jobjectArray measurementArray;
-    clock = translate_gps_clock(env, &data->clock);
-    measurementArray = translate_gps_measurements(
-            env, data->measurements, data->measurement_count);
-    set_measurement_data(env, clock, measurementArray);
-
-    env->DeleteLocalRef(clock);
-    env->DeleteLocalRef(measurementArray);
-}
-
-static void gnss_measurement_callback(GnssData* data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (data == NULL) {
-        ALOGE("Invalid data provided to gps_measurement_callback");
-        return;
-    }
-    if (data->size != sizeof(GnssData)) {
-        ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
-              "size=%zd",
-              data->size);
-        return;
-    }
-
-    jobject clock;
-    jobjectArray measurementArray;
-    clock = translate_gnss_clock(env, &data->clock);
-    measurementArray = translate_gnss_measurements(
-            env, data->measurements, data->measurement_count);
-    set_measurement_data(env, clock, measurementArray);
-
-    env->DeleteLocalRef(clock);
-    env->DeleteLocalRef(measurementArray);
-}
-
-GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
-    sizeof(GpsMeasurementCallbacks),
-    measurement_callback,
-    gnss_measurement_callback,
+/*
+ * GnssNiCallback implements callback methods required by the IGnssNi interface.
+ */
+struct GnssNiCallback : public IGnssNiCallback {
+    Return<void> niNotifyCb(const IGnssNiCallback::GnssNiNotification& notification)
+            override;
 };
 
+Return<void> GnssNiCallback::niNotifyCb(
+        const IGnssNiCallback::GnssNiNotification& notification) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
+    jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
+
+    if (requestorId && text) {
+        env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
+                            notification.notificationId, notification.niType,
+                            notification.notifyFlags, notification.timeoutSec,
+                            notification.defaultResponse, requestorId, text,
+                            notification.requestorIdEncoding,
+                            notification.notificationIdEncoding);
+    } else {
+        ALOGE("%s: OOM Error\n", __func__);
+    }
+
+    if (requestorId) {
+        env->DeleteLocalRef(requestorId);
+    }
+
+    if (text) {
+        env->DeleteLocalRef(text);
+    }
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
+ * AGnssCallback implements callback methods required by the IAGnss interface.
+ */
+struct AGnssCallback : public IAGnssCallback {
+    // Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow.
+    Return<void> agnssStatusIpV6Cb(
+      const IAGnssCallback::AGnssStatusIpV6& agps_status) override;
+
+    Return<void> agnssStatusIpV4Cb(
+      const IAGnssCallback::AGnssStatusIpV4& agps_status) override;
+ private:
+    jbyteArray convertToIpV4(uint32_t ip);
+};
+
+Return<void> AGnssCallback::agnssStatusIpV6Cb(
+        const IAGnssCallback::AGnssStatusIpV6& agps_status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray byteArray = NULL;
+    bool isSupported = false;
+
+    byteArray = env->NewByteArray(16);
+    if (byteArray != NULL) {
+        env->SetByteArrayRegion(byteArray, 0, 16,
+                                (const jbyte*)(agps_status.ipV6Addr.data()));
+        isSupported = true;
+    } else {
+        ALOGE("Unable to allocate byte array for IPv6 address.");
+    }
+
+    IF_ALOGD() {
+        // log the IP for reference in case there is a bogus value pushed by HAL
+        char str[INET6_ADDRSTRLEN];
+        inet_ntop(AF_INET6, agps_status.ipV6Addr.data(), str, INET6_ADDRSTRLEN);
+        ALOGD("AGPS IP is v6: %s", str);
+    }
+
+    jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+    ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+    env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+                        agps_status.type, agps_status.status, byteArray);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+    if (byteArray) {
+        env->DeleteLocalRef(byteArray);
+    }
+
+    return Void();
+}
+
+Return<void> AGnssCallback::agnssStatusIpV4Cb(
+        const IAGnssCallback::AGnssStatusIpV4& agps_status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray byteArray = NULL;
+
+    uint32_t ipAddr = agps_status.ipV4Addr;
+    byteArray = convertToIpV4(ipAddr);
+
+    IF_ALOGD() {
+        /*
+         * log the IP for reference in case there is a bogus value pushed by
+         * HAL.
+         */
+        char str[INET_ADDRSTRLEN];
+        inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
+        ALOGD("AGPS IP is v4: %s", str);
+    }
+
+    jsize byteArrayLength =
+      byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+    ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+    env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+                      agps_status.type, agps_status.status, byteArray);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+    if (byteArray) {
+        env->DeleteLocalRef(byteArray);
+    }
+    return Void();
+}
+
+jbyteArray AGnssCallback::convertToIpV4(uint32_t ip) {
+    if (INADDR_NONE == ip) {
+        return NULL;
+    }
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray byteArray = env->NewByteArray(4);
+    if (byteArray == NULL) {
+        ALOGE("Unable to allocate byte array for IPv4 address");
+        return NULL;
+    }
+
+    jbyte ipv4[4];
+    ALOGV("Converting IPv4 address byte array (net_order) %x", ip);
+    memcpy(ipv4, &ip, sizeof(ipv4));
+    env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*)ipv4);
+    return byteArray;
+}
+
+/*
+ * AGnssRilCallback implements the callback methods required by the AGnssRil
+ * interface.
+ */
+struct AGnssRilCallback : IAGnssRilCallback {
+    Return<void> requestSetIdCb(IAGnssRilCallback::ID setIdFlag) override;
+    Return<void> requestRefLocCb() override;
+};
+
+Return<void> AGnssRilCallback::requestSetIdCb(IAGnssRilCallback::ID setIdFlag) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestSetID, setIdFlag);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> AGnssRilCallback::requestRefLocCb() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestRefLocation);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+    method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
+    method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
+    method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
+    method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
+    method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
+    method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
+    method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
+    method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
+    method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
+            "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
+    method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
+    method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
+    method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
+    method_reportGeofenceTransition = env->GetMethodID(clazz, "reportGeofenceTransition",
+            "(IIDDDFFFJIJ)V");
+    method_reportGeofenceStatus = env->GetMethodID(clazz, "reportGeofenceStatus",
+            "(IIDDDFFFJ)V");
+    method_reportGeofenceAddStatus = env->GetMethodID(clazz, "reportGeofenceAddStatus",
+            "(II)V");
+    method_reportGeofenceRemoveStatus = env->GetMethodID(clazz, "reportGeofenceRemoveStatus",
+            "(II)V");
+    method_reportGeofenceResumeStatus = env->GetMethodID(clazz, "reportGeofenceResumeStatus",
+            "(II)V");
+    method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
+            "(II)V");
+    method_reportMeasurementData = env->GetMethodID(
+            clazz,
+            "reportMeasurementData",
+            "(Landroid/location/GnssMeasurementsEvent;)V");
+    method_reportNavigationMessages = env->GetMethodID(
+            clazz,
+            "reportNavigationMessage",
+            "(Landroid/location/GnssNavigationMessage;)V");
+
+    // TODO(b/31632518)
+    gnssHal = IGnss::getService("gnss");
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->getExtensionXtra([](const sp<IGnssXtra>& xtraIface) {
+            gnssXtraIface = xtraIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to Xtra");
+        }
+
+        result = gnssHal->getExtensionAGnssRil([](const sp<IAGnssRil>& rilIface) {
+            agnssRilIface = rilIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to AGnssRil");
+        }
+
+        result = gnssHal->getExtensionAGnss([](const sp<IAGnss>& assistedGnssIface) {
+            agnssIface = assistedGnssIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to AGnss");
+        }
+
+        result = gnssHal->getExtensionGnssNavigationMessage(
+                [](const sp<IGnssNavigationMessage>& navigationMessageIface) {
+            gnssNavigationMessageIface = navigationMessageIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssNavigationMessage");
+        }
+
+        result = gnssHal->getExtensionGnssMeasurement([](
+                const sp<IGnssMeasurement>& measurementIface) {
+            gnssMeasurementIface = measurementIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssMeasurement");
+        }
+
+        result = gnssHal->getExtensionGnssDebug([](const sp<IGnssDebug>& debugIface) {
+            gnssDebugIface = debugIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssDebug");
+        }
+
+        result = gnssHal->getExtensionGnssNi([](const sp<IGnssNi>& niIface) {
+            gnssNiIface = niIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssNi");
+        }
+
+        result = gnssHal->getExtensionGnssConfiguration([](const sp<IGnssConfiguration>& configIface) {
+            gnssConfigurationIface = configIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssConfiguration");
+        }
+
+        result = gnssHal->getExtensionGnssGeofencing([](const sp<IGnssGeofencing>& geofenceIface) {
+            gnssGeofencingIface = geofenceIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssGeofencing");
+        }
+
+    } else {
+      ALOGE("Unable to get GPS service\n");
+    }
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
+    ProcessState::self()->startThreadPool();
+}
+
+static jboolean android_location_GnssLocationProvider_is_supported(
+        JNIEnv* /* env */, jclass /* clazz */) {
+    return (gnssHal != nullptr) ?  JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
+        JNIEnv* /* env */, jclass /* clazz */) {
+    return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
+        JNIEnv* /* env */, jclass /* jclazz */) {
+    return (gnssConfigurationIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
+    /*
+     * This must be set before calling into the HAL library.
+     */
+    if (!mCallbacksObj)
+        mCallbacksObj = env->NewGlobalRef(obj);
+
+    sp<IGnssCallback> gnssCbIface = new GnssCallback();
+    /*
+     * Fail if the main interface fails to initialize
+     */
+    if (gnssHal == nullptr) {
+        ALOGE("Unable to Initialize GNSS HAL\n");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssHal->setCallback(gnssCbIface);
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("SetCallback for Gnss Interface fails\n");
+        return JNI_FALSE;
+    }
+
+    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
+    if (gnssXtraIface == nullptr) {
+        ALOGE("Unable to initialize GNSS Xtra interface\n");
+    }
+
+    result = gnssXtraIface->setCallback(gnssXtraCbIface);
+    if ((!result) || (!result.getStatus().isOk())) {
+        gnssXtraIface = nullptr;
+        ALOGE("SetCallback for Gnss Xtra Interface fails\n");
+    }
+
+    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
+    if (agnssIface != nullptr) {
+        agnssIface->setCallback(aGnssCbIface);
+    } else {
+        ALOGE("Unable to Initialize AGnss interface\n");
+    }
+
+    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
+    if (gnssGeofencingIface != nullptr) {
+      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
+    } else {
+        ALOGE("Unable to initialize GNSS Geofencing interface\n");
+    }
+
+    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
+    if (gnssNiCbIface != nullptr) {
+        gnssNiIface->setCallback(gnssNiCbIface);
+    } else {
+        ALOGE("Unable to initialize GNSS NI interface\n");
+    }
+
+    return JNI_TRUE;
+}
+
+static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) {
+    if (gnssHal != nullptr) {
+        gnssHal->cleanup();
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
+        jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
+        jint preferred_time) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->setPositionMode(static_cast<IGnss::GnssPositionMode>(mode),
+                                     static_cast<IGnss::GnssPositionRecurrence>(recurrence),
+                                     min_interval,
+                                     preferred_accuracy,
+                                     preferred_time);
+        if (!result.getStatus().isOk()) {
+            ALOGE("%s: GNSS setPositionMode failed\n", __func__);
+            return JNI_FALSE;
+        } else {
+            return result;
+        }
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->start();
+        if (!result.getStatus().isOk()) {
+            return JNI_FALSE;
+        } else {
+            return result;
+        }
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->stop();
+        if (!result.getStatus().isOk()) {
+            return JNI_FALSE;
+        } else {
+            return result;
+        }
+    } else {
+        return JNI_FALSE;
+    }
+}
+static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
+                                                                    jobject /* obj */,
+                                                                    jint flags) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->deleteAidingData(static_cast<IGnss::GnssAidingData>(flags));
+        if (!result.getStatus().isOk()) {
+            ALOGE("Error in deleting aiding data");
+        }
+    }
+}
+
+/*
+ * This enum is used by the read_sv_status method to combine the svid,
+ * constellation and svFlag fields.
+ */
+enum ShiftWidth: uint8_t {
+    SVID_SHIFT_WIDTH = 7,
+    CONSTELLATION_TYPE_SHIFT_WIDTH = 3
+};
+
+static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
+        jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
+        jfloatArray azumArray) {
+    /*
+     * This method should only be called from within a call to reportSvStatus.
+     */
+    jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
+    jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
+    jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
+    jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
+
+    /*
+     * Read GNSS SV info.
+     */
+    for (size_t i = 0; i < GnssCallback::sGnssSvListSize; ++i) {
+        const IGnssCallback::GnssSvInfo& info = GnssCallback::sGnssSvList[i];
+        svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
+            (static_cast<uint32_t>(info.constellation) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+            static_cast<uint32_t>(info.svFlag);
+        cn0s[i] = info.cN0Dbhz;
+        elev[i] = info.elevationDegrees;
+        azim[i] = info.azimuthDegrees;
+    }
+
+    env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
+    env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
+    env->ReleaseFloatArrayElements(elevArray, elev, 0);
+    env->ReleaseFloatArrayElements(azumArray, azim, 0);
+    return static_cast<jint>(GnssCallback::sGnssSvListSize);
+}
+
+static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
+        JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid) {
+    IAGnssRil::AGnssRefLocation location;
+
+    if (agnssRilIface == nullptr) {
+        ALOGE("No AGPS RIL interface in agps_set_reference_location_cellid");
+        return;
+    }
+
+    switch (static_cast<IAGnssRil::AGnssRefLocationType>(type)) {
+        case IAGnssRil::AGnssRefLocationType::GSM_CELLID:
+        case IAGnssRil::AGnssRefLocationType::UMTS_CELLID:
+          location.type = static_cast<IAGnssRil::AGnssRefLocationType>(type);
+          location.cellID.mcc = mcc;
+          location.cellID.mnc = mnc;
+          location.cellID.lac = lac;
+          location.cellID.cid = cid;
+          break;
+        default:
+            ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).", __FUNCTION__, __LINE__);
+            return;
+            break;
+    }
+
+    agnssRilIface->setRefLocation(location);
+}
+
+static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
+                                                             jint type, jstring  setid_string) {
+    if (agnssRilIface == nullptr) {
+        ALOGE("no AGPS RIL interface in agps_set_id");
+        return;
+    }
+
+    const char *setid = env->GetStringUTFChars(setid_string, NULL);
+    agnssRilIface->setSetId((IAGnssRil::SetIDType)type, setid);
+    env->ReleaseStringUTFChars(setid_string, setid);
+}
+
+static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
+                                            jbyteArray nmeaArray, jint buffer_size) {
+    // this should only be called from within a call to reportNmea
+    jbyte* nmea = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(nmeaArray, 0));
+    int length = GnssCallback::sNmeaStringLength;
+    if (length > buffer_size)
+        length = buffer_size;
+    memcpy(nmea, GnssCallback::sNmeaString, length);
+    env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
+    return (jint) length;
+}
+
+static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
+        jlong time, jlong timeReference, jint uncertainty) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->injectTime(time, timeReference, uncertainty);
+        if (!result || !result.getStatus().isOk()) {
+            ALOGE("%s: Gnss injectTime() failed", __func__);
+        }
+    }
+}
+
+static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
+        jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->injectLocation(latitude, longitude, accuracy);
+        if (!result || !result.getStatus().isOk()) {
+            ALOGE("%s: Gnss injectLocation() failed", __func__);
+        }
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_supports_xtra(
+        JNIEnv* /* env */, jobject /* obj */) {
+    return (gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
+        jbyteArray data, jint length) {
+    if (gnssXtraIface == nullptr) {
+        ALOGE("XTRA Interface not supported");
+        return;
+    }
+
+    jbyte* bytes = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(data, 0));
+    gnssXtraIface->injectXtraData(std::string((const char*)bytes, length));
+    env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_open(
+        JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) {
+    if (agnssIface == nullptr) {
+        ALOGE("no AGPS interface in agps_data_conn_open");
+        return;
+    }
+    if (apn == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    const char *apnStr = env->GetStringUTFChars(apn, NULL);
+
+    auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to set APN and its IP type", __func__);
+    }
+    env->ReleaseStringUTFChars(apn, apnStr);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
+                                                                       jobject /* obj */) {
+    if (agnssIface == nullptr) {
+        ALOGE("%s: AGPS interface not supported", __func__);
+        return;
+    }
+
+    auto result = agnssIface->dataConnClosed();
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to close AGnss data connection", __func__);
+    }
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
+                                                                       jobject /* obj */) {
+    if (agnssIface == nullptr) {
+        ALOGE("%s: AGPS interface not supported", __func__);
+        return;
+    }
+
+    auto result = agnssIface->dataConnFailed();
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
+    }
+}
+
+static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
+        jint type, jstring hostname, jint port) {
+    if (agnssIface == nullptr) {
+        ALOGE("no AGPS interface in set_agps_server");
+        return;
+    }
+
+    const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
+    auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
+                                       c_hostname,
+                                       port);
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to set AGnss host name and port", __func__);
+    }
+
+    env->ReleaseStringUTFChars(hostname, c_hostname);
+}
+
+static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
+      jobject /* obj */, jint notifId, jint response) {
+    if (gnssNiIface == nullptr) {
+        ALOGE("no NI interface in send_ni_response");
+        return;
+    }
+
+    gnssNiIface->respond(notifId, static_cast<IGnssNiCallback::GnssUserResponseType>(response));
+}
+
+static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
+                                                                       jobject /* obj */) {
+    jstring result = NULL;
+    /*
+     * TODO(b/33089503) : Create a jobject to represent GnssDebug.
+     */
+    if (gnssDebugIface != nullptr) {
+        IGnssDebug::DebugData data;
+        gnssDebugIface->getDebugData([&data](const IGnssDebug::DebugData& debugData) {
+            data = debugData;
+        });
+
+        std::stringstream internalState;
+        if (data.position.valid) {
+            internalState << "Gnss Location Data:: LatitudeDegrees: " << data.position.latitudeDegrees
+                          << ", LongitudeDegrees: " << data.position.longitudeDegrees
+                          << ", altitudeMeters: " << data.position.altitudeMeters
+                          << ", accuracyMeters: " << data.position.accuracyMeters
+                          << ", ageSeconds: " << data.position.ageSeconds << std::endl;
+        }
+
+        if (data.time.valid) {
+            internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate
+                          << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs << std::endl;
+        }
+
+        if (data.satelliteDataArray.size() != 0) {
+            internalState << "Satellite Data:: ";
+        }
+
+        for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
+            internalState << "svid: " << data.satelliteDataArray[i].svid
+                          << ", constellation: "
+                          << static_cast<uint32_t>(data.satelliteDataArray[i].constellation)
+                          << ", ephemerisType: "
+                          << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisType)
+                          << ", ephemerisAgeSeconds: "
+                          << data.satelliteDataArray[i].ephemerisAgeSeconds << std::endl;
+        }
+        result = env->NewStringUTF(internalState.str().c_str());
+    }
+    return result;
+}
+
+static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env,
+                                                                       jobject /* obj */,
+                                                                       jboolean connected,
+                                                                       jint type,
+                                                                       jboolean roaming,
+                                                                       jboolean available,
+                                                                       jstring extraInfo,
+                                                                       jstring apn) {
+    if (agnssRilIface != nullptr) {
+        auto result = agnssRilIface->updateNetworkState(connected,
+                                                       static_cast<IAGnssRil::NetworkType>(type),
+                                                       roaming);
+        if ((!result) || (!result.getStatus().isOk())) {
+            ALOGE("updateNetworkState failed");
+        }
+
+        const char *c_apn = env->GetStringUTFChars(apn, NULL);
+        result = agnssRilIface->updateNetworkAvailability(available, c_apn);
+        if ((!result) || (!result.getStatus().isOk())) {
+            ALOGE("updateNetworkAvailability failed");
+        }
+
+        env->ReleaseStringUTFChars(apn, c_apn);
+    } else {
+        ALOGE("AGnssRilInterface does not exist");
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_is_geofence_supported(
+        JNIEnv* /* env */, jobject /* obj */) {
+    return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId, jdouble latitude, jdouble longitude, jdouble radius,
+        jint last_transition, jint monitor_transition, jint notification_responsiveness,
+        jint unknown_timer) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->addGeofence(
+                geofenceId, latitude, longitude, radius,
+                static_cast<IGnssGeofenceCallback::GeofenceTransition>(last_transition),
+                monitor_transition, notification_responsiveness, unknown_timer);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence Interface not available");
+    }
+    return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->removeGeofence(geofenceId);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence interface not available");
+    }
+    return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence interface not available");
+    }
+    return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId, jint monitor_transition) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence interface not available");
+    }
+    return JNI_FALSE;
+}
+
 static jboolean android_location_GnssLocationProvider_is_measurement_supported(
-        JNIEnv* env,
-        jclass clazz) {
-    if (sGpsMeasurementInterface != NULL) {
+    JNIEnv* env, jclass clazz) {
+    if (gnssMeasurementIface != nullptr) {
         return JNI_TRUE;
     }
+
     return JNI_FALSE;
 }
 
 static jboolean android_location_GnssLocationProvider_start_measurement_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsMeasurementInterface == NULL) {
-        ALOGE("Measurement interface is not available.");
+    if (gnssMeasurementIface == nullptr) {
+        ALOGE("GNSS Measurement interface is not available.");
         return JNI_FALSE;
     }
 
-    int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
-    if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
+    sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
+    IGnssMeasurement::GnssMeasurementStatus result = gnssMeasurementIface->setCallback(cbIface);
+    if (result != IGnssMeasurement::GnssMeasurementStatus::SUCCESS) {
+        ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
+              static_cast<int32_t>(result));
         return JNI_FALSE;
+    } else {
+      ALOGD("gnss measurement infc has been enabled");
     }
 
     return JNI_TRUE;
@@ -1464,104 +1464,19 @@
 static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsMeasurementInterface == NULL) {
+    if (gnssMeasurementIface == nullptr) {
         ALOGE("Measurement interface not available");
         return JNI_FALSE;
     }
 
-    sGpsMeasurementInterface->close();
-    return JNI_TRUE;
+    auto result = gnssMeasurementIface->close();
+    return boolToJbool(result.getStatus().isOk());
 }
 
-static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
-    size_t dataLength = message->data_length;
-    uint8_t* data = message->data;
-    if (dataLength == 0 || data == NULL) {
-        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
-        return NULL;
-    }
-    JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Svid, static_cast<int32_t>(message->prn));
-    if (message->prn >=1 && message->prn <= 32) {
-        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
-        // Legacy driver doesn't set the higher byte to constellation type
-        // correctly. Set the higher byte to 'GPS'.
-        SET(Type, static_cast<int32_t>(message->type | 0x0100));
-    } else {
-        ALOGD("Unknown constellation type with Svid = %d.", message->prn);
-        SET(ConstellationType,
-            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
-        SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
-    }
-    SET(MessageId, static_cast<int32_t>(message->message_id));
-    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
-    object.callSetter("setData", data, dataLength);
-    SET(Status, static_cast<int32_t>(message->status));
-    return object.get();
-}
-
-static jobject translate_gnss_navigation_message(
-        JNIEnv* env, GnssNavigationMessage* message) {
-    size_t dataLength = message->data_length;
-    uint8_t* data = message->data;
-    if (dataLength == 0 || data == NULL) {
-        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
-        return NULL;
-    }
-    JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Type, static_cast<int32_t>(message->type));
-    SET(Svid, static_cast<int32_t>(message->svid));
-    SET(MessageId, static_cast<int32_t>(message->message_id));
-    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
-    object.callSetter("setData", data, dataLength);
-    SET(Status, static_cast<int32_t>(message->status));
-    return object.get();
-}
-
-static void navigation_message_callback(GpsNavigationMessage* message) {
-    if (message == NULL) {
-        ALOGE("Invalid Navigation Message provided to callback");
-        return;
-    }
-    if (message->size != sizeof(GpsNavigationMessage)) {
-        ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
-        return;
-    }
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject navigationMessage = translate_gps_navigation_message(env, message);
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportNavigationMessages,
-                        navigationMessage);
-    env->DeleteLocalRef(navigationMessage);
-}
-
-static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
-    if (message == NULL) {
-        ALOGE("Invalid Navigation Message provided to callback");
-        return;
-    }
-    if (message->size != sizeof(GnssNavigationMessage)) {
-        ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
-        return;
-    }
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject navigationMessage = translate_gnss_navigation_message(env, message);
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportNavigationMessages,
-                        navigationMessage);
-    env->DeleteLocalRef(navigationMessage);
-}
-
-GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
-    sizeof(GpsNavigationMessageCallbacks),
-    navigation_message_callback,
-    gnss_navigation_message_callback,
-};
-
 static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
         JNIEnv* env,
         jclass clazz) {
-    if(sGpsNavigationMessageInterface != NULL) {
+    if (gnssNavigationMessageIface != nullptr) {
         return JNI_TRUE;
     }
     return JNI_FALSE;
@@ -1570,14 +1485,18 @@
 static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsNavigationMessageInterface == NULL) {
+    if (gnssNavigationMessageIface == nullptr) {
         ALOGE("Navigation Message interface is not available.");
         return JNI_FALSE;
     }
 
-    int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
-    if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
-        ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
+    sp<IGnssNavigationMessageCallback> gnssNavigationMessageCbIface =
+            new GnssNavigationMessageCallback();
+    IGnssNavigationMessage::GnssNavigationMessageStatus result =
+            gnssNavigationMessageIface->setCallback(gnssNavigationMessageCbIface);
+
+    if (result != IGnssNavigationMessage::GnssNavigationMessageStatus::SUCCESS) {
+        ALOGE("An error has been found in %s: %d", __FUNCTION__, static_cast<int32_t>(result));
         return JNI_FALSE;
     }
 
@@ -1587,127 +1506,255 @@
 static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsNavigationMessageInterface == NULL) {
+    if (gnssNavigationMessageIface == nullptr) {
         ALOGE("Navigation Message interface is not available.");
         return JNI_FALSE;
     }
 
-    sGpsNavigationMessageInterface->close();
-    return JNI_TRUE;
+    auto result = gnssNavigationMessageIface->close();
+    return boolToJbool(result.getStatus().isOk());
 }
 
-static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
-        jstring config_content)
-{
-    if (!sGnssConfigurationInterface) {
-        ALOGE("no GPS configuration interface in configuraiton_update");
-        return;
+static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNIEnv*,
+                                                                    jobject,
+                                                                    jint emergencySuplPdn) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
     }
-    const char *data = env->GetStringUTFChars(config_content, NULL);
-    ALOGD("GPS configuration:\n %s", data);
-    sGnssConfigurationInterface->configuration_update(
-            data, env->GetStringUTFLength(config_content));
-    env->ReleaseStringUTFChars(config_content, data);
+
+    auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_version(JNIEnv*,
+                                                                    jobject,
+                                                                    jint version) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+    auto result = gnssConfigurationIface->setSuplVersion(version);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_es(JNIEnv*,
+                                                                    jobject,
+                                                                    jint suplEs) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setSuplEs(suplEs);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_mode(JNIEnv*,
+                                                                    jobject,
+                                                                    jint mode) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setSuplMode(mode);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gps_lock(JNIEnv*,
+                                                                   jobject,
+                                                                   jint gpsLock) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setGpsLock(gpsLock);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_lpp_profile(JNIEnv*,
+                                                                   jobject,
+                                                                   jint lppProfile) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setLppProfile(lppProfile);
+
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_select(JNIEnv*,
+                                                                   jobject,
+                                                                   jint gnssPosProtocol) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
 }
 
 static const JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
-    {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
-    {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
+    {"class_init_native", "()V", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_class_init_native)},
+    {"native_is_supported", "()Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_is_supported)},
     {"native_is_agps_ril_supported", "()Z",
-            (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_is_agps_ril_supported)},
     {"native_is_gnss_configuration_supported", "()Z",
-            (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
-    {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
-    {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
+            reinterpret_cast<void *>(
+                    android_location_gpsLocationProvider_is_gnss_configuration_supported)},
+    {"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
+    {"native_cleanup", "()V", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_cleanup)},
     {"native_set_position_mode",
             "(IIIII)Z",
-            (void*)android_location_GnssLocationProvider_set_position_mode},
-    {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
-    {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
+            reinterpret_cast<void*>(android_location_GnssLocationProvider_set_position_mode)},
+    {"native_start", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_start)},
+    {"native_stop", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_stop)},
     {"native_delete_aiding_data",
             "(I)V",
-            (void*)android_location_GnssLocationProvider_delete_aiding_data},
+            reinterpret_cast<void*>(android_location_GnssLocationProvider_delete_aiding_data)},
     {"native_read_sv_status",
             "([I[F[F[F)I",
-            (void*)android_location_GnssLocationProvider_read_sv_status},
-    {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
-    {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_read_sv_status)},
+    {"native_read_nmea", "([BI)I", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_read_nmea)},
+    {"native_inject_time", "(JJI)V", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_inject_time)},
     {"native_inject_location",
             "(DDF)V",
-            (void*)android_location_GnssLocationProvider_inject_location},
-    {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_location)},
+    {"native_supports_xtra", "()Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_supports_xtra)},
     {"native_inject_xtra_data",
             "([BI)V",
-            (void*)android_location_GnssLocationProvider_inject_xtra_data},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_xtra_data)},
     {"native_agps_data_conn_open",
             "(Ljava/lang/String;I)V",
-            (void*)android_location_GnssLocationProvider_agps_data_conn_open},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_open)},
     {"native_agps_data_conn_closed",
             "()V",
-            (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_closed)},
     {"native_agps_data_conn_failed",
             "()V",
-            (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_failed)},
     {"native_agps_set_id",
             "(ILjava/lang/String;)V",
-            (void*)android_location_GnssLocationProvider_agps_set_id},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_set_id)},
     {"native_agps_set_ref_location_cellid",
             "(IIIII)V",
-            (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_agps_set_reference_location_cellid)},
     {"native_set_agps_server",
             "(ILjava/lang/String;I)V",
-            (void*)android_location_GnssLocationProvider_set_agps_server},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_agps_server)},
     {"native_send_ni_response",
             "(II)V",
-            (void*)android_location_GnssLocationProvider_send_ni_response},
-    {"native_agps_ni_message",
-            "([BI)V",
-            (void *)android_location_GnssLocationProvider_agps_send_ni_message},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_send_ni_response)},
     {"native_get_internal_state",
             "()Ljava/lang/String;",
-            (void*)android_location_GnssLocationProvider_get_internal_state},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
     {"native_update_network_state",
             "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
-            (void*)android_location_GnssLocationProvider_update_network_state },
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
     {"native_is_geofence_supported",
             "()Z",
-            (void*) android_location_GnssLocationProvider_is_geofence_supported},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_is_geofence_supported)},
     {"native_add_geofence",
             "(IDDDIIII)Z",
-            (void *)android_location_GnssLocationProvider_add_geofence},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_add_geofence)},
     {"native_remove_geofence",
             "(I)Z",
-            (void *)android_location_GnssLocationProvider_remove_geofence},
-    {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_remove_geofence)},
+    {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_pause_geofence)},
     {"native_resume_geofence",
             "(II)Z",
-            (void *)android_location_GnssLocationProvider_resume_geofence},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_resume_geofence)},
     {"native_is_measurement_supported",
             "()Z",
-            (void*) android_location_GnssLocationProvider_is_measurement_supported},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_is_measurement_supported)},
     {"native_start_measurement_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_start_measurement_collection},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_start_measurement_collection)},
     {"native_stop_measurement_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_stop_measurement_collection},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_stop_measurement_collection)},
     {"native_is_navigation_message_supported",
             "()Z",
-            (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_is_navigation_message_supported)},
     {"native_start_navigation_message_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_start_navigation_message_collection)},
     {"native_stop_navigation_message_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
-    {"native_configuration_update",
-            "(Ljava/lang/String;)V",
-            (void*)android_location_GnssLocationProvider_configuration_update},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_stop_navigation_message_collection)},
+    {"native_set_supl_es",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
+    {"native_set_supl_version",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_version)},
+    {"native_set_supl_mode",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_mode)},
+    {"native_set_lpp_profile",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_lpp_profile)},
+    {"native_set_gnss_pos_protocol_select",
+            "(I)Z",
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_set_gnss_pos_protocol_select)},
+    {"native_set_gps_lock",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_gps_lock)},
+    {"native_set_emergency_supl_pdn",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
 };
 
-int register_android_server_location_GnssLocationProvider(JNIEnv* env)
-{
+int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
     return jniRegisterNativeMethods(
             env,
             "com/android/server/location/GnssLocationProvider",
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 9f01773..99af9e8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -376,6 +376,7 @@
 
         @Override
         boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) {
+            assertNotNull(activity);
             return mEnabledActivityChecker.test(activity, userId);
         }
 
@@ -416,6 +417,11 @@
             // During tests, WTF is fatal.
             fail(message + "  exception: " + th + "\n" + Log.getStackTraceString(th));
         }
+
+        @Override
+        void verifyError() {
+            fail("Verify error");
+        }
     }
 
     /** ShortcutManager with injection override methods. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
index f773c15..1188bb7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
@@ -27,12 +27,16 @@
 import android.util.ArraySet;
 
 import com.android.internal.os.RoSystemProperties;
+import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
 import static junit.framework.Assert.assertTrue;
 
 
@@ -53,27 +57,34 @@
     }
 
     /**
-     * <p>This test ensures that all signature|privileged permissions are granted to core apps like
-     * systemui/settings. If CONTROL_PRIVAPP_PERMISSIONS is set, the test also verifies that
+     * <p>This test ensures that all signature|privileged permissions are granted to priv-apps.
+     * If CONTROL_PRIVAPP_PERMISSIONS_ENFORCE is set, the test also verifies that
      * granted permissions are whitelisted in {@link SystemConfig}
      */
     @Test
     @SmallTest
     @Presubmit
     public void testPrivAppPermissions() throws PackageManager.NameNotFoundException {
-        String[] testPackages = {"com.android.settings", "com.android.shell",
-                "com.android.systemui"};
-        for (String testPackage : testPackages) {
-            testPackagePrivAppPermission(testPackage);
+        List<PackageInfo> installedPackages = mPackageManager
+                .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES | GET_PERMISSIONS);
+        for (PackageInfo packageInfo : installedPackages) {
+            if (!packageInfo.applicationInfo.isPrivilegedApp()
+                    || PackageManagerService.PLATFORM_PACKAGE_NAME.equals(packageInfo.packageName)) {
+                continue;
+            }
+            testPackagePrivAppPermission(packageInfo);
         }
+
     }
 
-    private void testPackagePrivAppPermission(String testPackage)
+    private void testPackagePrivAppPermission(PackageInfo packageInfo)
             throws PackageManager.NameNotFoundException {
-        PackageInfo packageInfo = mPackageManager.getPackageInfo(testPackage,
-                PackageManager.GET_PERMISSIONS);
+        String packageName = packageInfo.packageName;
         ArraySet<String> privAppPermissions = SystemConfig.getInstance()
-                .getPrivAppPermissions(testPackage);
+                .getPrivAppPermissions(packageName);
+        if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) {
+            return;
+        }
         for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
             String pName = packageInfo.requestedPermissions[i];
             int protectionLevel;
@@ -89,13 +100,14 @@
             if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
                 boolean granted = (packageInfo.requestedPermissionsFlags[i]
                         & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
-                assertTrue("Permission " + pName + " should be granted to " + testPackage, granted);
+                assertTrue("Permission " + pName + " should be granted to " + packageName, granted);
                 // if privapp permissions are enforced, platform permissions must be whitelisted
                 // in SystemConfig
                 if (platformPermission && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                     assertTrue("Permission " + pName
-                                    + " should be declared in the xml file for package "
-                                    + testPackage,
+                                    + " should be declared in privapp-permissions-platform.xml "
+                                    + "or privapp-permissions-<product>.xml file for package "
+                                    + packageName,
                             privAppPermissions.contains(pName));
                 }
             }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 74c1ca5..97bcaf0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1292,7 +1292,43 @@
                     /* activity =*/ null, /* flags */ 0), getCallingUser());
                 });
 
-        // TODO More tests: pinned but dynamic.
+        // Make sure floating shortcuts don't match with an activity.
+        // At this point, s1 is dynamic and pinned, so it still has a target activity.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildQuery(
+                    /* time =*/ 0,
+                    CALLING_PACKAGE_2,
+                    /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
+                            ShortcutActivity2.class.getName()),
+                    ShortcutQuery.FLAG_GET_PINNED),
+                    getCallingUser()))
+                    .haveIds("s3")
+                    .areAllPinned()
+                    .areAllDynamic()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_2,
+                            ShortcutActivity2.class.getName()));
+        });
+
+        // Now remove as a dynamic, making it floating.
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            mManager.removeDynamicShortcuts(list("s3"));
+            assertWith(mManager.getPinnedShortcuts())
+                    .selectFloating()
+                    .areAllWithNoActivity();
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // This shouldn't match now.
+            assertWith(mLauncherApps.getShortcuts(buildQuery(
+                    /* time =*/ 0,
+                    CALLING_PACKAGE_2,
+                    /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
+                            ShortcutActivity2.class.getName()),
+                    ShortcutQuery.FLAG_GET_PINNED),
+                    getCallingUser()))
+                    .isEmpty();
+        });
+
     }
 
     public void testGetShortcuts_shortcutKinds() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index d25923c..7486858 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1052,7 +1052,7 @@
 
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
-        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+        assertNull(si.getActivity()); // It's now floating, so no target activity.
         assertEquals(null, si.getIcon());
         assertEquals("title", si.getTitle());
         assertEquals("text", si.getText());
@@ -1116,7 +1116,7 @@
 
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
-        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+        assertNull(si.getActivity()); // It's now floating, so no target activity.
         assertEquals(null, si.getIcon());
         assertEquals(10, si.getTitleResId());
         assertEquals("r10", si.getTitleResName());
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 1fe5cb7..6e74deb 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -764,6 +764,12 @@
                     filter(mList, ShortcutInfo::isPinned));
         }
 
+        public ShortcutListAsserter selectFloating() {
+            return new ShortcutListAsserter(this,
+                    filter(mList, (si -> si.isPinned()
+                            && !(si.isDynamic() || si.isDeclaredInManifest()))));
+        }
+
         public ShortcutListAsserter selectByActivity(ComponentName activity) {
             return new ShortcutListAsserter(this,
                     ShortcutManagerTestUtils.filterByActivity(mList, activity));
@@ -895,6 +901,11 @@
             return this;
         }
 
+        public ShortcutListAsserter areAllWithNoActivity() {
+            forAllShortcuts(s -> assertNull("id=" + s.getId(), s.getActivity()));
+            return this;
+        }
+
         public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
             boolean found = false;
             for (int i = 0; i < mList.size(); i++) {