Merge "Moving the LoadedApk class to its own file."
diff --git a/Android.mk b/Android.mk
index e68b310..22323c5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -182,6 +182,7 @@
 	core/java/android/hardware/display/IVirtualDisplayCallback.aidl \
 	core/java/android/hardware/fingerprint/IFingerprintService.aidl \
 	core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl \
+	core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl \
 	core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \
 	core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \
 	core/java/android/hardware/hdmi/IHdmiControlService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 0ca9875..869d148 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -349,6 +349,7 @@
     field public static final int calendarTextColor = 16843931; // 0x101049b
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
+    field public static final int canCaptureFingerprintGestures = 16844111; // 0x101054f
     field public static final int canControlMagnification = 16844039; // 0x1010507
     field public static final int canPerformGestures = 16844045; // 0x101050d
     field public static final int canRecord = 16844060; // 0x101051c
@@ -2692,6 +2693,7 @@
     method public final void disableSelf();
     method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
@@ -2783,6 +2785,7 @@
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 64; // 0x40
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
     field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
@@ -2798,6 +2801,7 @@
     field public static final int FEEDBACK_HAPTIC = 2; // 0x2
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
     field public static final int FEEDBACK_VISUAL = 8; // 0x8
+    field public static final int FLAG_CAPTURE_FINGERPRINT_GESTURES = 512; // 0x200
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
@@ -2812,6 +2816,22 @@
     field public java.lang.String[] packageNames;
   }
 
+  public final class FingerprintGestureController {
+    method public boolean isGestureDetectionAvailable();
+    method public void registerFingerprintGestureCallback(android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback, android.os.Handler);
+    method public void unregisterFingerprintGestureCallback(android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback);
+    field public static final int FINGERPRINT_GESTURE_SWIPE_DOWN = 8; // 0x8
+    field public static final int FINGERPRINT_GESTURE_SWIPE_LEFT = 2; // 0x2
+    field public static final int FINGERPRINT_GESTURE_SWIPE_RIGHT = 1; // 0x1
+    field public static final int FINGERPRINT_GESTURE_SWIPE_UP = 4; // 0x4
+  }
+
+  public static abstract class FingerprintGestureController.FingerprintGestureCallback {
+    ctor public FingerprintGestureController.FingerprintGestureCallback();
+    method public void onGesture(int);
+    method public void onGestureDetectionAvailabilityChanged(boolean);
+  }
+
   public final class GestureDescription {
     method public static long getMaxGestureDuration();
     method public static int getMaxStrokeCount();
@@ -4516,6 +4536,7 @@
     method public final boolean isInLayout();
     method public final boolean isRemoving();
     method public final boolean isResumed();
+    method public final boolean isStateSaved();
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
@@ -4754,6 +4775,7 @@
     method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
     method public abstract boolean isAddToBackStackAllowed();
     method public abstract boolean isEmpty();
+    method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable);
     method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
     method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
     method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
@@ -32965,7 +32987,7 @@
     ctor public ContactsContract.Intents();
     field public static final java.lang.String ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS = "android.provider.action.VOICE_SEND_MESSAGE_TO_CONTACTS";
     field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
-    field public static final deprecated java.lang.String CONTACTS_DATABASE_CREATED = "android.provider.Contacts.DATABASE_CREATED";
+    field public static final java.lang.String CONTACTS_DATABASE_CREATED = "android.provider.Contacts.DATABASE_CREATED";
     field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
     field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID";
@@ -33078,7 +33100,6 @@
     field public static final java.lang.String DATABASE_CREATION_TIMESTAMP = "database_creation_timestamp";
     field public static final java.lang.String STATUS = "status";
     field public static final int STATUS_BUSY = 1; // 0x1
-    field public static final android.net.Uri STATUS_CHANGE_NOTIFICATION_CONTENT_URI;
     field public static final int STATUS_EMPTY = 2; // 0x2
     field public static final int STATUS_NORMAL = 0; // 0x0
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 594fa2e..aa49f23 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -461,6 +461,7 @@
     field public static final int calendarTextColor = 16843931; // 0x101049b
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
+    field public static final int canCaptureFingerprintGestures = 16844111; // 0x101054f
     field public static final int canControlMagnification = 16844039; // 0x1010507
     field public static final int canPerformGestures = 16844045; // 0x101050d
     field public static final int canRecord = 16844060; // 0x101051c
@@ -2811,6 +2812,7 @@
     method public final void disableSelf();
     method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
@@ -2902,6 +2904,7 @@
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 64; // 0x40
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
     field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
@@ -2917,6 +2920,7 @@
     field public static final int FEEDBACK_HAPTIC = 2; // 0x2
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
     field public static final int FEEDBACK_VISUAL = 8; // 0x8
+    field public static final int FLAG_CAPTURE_FINGERPRINT_GESTURES = 512; // 0x200
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
@@ -2931,6 +2935,22 @@
     field public java.lang.String[] packageNames;
   }
 
+  public final class FingerprintGestureController {
+    method public boolean isGestureDetectionAvailable();
+    method public void registerFingerprintGestureCallback(android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback, android.os.Handler);
+    method public void unregisterFingerprintGestureCallback(android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback);
+    field public static final int FINGERPRINT_GESTURE_SWIPE_DOWN = 8; // 0x8
+    field public static final int FINGERPRINT_GESTURE_SWIPE_LEFT = 2; // 0x2
+    field public static final int FINGERPRINT_GESTURE_SWIPE_RIGHT = 1; // 0x1
+    field public static final int FINGERPRINT_GESTURE_SWIPE_UP = 4; // 0x4
+  }
+
+  public static abstract class FingerprintGestureController.FingerprintGestureCallback {
+    ctor public FingerprintGestureController.FingerprintGestureCallback();
+    method public void onGesture(int);
+    method public void onGestureDetectionAvailabilityChanged(boolean);
+  }
+
   public final class GestureDescription {
     method public static long getMaxGestureDuration();
     method public static int getMaxStrokeCount();
@@ -4676,6 +4696,7 @@
     method public final boolean isInLayout();
     method public final boolean isRemoving();
     method public final boolean isResumed();
+    method public final boolean isStateSaved();
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
@@ -4914,6 +4935,7 @@
     method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
     method public abstract boolean isAddToBackStackAllowed();
     method public abstract boolean isEmpty();
+    method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable);
     method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
     method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
     method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
@@ -33725,7 +33747,6 @@
     method public final void attachBaseContext(android.content.Context);
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract java.util.List<android.content.pm.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(java.lang.String);
-    method public abstract java.util.List<android.content.pm.ApplicationInfo> onGetAppsUsingPermissions(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.permissionpresenterservice.RuntimePermissionPresenterService";
   }
 
@@ -35835,7 +35856,7 @@
     ctor public ContactsContract.Intents();
     field public static final java.lang.String ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS = "android.provider.action.VOICE_SEND_MESSAGE_TO_CONTACTS";
     field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
-    field public static final deprecated java.lang.String CONTACTS_DATABASE_CREATED = "android.provider.Contacts.DATABASE_CREATED";
+    field public static final java.lang.String CONTACTS_DATABASE_CREATED = "android.provider.Contacts.DATABASE_CREATED";
     field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
     field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID";
@@ -35978,7 +35999,6 @@
     field public static final java.lang.String DATABASE_CREATION_TIMESTAMP = "database_creation_timestamp";
     field public static final java.lang.String STATUS = "status";
     field public static final int STATUS_BUSY = 1; // 0x1
-    field public static final android.net.Uri STATUS_CHANGE_NOTIFICATION_CONTENT_URI;
     field public static final int STATUS_EMPTY = 2; // 0x2
     field public static final int STATUS_NORMAL = 0; // 0x0
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 0261629..86936d3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -349,6 +349,7 @@
     field public static final int calendarTextColor = 16843931; // 0x101049b
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
+    field public static final int canCaptureFingerprintGestures = 16844111; // 0x101054f
     field public static final int canControlMagnification = 16844039; // 0x1010507
     field public static final int canPerformGestures = 16844045; // 0x101050d
     field public static final int canRecord = 16844060; // 0x101051c
@@ -2692,6 +2693,7 @@
     method public final void disableSelf();
     method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
@@ -2783,6 +2785,7 @@
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 64; // 0x40
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
     field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
@@ -2798,6 +2801,7 @@
     field public static final int FEEDBACK_HAPTIC = 2; // 0x2
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
     field public static final int FEEDBACK_VISUAL = 8; // 0x8
+    field public static final int FLAG_CAPTURE_FINGERPRINT_GESTURES = 512; // 0x200
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
@@ -2812,6 +2816,22 @@
     field public java.lang.String[] packageNames;
   }
 
+  public final class FingerprintGestureController {
+    method public boolean isGestureDetectionAvailable();
+    method public void registerFingerprintGestureCallback(android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback, android.os.Handler);
+    method public void unregisterFingerprintGestureCallback(android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback);
+    field public static final int FINGERPRINT_GESTURE_SWIPE_DOWN = 8; // 0x8
+    field public static final int FINGERPRINT_GESTURE_SWIPE_LEFT = 2; // 0x2
+    field public static final int FINGERPRINT_GESTURE_SWIPE_RIGHT = 1; // 0x1
+    field public static final int FINGERPRINT_GESTURE_SWIPE_UP = 4; // 0x4
+  }
+
+  public static abstract class FingerprintGestureController.FingerprintGestureCallback {
+    ctor public FingerprintGestureController.FingerprintGestureCallback();
+    method public void onGesture(int);
+    method public void onGestureDetectionAvailabilityChanged(boolean);
+  }
+
   public final class GestureDescription {
     method public static long getMaxGestureDuration();
     method public static int getMaxStrokeCount();
@@ -4526,6 +4546,7 @@
     method public final boolean isInLayout();
     method public final boolean isRemoving();
     method public final boolean isResumed();
+    method public final boolean isStateSaved();
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
@@ -4764,6 +4785,7 @@
     method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
     method public abstract boolean isAddToBackStackAllowed();
     method public abstract boolean isEmpty();
+    method public abstract android.app.FragmentTransaction postOnCommit(java.lang.Runnable);
     method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
     method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
     method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
@@ -33083,7 +33105,7 @@
     ctor public ContactsContract.Intents();
     field public static final java.lang.String ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS = "android.provider.action.VOICE_SEND_MESSAGE_TO_CONTACTS";
     field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
-    field public static final deprecated java.lang.String CONTACTS_DATABASE_CREATED = "android.provider.Contacts.DATABASE_CREATED";
+    field public static final java.lang.String CONTACTS_DATABASE_CREATED = "android.provider.Contacts.DATABASE_CREATED";
     field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
     field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID";
@@ -33196,7 +33218,6 @@
     field public static final java.lang.String DATABASE_CREATION_TIMESTAMP = "database_creation_timestamp";
     field public static final java.lang.String STATUS = "status";
     field public static final int STATUS_BUSY = 1; // 0x1
-    field public static final android.net.Uri STATUS_CHANGE_NOTIFICATION_CONTENT_URI;
     field public static final int STATUS_EMPTY = 2; // 0x2
     field public static final int STATUS_NORMAL = 0; // 0x0
   }
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 3e5cc54..a036b6a 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -20,11 +20,13 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.graphics.Region;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -33,11 +35,9 @@
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
@@ -362,19 +362,22 @@
     private static final String LOG_TAG = "AccessibilityService";
 
     /**
+     * Interface used by IAccessibilityServiceWrapper to call the service from its main thread.
      * @hide
      */
     public interface Callbacks {
-        public void onAccessibilityEvent(AccessibilityEvent event);
-        public void onInterrupt();
-        public void onServiceConnected();
-        public void init(int connectionId, IBinder windowToken);
-        public boolean onGesture(int gestureId);
-        public boolean onKeyEvent(KeyEvent event);
-        public void onMagnificationChanged(@NonNull Region region,
+        void onAccessibilityEvent(AccessibilityEvent event);
+        void onInterrupt();
+        void onServiceConnected();
+        void init(int connectionId, IBinder windowToken);
+        boolean onGesture(int gestureId);
+        boolean onKeyEvent(KeyEvent event);
+        void onMagnificationChanged(@NonNull Region region,
                 float scale, float centerX, float centerY);
-        public void onSoftKeyboardShowModeChanged(int showMode);
-        public void onPerformGestureResult(int sequence, boolean completedSuccessfully);
+        void onSoftKeyboardShowModeChanged(int showMode);
+        void onPerformGestureResult(int sequence, boolean completedSuccessfully);
+        void onFingerprintCapturingGesturesChanged(boolean active);
+        void onFingerprintGesture(int gesture);
     }
 
     /**
@@ -404,6 +407,8 @@
 
     private final Object mLock = new Object();
 
+    private FingerprintGestureController mFingerprintGestureController;
+
     /**
      * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
      *
@@ -598,6 +603,32 @@
     }
 
     /**
+     * Get the controller for fingerprint gestures. This feature requires {@link
+     * AccessibilityServiceInfo#CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES}.
+     *
+     *<strong>Note: </strong> The service must be connected before this method is called.
+     *
+     * @return The controller for fingerprint gestures, or {@code null} if gestures are unavailable.
+     */
+    @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT)
+    public final @Nullable FingerprintGestureController getFingerprintGestureController() {
+        if (mFingerprintGestureController == null) {
+            FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
+            if ((fingerprintManager != null) && fingerprintManager.isHardwareDetected()) {
+                AccessibilityServiceInfo info = getServiceInfo();
+                int fingerprintCapabilityMask =
+                        AccessibilityServiceInfo.CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES;
+                if ((info.getCapabilities() & fingerprintCapabilityMask) != 0) {
+                    mFingerprintGestureController = new FingerprintGestureController(
+                            AccessibilityInteractionClient.getInstance()
+                                    .getConnection(mConnectionId));
+                }
+            }
+        }
+        return mFingerprintGestureController;
+    }
+
+    /**
      * Dispatch a gesture to the touch screen. Any gestures currently in progress, whether from
      * the user, this service, or another service, will be cancelled.
      * <p>
@@ -694,6 +725,22 @@
     }
 
     /**
+     * Callback for fingerprint gesture handling
+     * @param active If gesture detection is active
+     */
+    private void onFingerprintCapturingGesturesChanged(boolean active) {
+        getFingerprintGestureController().onGestureDetectionActiveChanged(active);
+    }
+
+    /**
+     * Callback for fingerprint gesture handling
+     * @param gesture The identifier for the gesture performed
+     */
+    private void onFingerprintGesture(int gesture) {
+        getFingerprintGestureController().onGesture(gesture);
+    }
+
+    /**
      * Used to control and query the state of display magnification.
      */
     public static final class MagnificationController {
@@ -1486,6 +1533,16 @@
             public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
                 AccessibilityService.this.onPerformGestureResult(sequence, completedSuccessfully);
             }
+
+            @Override
+            public void onFingerprintCapturingGesturesChanged(boolean active) {
+                AccessibilityService.this.onFingerprintCapturingGesturesChanged(active);
+            }
+
+            @Override
+            public void onFingerprintGesture(int gesture) {
+                AccessibilityService.this.onFingerprintGesture(gesture);
+            }
         });
     }
 
@@ -1506,6 +1563,8 @@
         private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
         private static final int DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED = 8;
         private static final int DO_GESTURE_COMPLETE = 9;
+        private static final int DO_ON_FINGERPRINT_ACTIVE_CHANGED = 10;
+        private static final int DO_ON_FINGERPRINT_GESTURE = 11;
 
         private final HandlerCaller mCaller;
 
@@ -1577,6 +1636,15 @@
             mCaller.sendMessage(message);
         }
 
+        public void onFingerprintCapturingGesturesChanged(boolean active) {
+            mCaller.sendMessage(mCaller.obtainMessageI(
+                    DO_ON_FINGERPRINT_ACTIVE_CHANGED, active ? 1 : 0));
+        }
+
+        public void onFingerprintGesture(int gesture) {
+            mCaller.sendMessage(mCaller.obtainMessageI(DO_ON_FINGERPRINT_GESTURE, gesture));
+        }
+
         @Override
         public void executeMessage(Message message) {
             switch (message.what) {
@@ -1675,6 +1743,12 @@
                     final boolean successfully = message.arg2 == 1;
                     mCallback.onPerformGestureResult(message.arg1, successfully);
                 } return;
+                case DO_ON_FINGERPRINT_ACTIVE_CHANGED: {
+                    mCallback.onFingerprintCapturingGesturesChanged(message.arg1 == 1);
+                } return;
+                case DO_ON_FINGERPRINT_GESTURE: {
+                    mCallback.onFingerprintGesture(message.arg1);
+                } return;
 
                 default :
                     Log.w(LOG_TAG, "Unknown message type " + message.what);
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index b76aeb7..18e57cb 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -25,6 +25,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -116,34 +117,13 @@
      */
     public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020;
 
-    private static final SparseArray<CapabilityInfo> sAvailableCapabilityInfos =
-            new SparseArray<CapabilityInfo>();
-    static {
-        sAvailableCapabilityInfos.put(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
-                new CapabilityInfo(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
-                        R.string.capability_title_canRetrieveWindowContent,
-                        R.string.capability_desc_canRetrieveWindowContent));
-        sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
-                new CapabilityInfo(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
-                        R.string.capability_title_canRequestTouchExploration,
-                        R.string.capability_desc_canRequestTouchExploration));
-        sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
-                new CapabilityInfo(CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
-                        R.string.capability_title_canRequestEnhancedWebAccessibility,
-                        R.string.capability_desc_canRequestEnhancedWebAccessibility));
-        sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
-                new CapabilityInfo(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
-                        R.string.capability_title_canRequestFilterKeyEvents,
-                        R.string.capability_desc_canRequestFilterKeyEvents));
-        sAvailableCapabilityInfos.put(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
-                new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
-                        R.string.capability_title_canControlMagnification,
-                        R.string.capability_desc_canControlMagnification));
-        sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES,
-                new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
-                        R.string.capability_title_canPerformGestures,
-                        R.string.capability_desc_canPerformGestures));
-    }
+    /**
+     * Capability: This accessibility service can capture gestures from the fingerprint sensor
+     * @see android.R.styleable#AccessibilityService_canCaptureFingerprintGestures
+     */
+    public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 0x00000040;
+
+    private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos;
 
     /**
      * Denotes spoken feedback.
@@ -326,6 +306,12 @@
      */
     public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080;
 
+    /**
+     * This flag requests that all fingerprint gestures be sent to the accessibility service.
+     * It is handled in {@link FingerprintGestureController}
+     */
+    public static final int FLAG_CAPTURE_FINGERPRINT_GESTURES = 0x00000200;
+
     /** {@hide} */
     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
 
@@ -535,6 +521,10 @@
                     .AccessibilityService_canPerformGestures, false)) {
                 mCapabilities |= CAPABILITY_CAN_PERFORM_GESTURES;
             }
+            if (asAttributes.getBoolean(com.android.internal.R.styleable
+                    .AccessibilityService_canCaptureFingerprintGestures, false)) {
+                mCapabilities |= CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES;
+            }
             TypedValue peekedValue = asAttributes.peekValue(
                     com.android.internal.R.styleable.AccessibilityService_description);
             if (peekedValue != null) {
@@ -946,6 +936,8 @@
                 return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS";
             case FLAG_ENABLE_ACCESSIBILITY_VOLUME:
                 return "FLAG_ENABLE_ACCESSIBILITY_VOLUME";
+            case FLAG_CAPTURE_FINGERPRINT_GESTURES:
+                return "FLAG_CAPTURE_FINGERPRINT_GESTURES";
             default:
                 return null;
         }
@@ -973,6 +965,8 @@
                 return "CAPABILITY_CAN_CONTROL_MAGNIFICATION";
             case CAPABILITY_CAN_PERFORM_GESTURES:
                 return "CAPABILITY_CAN_PERFORM_GESTURES";
+            case CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES:
+                return "CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES";
             default:
                 return "UNKNOWN";
         }
@@ -981,17 +975,29 @@
     /**
      * @hide
      * @return The list of {@link CapabilityInfo} objects.
+     * @deprecated The version that takes a context works better.
      */
     public List<CapabilityInfo> getCapabilityInfos() {
+        return getCapabilityInfos(null);
+    }
+
+    /**
+     * @hide
+     * @param context A valid context
+     * @return The list of {@link CapabilityInfo} objects.
+     */
+    public List<CapabilityInfo> getCapabilityInfos(Context context) {
         if (mCapabilities == 0) {
             return Collections.emptyList();
         }
         int capabilities = mCapabilities;
         List<CapabilityInfo> capabilityInfos = new ArrayList<CapabilityInfo>();
+        SparseArray<CapabilityInfo> capabilityInfoSparseArray =
+                getCapabilityInfoSparseArray(context);
         while (capabilities != 0) {
             final int capabilityBit = 1 << Integer.numberOfTrailingZeros(capabilities);
             capabilities &= ~capabilityBit;
-            CapabilityInfo capabilityInfo = sAvailableCapabilityInfos.get(capabilityBit);
+            CapabilityInfo capabilityInfo = capabilityInfoSparseArray.get(capabilityBit);
             if (capabilityInfo != null) {
                 capabilityInfos.add(capabilityInfo);
             }
@@ -999,6 +1005,44 @@
         return capabilityInfos;
     }
 
+    private static SparseArray<CapabilityInfo> getCapabilityInfoSparseArray(Context context) {
+        if (sAvailableCapabilityInfos == null) {
+            sAvailableCapabilityInfos = new SparseArray<CapabilityInfo>();
+            sAvailableCapabilityInfos.put(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
+                    new CapabilityInfo(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT,
+                            R.string.capability_title_canRetrieveWindowContent,
+                            R.string.capability_desc_canRetrieveWindowContent));
+            sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
+                    new CapabilityInfo(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION,
+                            R.string.capability_title_canRequestTouchExploration,
+                            R.string.capability_desc_canRequestTouchExploration));
+            sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
+                    new CapabilityInfo(CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
+                            R.string.capability_title_canRequestEnhancedWebAccessibility,
+                            R.string.capability_desc_canRequestEnhancedWebAccessibility));
+            sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
+                    new CapabilityInfo(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS,
+                            R.string.capability_title_canRequestFilterKeyEvents,
+                            R.string.capability_desc_canRequestFilterKeyEvents));
+            sAvailableCapabilityInfos.put(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
+                    new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
+                            R.string.capability_title_canControlMagnification,
+                            R.string.capability_desc_canControlMagnification));
+            sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES,
+                    new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
+                            R.string.capability_title_canPerformGestures,
+                            R.string.capability_desc_canPerformGestures));
+            if ((context == null)
+                    || context.getSystemService(FingerprintManager.class).isHardwareDetected()) {
+                sAvailableCapabilityInfos.put(CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES,
+                        new CapabilityInfo(CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES,
+                                R.string.capability_title_canCaptureFingerprintGestures,
+                                R.string.capability_desc_canCaptureFingerprintGestures));
+            }
+        }
+        return sAvailableCapabilityInfos;
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/accessibilityservice/FingerprintGestureController.java b/core/java/android/accessibilityservice/FingerprintGestureController.java
new file mode 100644
index 0000000..e203c6d
--- /dev/null
+++ b/core/java/android/accessibilityservice/FingerprintGestureController.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.accessibilityservice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * An {@link AccessibilityService} can capture gestures performed on a device's fingerprint
+ * sensor, as long as the device has a sensor capable of detecting gestures.
+ * <p>
+ * This capability must be declared by the service as
+ * {@link AccessibilityServiceInfo#CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES}. It also requires
+ * the permission {@link android.Manifest.permission#USE_FINGERPRINT}.
+ * <p>
+ * Because capturing fingerprint gestures may have side effects, services with the capability only
+ * capture gestures when {@link AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES} is set.
+ * <p>
+ * <strong>Note: </strong>The fingerprint sensor is used for authentication in critical use cases,
+ * so services must carefully design their user's experience when performing gestures on the sensor.
+ * When the sensor is in use by an app, for example, when authenticating or enrolling a user,
+ * the sensor will not detect gestures. Services need to ensure that users understand when the
+ * sensor is in-use for authentication to prevent users from authenticating unintentionally when
+ * trying to interact with the service. They can use
+ * {@link FingerprintGestureCallback#onGestureDetectionAvailabilityChanged(boolean)} to learn when
+ * gesture detection becomes unavailable.
+ * <p>
+ * Multiple accessibility services may listen for fingerprint gestures simultaneously, so services
+ * should provide a way for the user to disable the use of this feature so multiple services don't
+ * conflict with each other.
+ * <p>
+ * {@see android.hardware.fingerprint.FingerprintManager#isHardwareDetected}
+ */
+public final class FingerprintGestureController {
+    /** Identifier for a swipe right on the fingerprint sensor */
+    public static final int FINGERPRINT_GESTURE_SWIPE_RIGHT = 0x00000001;
+
+    /** Identifier for a swipe left on the fingerprint sensor */
+    public static final int FINGERPRINT_GESTURE_SWIPE_LEFT = 0x00000002;
+
+    /** Identifier for a swipe up on the fingerprint sensor */
+    public static final int FINGERPRINT_GESTURE_SWIPE_UP = 0x00000004;
+
+    /** Identifier for a swipe down on the fingerprint sensor */
+    public static final int FINGERPRINT_GESTURE_SWIPE_DOWN = 0x00000008;
+
+    private static final String LOG_TAG = "FingerprintGestureController";
+    private final Object mLock = new Object();
+    private final IAccessibilityServiceConnection mAccessibilityServiceConnection;
+
+    private final ArrayMap<FingerprintGestureCallback, Handler> mCallbackHandlerMap =
+            new ArrayMap<>(1);
+
+    /**
+     * @param connection The connection to use for system interactions
+     * @hide
+     */
+    @VisibleForTesting
+    public FingerprintGestureController(IAccessibilityServiceConnection connection) {
+        mAccessibilityServiceConnection = connection;
+    }
+
+    /**
+     * Gets if the fingerprint sensor's gesture detection is available.
+     *
+     * @return {@code true} if the sensor's gesture detection is available. {@code false} if it is
+     * not currently detecting gestures (for example, if it is enrolling a finger).
+     */
+    public boolean isGestureDetectionAvailable() {
+        try {
+            return mAccessibilityServiceConnection.isFingerprintGestureDetectionAvailable();
+        } catch (RemoteException re) {
+            Log.w(LOG_TAG, "Failed to check if fingerprint gestures are active", re);
+            re.rethrowFromSystemServer();
+            return false;
+        }
+    }
+
+    /**
+     * Register a callback to be informed of fingerprint sensor gesture events.
+     *
+     * @param callback The listener to be added.
+     * @param handler The handler to use for the callback. If {@code null}, callbacks will happen
+     * on the service's main thread.
+     */
+    public void registerFingerprintGestureCallback(
+            @NonNull FingerprintGestureCallback callback, @Nullable Handler handler) {
+        synchronized (mLock) {
+            mCallbackHandlerMap.put(callback, handler);
+        }
+    }
+
+    /**
+     * Unregister a listener added with {@link #registerFingerprintGestureCallback}.
+     *
+     * @param callback The callback to remove. Removing a callback that was never added has no
+     * effect.
+     */
+    public void unregisterFingerprintGestureCallback(FingerprintGestureCallback callback) {
+        synchronized (mLock) {
+            mCallbackHandlerMap.remove(callback);
+        }
+    }
+
+    /**
+     * Called when gesture detection becomes active or inactive
+     * @hide
+     */
+    public void onGestureDetectionActiveChanged(boolean active) {
+        final ArrayMap<FingerprintGestureCallback, Handler> handlerMap;
+        synchronized (mLock) {
+            handlerMap = new ArrayMap<>(mCallbackHandlerMap);
+        }
+        int numListeners = handlerMap.size();
+        for (int i = 0; i < numListeners; i++) {
+            FingerprintGestureCallback callback = handlerMap.keyAt(i);
+            Handler handler = handlerMap.valueAt(i);
+            if (handler != null) {
+                handler.post(() -> callback.onGestureDetectionAvailabilityChanged(active));
+            } else {
+                callback.onGestureDetectionAvailabilityChanged(active);
+            }
+        }
+    }
+
+    /**
+     * Called when gesture is detected.
+     * @hide
+     */
+    public void onGesture(int gesture) {
+        final ArrayMap<FingerprintGestureCallback, Handler> handlerMap;
+        synchronized (mLock) {
+            handlerMap = new ArrayMap<>(mCallbackHandlerMap);
+        }
+        int numListeners = handlerMap.size();
+        for (int i = 0; i < numListeners; i++) {
+            FingerprintGestureCallback callback = handlerMap.keyAt(i);
+            Handler handler = handlerMap.valueAt(i);
+            if (handler != null) {
+                handler.post(() -> callback.onGesture(gesture));
+            } else {
+                callback.onGesture(gesture);
+            }
+        }
+    }
+
+    /**
+     * Class that is called back when fingerprint gestures are being used for accessibility.
+     */
+    public abstract static class FingerprintGestureCallback {
+        /**
+         * Called when the fingerprint sensor's gesture detection becomes available or unavailable.
+         *
+         * @param available Whether or not the sensor's gesture detection is now available.
+         */
+        public void onGestureDetectionAvailabilityChanged(boolean available) {}
+
+        /**
+         * Called when the fingerprint sensor detects gestures.
+         *
+         * @param gesture The id of the gesture that was detected. For example,
+         * {@link #FINGERPRINT_GESTURE_SWIPE_RIGHT}.
+         */
+        public void onGesture(int gesture) {}
+    }
+}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index da16a65..3f778ad 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -46,4 +46,8 @@
     void onSoftKeyboardShowModeChanged(int showMode);
 
     void onPerformGestureResult(int sequence, boolean completedSuccessfully);
+
+    void onFingerprintCapturingGesturesChanged(boolean capturing);
+
+    void onFingerprintGesture(int gesture);
 }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 81cddba..5499bd5 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -89,4 +89,6 @@
     void setSoftKeyboardCallbackEnabled(boolean enabled);
 
     void sendGesture(int sequence, in ParceledListSlice gestureSteps);
+
+    boolean isFingerprintGestureDetectionAvailable();
 }
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 08ad976..4ebcc44 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -26,7 +26,7 @@
  * This is the superclass for classes which provide basic support for animations which can be
  * started, ended, and have <code>AnimatorListeners</code> added to them.
  */
-public abstract class Animator implements Cloneable, AnimationHandler.AnimationFrameCallback {
+public abstract class Animator implements Cloneable {
 
     /**
      * The value used to indicate infinite duration (e.g. when Animators repeat infinitely).
@@ -464,24 +464,14 @@
         throw new IllegalStateException("Reverse is not supported");
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public boolean doAnimationFrame(long frameTime) {
+    // Pulse an animation frame into the animation.
+    boolean pulseAnimationFrame(long frameTime) {
         // TODO: Need to find a better signal than this. There's a bug in SystemUI that's preventing
         // returning !isStarted() from working.
         return false;
     }
 
     /**
-     * @hide
-     */
-    @Override
-    public void commitAnimationFrame(long frameTime) {}
-
-
-    /**
      * Internal use only.
      * This call starts the animation in regular or reverse direction without requiring them to
      * register frame callbacks. The caller will be responsible for all the subsequent animation
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 8aba405..4e3b7d0 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -948,7 +948,8 @@
         for (int i = 0; i < mPlayingSet.size(); i++) {
             Node node = mPlayingSet.get(i);
             if (!node.mEnded) {
-                node.mEnded = node.mAnimation.doAnimationFrame(getPlayTimeForNode(playTime, node));
+                node.mEnded = node.mAnimation.pulseAnimationFrame(
+                    getPlayTimeForNode(playTime, node));
             }
         }
 
@@ -978,6 +979,19 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public void commitAnimationFrame(long frameTime) {
+        // No op.
+    }
+
+    @Override
+    boolean pulseAnimationFrame(long frameTime) {
+        return doAnimationFrame(frameTime);
+    }
+
+    /**
      * When playing forward, we call start() at the animation's scheduled start time, and make sure
      * to pump a frame at the animation's scheduled end time.
      *
@@ -993,11 +1007,10 @@
                 if (event.mEvent == AnimationEvent.ANIMATION_END) {
                     mPlayingSet.add(event.mNode);
                     node.mAnimation.startWithoutPulsing(true);
-                    node.mAnimation.doAnimationFrame(0);
+                    pulseFrame(node, 0);
                 } else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED && !node.mEnded) {
                     // end event:
-                    node.mEnded =
-                            node.mAnimation.doAnimationFrame(getPlayTimeForNode(playTime, node));
+                    pulseFrame(node, getPlayTimeForNode(playTime, node));
                 }
             }
         } else {
@@ -1007,16 +1020,21 @@
                 if (event.mEvent == AnimationEvent.ANIMATION_START) {
                     mPlayingSet.add(event.mNode);
                     node.mAnimation.startWithoutPulsing(false);
-                    node.mAnimation.doAnimationFrame(0);
+                    pulseFrame(node, 0);
                 } else if (event.mEvent == AnimationEvent.ANIMATION_END && !node.mEnded) {
                     // start event:
-                    node.mEnded =
-                            node.mAnimation.doAnimationFrame(getPlayTimeForNode(playTime, node));
+                    pulseFrame(node, getPlayTimeForNode(playTime, node));
                 }
             }
         }
     }
 
+    private void pulseFrame(Node node, long frameTime) {
+        if (!node.mEnded) {
+            node.mEnded = node.mAnimation.pulseAnimationFrame(frameTime);
+        }
+    }
+
     private long getPlayTimeForNode(long overallPlayTime, Node node) {
         return getPlayTimeForNode(overallPlayTime, node, mReversing);
     }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 470523f..55ac1f4 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -68,7 +68,7 @@
  * </div>
  */
 @SuppressWarnings("unchecked")
-public class ValueAnimator extends Animator {
+public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
     private static final String TAG = "ValueAnimator";
     private static final boolean DEBUG = false;
 
@@ -225,6 +225,12 @@
     private boolean mSelfPulse = true;
 
     /**
+     * Whether or not the animator has been requested to start without pulsing. This flag gets set
+     * in startWithoutPulsing(), and reset in start().
+     */
+    private boolean mSuppressSelfPulseRequested = false;
+
+    /**
      * The time interpolator to be used. The elapsed fraction of the animation will be passed
      * through this interpolator to calculate the interpolated fraction, which is then used to
      * calculate the animated values.
@@ -997,12 +1003,12 @@
      *
      * @param playBackwards Whether the ValueAnimator should start playing in reverse.
      */
-    private void start(boolean playBackwards, boolean selfPulse) {
+    private void start(boolean playBackwards) {
         if (Looper.myLooper() == null) {
             throw new AndroidRuntimeException("Animators may only be run on Looper threads");
         }
         mReversing = playBackwards;
-        mSelfPulse = selfPulse;
+        mSelfPulse = !mSuppressSelfPulseRequested;
         // Special case: reversing from seek-to-0 should act as if not seeked at all.
         if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
             if (mRepeatCount == INFINITE) {
@@ -1041,12 +1047,18 @@
     }
 
     void startWithoutPulsing(boolean inReverse) {
-        start(inReverse, false);
+        mSuppressSelfPulseRequested = true;
+        if (inReverse) {
+            reverse();
+        } else {
+            start();
+        }
+        mSuppressSelfPulseRequested = false;
     }
 
     @Override
     public void start() {
-        start(false, true);
+        start(false);
     }
 
     @Override
@@ -1150,7 +1162,7 @@
             mReversing = !mReversing;
             end();
         } else {
-            start(true, true);
+            start(true);
         }
     }
 
@@ -1364,6 +1376,11 @@
         animateValue(endFraction);
     }
 
+    @Override
+    boolean isInitialized() {
+        return mInitialized;
+    }
+
     /**
      * Processes a frame of the animation, adjusting the start time if needed.
      *
@@ -1430,6 +1447,20 @@
         return finished;
     }
 
+    @Override
+    boolean pulseAnimationFrame(long frameTime) {
+        if (mSelfPulse) {
+            // Pulse animation frame will *always* be after calling start(). If mSelfPulse isn't
+            // set to false at this point, that means child animators did not call super's start().
+            // This can happen when the Animator is just a non-animating wrapper around a real
+            // functional animation. In this case, we can't really pulse a frame into the animation,
+            // because the animation cannot necessarily be properly initialized (i.e. no start/end
+            // values set).
+            return false;
+        }
+        return doAnimationFrame(frameTime);
+    }
+
     private void addOneShotCommitCallback() {
         if (!mSelfPulse) {
             return;
@@ -1514,6 +1545,8 @@
         anim.mFirstFrameTime = -1;
         anim.mOverallFraction = 0;
         anim.mCurrentFraction = 0;
+        anim.mSelfPulse = true;
+        anim.mSuppressSelfPulseRequested = false;
 
         PropertyValuesHolder[] oldValues = mValues;
         if (oldValues != null) {
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index a27775e..66b2355 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -220,6 +220,8 @@
     int mIndex = -1;
     boolean mAllowOptimization;
 
+    ArrayList<Runnable> mCommitRunnables;
+
     int mBreadCrumbTitleRes;
     CharSequence mBreadCrumbTitleText;
     int mBreadCrumbShortTitleRes;
@@ -620,6 +622,28 @@
         }
     }
 
+    @Override
+    public FragmentTransaction postOnCommit(Runnable runnable) {
+        if (runnable == null) {
+            throw new IllegalArgumentException("runnable cannot be null");
+        }
+        disallowAddToBackStack();
+        if (mCommitRunnables == null) {
+            mCommitRunnables = new ArrayList<>();
+        }
+        mCommitRunnables.add(runnable);
+        return this;
+    }
+
+    public void runOnCommitRunnables() {
+        if (mCommitRunnables != null) {
+            for (int i = 0, N = mCommitRunnables.size(); i < N; i++) {
+                mCommitRunnables.get(i).run();
+            }
+            mCommitRunnables = null;
+        }
+    }
+
     public int commit() {
         return commitInternal(false);
     }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 612998d..108ab71 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -714,14 +714,20 @@
     }
 
     /**
-     * Supply the construction arguments for this fragment.  This can only
-     * be called before the fragment has been attached to its activity; that
-     * is, you should call it immediately after constructing the fragment.  The
-     * arguments supplied here will be retained across fragment destroy and
+     * Supply the construction arguments for this fragment.
+     * The arguments supplied here will be retained across fragment destroy and
      * creation.
+     *
+     * <p>This method cannot be called if the fragment is added to a FragmentManager and
+     * if {@link #isStateSaved()} would return true. Prior to {@link Build.VERSION_CODES#O},
+     * this method may only be called if the fragment has not yet been added to a FragmentManager.
+     * </p>
      */
     public void setArguments(Bundle args) {
-        if (mIndex >= 0) {
+        // The isStateSaved requirement below was only added in Android O and is compatible
+        // because it loosens previous requirements rather than making them more strict.
+        // See method javadoc.
+        if (mIndex >= 0 && isStateSaved()) {
             throw new IllegalStateException("Fragment already active");
         }
         mArguments = args;
@@ -735,6 +741,21 @@
     }
 
     /**
+     * Returns true if this fragment is added and its state has already been saved
+     * by its host. Any operations that would change saved state should not be performed
+     * if this method returns true, and some operations such as {@link #setArguments(Bundle)}
+     * will fail.
+     *
+     * @return true if this fragment's state has already been saved by its host
+     */
+    public final boolean isStateSaved() {
+        if (mFragmentManager == null) {
+            return false;
+        }
+        return mFragmentManager.isStateSaved();
+    }
+
+    /**
      * Set the initial saved state that this Fragment should restore itself
      * from when first being constructed, as returned by
      * {@link FragmentManager#saveFragmentInstanceState(Fragment)
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index b0150bd..4f68ec7 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1787,6 +1787,10 @@
         }
     }
 
+    public boolean isStateSaved() {
+        return mStateSaved;
+    }
+
     /**
      * Adds an action to the queue of pending actions.
      *
@@ -2108,6 +2112,7 @@
                 freeBackStackIndex(record.mIndex);
                 record.mIndex = -1;
             }
+            record.runOnCommitRunnables();
         }
 
         if (addToBackStack) {
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 07a313c..c938aa6 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -304,6 +304,22 @@
     public abstract FragmentTransaction setAllowOptimization(boolean allowOptimization);
 
     /**
+     * Add a Runnable to this transaction that will be run after this transaction has
+     * been committed. If fragment transactions are {@link #setAllowOptimization(boolean) optimized}
+     * this may be after other subsequent fragment operations have also taken place, or operations
+     * in this transaction may have been optimized out due to the presence of a subsequent
+     * fragment transaction in the batch.
+     *
+     * <p><code>postOnCommit</code> may not be used with transactions
+     * {@link #addToBackStack(String) added to the back stack} as Runnables cannot be persisted
+     * with back stack state.</p>
+     *
+     * @param runnable Runnable to add
+     * @return this FragmentTransaction
+     */
+    public abstract FragmentTransaction postOnCommit(Runnable runnable);
+
+    /**
      * Schedules a commit of this transaction.  The commit does
      * not happen immediately; it will be scheduled as work on the main thread
      * to be done the next time that thread is ready.
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 54cc4a0..6d1d1a3 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1108,6 +1108,16 @@
                 public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
                     /* do nothing */
                 }
+
+                @Override
+                public void onFingerprintCapturingGesturesChanged(boolean active) {
+                    /* do nothing */
+                }
+
+                @Override
+                public void onFingerprintGesture(int gesture) {
+                    /* do nothing */
+                }
             });
         }
     }
diff --git a/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl b/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
index 8766508..3c3b84d 100644
--- a/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
+++ b/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
@@ -25,5 +25,4 @@
  */
 oneway interface IRuntimePermissionPresenter {
     void getAppPermissions(String packageName, in RemoteCallback callback);
-    void getAppsUsingPermissions(boolean system, in RemoteCallback callback);
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
index 2e39926..6d55d2f 100644
--- a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
+++ b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
@@ -72,15 +72,6 @@
                 List<RuntimePermissionPresentationInfo> permissions) {
             /* do nothing - stub */
         }
-
-        /**
-         * The result for {@link #getAppsUsingPermissions(boolean, List)}.
-         * @param system Whether to return only the system apps or only the non-system ones.
-         * @param apps The apps using runtime permissions.
-         */
-        public void getAppsUsingPermissions(boolean system, @NonNull List<ApplicationInfo> apps) {
-            /* do nothing - stub */
-        }
     }
 
     private static final Object sLock = new Object();
@@ -127,29 +118,6 @@
         mRemoteService.processMessage(message);
     }
 
-    /**
-     * Gets the system apps that use runtime permissions. System apps are ones
-     * that are considered system for presentation purposes instead of ones
-     * that are preinstalled on the system image. System apps are ones that
-     * are on the system image, haven't been updated (a.k.a factory apps)
-     * that do not have a launcher icon.
-     *
-     * @param system If true only system apps are returned otherwise only
-     *        non-system ones are returned.
-     * @param callback Callback to receive the result.
-     * @param handler Handler on which to invoke the callback.
-     */
-    public void getAppsUsingPermissions(boolean system, @NonNull OnResultCallback callback,
-            @Nullable Handler handler) {
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = callback;
-        args.arg2 = handler;
-        args.argi1 = system ? 1 : 0;
-        Message message = mRemoteService.obtainMessage(
-                RemoteService.MSG_GET_APPS_USING_PERMISSIONS, args);
-        mRemoteService.processMessage(message);
-    }
-
     private static final class RemoteService
             extends Handler implements ServiceConnection {
         private static final long UNBIND_TIMEOUT_MILLIS = 10000;
@@ -254,51 +222,6 @@
                     scheduleUnbind();
                 } break;
 
-                case MSG_GET_APPS_USING_PERMISSIONS: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    final OnResultCallback callback = (OnResultCallback) args.arg1;
-                    final Handler handler = (Handler) args.arg2;
-                    final boolean system = args.argi1 == 1;
-                    args.recycle();
-                    final IRuntimePermissionPresenter remoteInstance;
-                    synchronized (mLock) {
-                        remoteInstance = mRemoteInstance;
-                    }
-                    if (remoteInstance == null) {
-                        return;
-                    }
-                    try {
-                        remoteInstance.getAppsUsingPermissions(system, new RemoteCallback(
-                                new RemoteCallback.OnResultListener() {
-                            @Override
-                            public void onResult(Bundle result) {
-                                final List<ApplicationInfo> reportedApps;
-                                List<ApplicationInfo> apps = null;
-                                if (result != null) {
-                                    apps = result.getParcelableArrayList(KEY_RESULT);
-                                }
-                                if (apps == null) {
-                                    apps = Collections.emptyList();
-                                }
-                                reportedApps = apps;
-                                if (handler != null) {
-                                    handler.post(new Runnable() {
-                                        @Override
-                                        public void run() {
-                                            callback.getAppsUsingPermissions(system, reportedApps);
-                                        }
-                                    });
-                                } else {
-                                    callback.getAppsUsingPermissions(system, reportedApps);
-                                }
-                            }
-                        }, this));
-                    } catch (RemoteException re) {
-                        Log.e(TAG, "Error getting apps using permissions", re);
-                    }
-                    scheduleUnbind();
-                } break;
-
                 case MSG_UNBIND: {
                     synchronized (mLock) {
                         if (mBound) {
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 612a751..522575f 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -293,7 +293,8 @@
      * case is to create a capture session with that output configuration. For example, if the
      * camera device uses the same private buffer format between a SurfaceView/SurfaceTexture and a
      * MediaRecorder/MediaCodec, {@link CameraDevice#createCaptureSessionByOutputConfigurations}
-     * will succeed. Otherwise, it throws {@code IllegalArgumentException}.
+     * will succeed. Otherwise, it fails with {@link
+     * CameraCaptureSession.StateCallback#onConfigureFailed}.
      * </ol>
      *
      * <p>To enable surface sharing, this function must be called before {@link
diff --git a/core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl b/core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl
new file mode 100644
index 0000000..5bcf476
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.fingerprint;
+
+/**
+ * Callback when clients become active or inactive.
+ * @hide
+ */
+oneway interface IFingerprintClientActiveCallback {
+    void onClientActiveChanged(boolean isActive);
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index ae3fc37..4879d54 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -16,6 +16,7 @@
 package android.hardware.fingerprint;
 
 import android.os.Bundle;
+import android.hardware.fingerprint.IFingerprintClientActiveCallback;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
 import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
 import android.hardware.fingerprint.Fingerprint;
@@ -82,4 +83,13 @@
 
     // Enumerate all fingerprints
     void enumerate(IBinder token, int userId, IFingerprintServiceReceiver receiver);
+
+    // Check if a client request is currently being handled
+    boolean isClientActive();
+
+    // Add a callback which gets notified when the service starts and stops handling client requests
+    void addClientActiveCallback(IFingerprintClientActiveCallback callback);
+
+    // Removes a callback set by addClientActiveCallback
+    void removeClientActiveCallback(IFingerprintClientActiveCallback callback);
 }
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 16ae867..5739c79 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -5,8 +5,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
-import android.os.Looper;
-import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -27,8 +25,6 @@
             "android.net.extra.RECOMMENDATION_RESULT";
     /** The key into the callback Bundle where the sequence will be found. */
     public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
-    private static final String EXTRA_RECOMMENDATION_REQUEST =
-            "android.net.extra.RECOMMENDATION_REQUEST";
     private final IBinder mService;
 
     /**
@@ -39,7 +35,7 @@
         if (handler == null) {
             throw new IllegalArgumentException("The provided handler cannot be null.");
         }
-        mService = new ServiceWrapper(new ServiceHandler(handler.getLooper()));
+        mService = new ServiceWrapper(handler);
     }
 
     /**
@@ -125,42 +121,10 @@
         }
     }
 
-    private final class ServiceHandler extends Handler {
-        static final int MSG_GET_RECOMMENDATION = 1;
-        static final int MSG_REQUEST_SCORES = 2;
-
-        ServiceHandler(Looper looper) {
-            super(looper, null /*callback*/, true /*async*/);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            final int what = msg.what;
-            switch (what) {
-                case MSG_GET_RECOMMENDATION:
-                    final IRemoteCallback callback = (IRemoteCallback) msg.obj;
-                    final int seq = msg.arg1;
-                    final RecommendationRequest request =
-                            msg.getData().getParcelable(EXTRA_RECOMMENDATION_REQUEST);
-                    final ResultCallback resultCallback = new ResultCallback(callback, seq);
-                    onRequestRecommendation(request, resultCallback);
-                    break;
-
-                case MSG_REQUEST_SCORES:
-                    final NetworkKey[] networks = (NetworkKey[]) msg.obj;
-                    onRequestScores(networks);
-                    break;
-
-                default:
-                    throw new IllegalArgumentException("Unknown message: " + what);
-            }
-        }
-    }
-
     /**
-     * A wrapper around INetworkRecommendationProvider that sends calls to the internal Handler.
+     * A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler.
      */
-    private static final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
+    private final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
         private final Handler mHandler;
 
         ServiceWrapper(Handler handler) {
@@ -168,20 +132,26 @@
         }
 
         @Override
-        public void requestRecommendation(RecommendationRequest request, IRemoteCallback callback,
-                int sequence) throws RemoteException {
-            final Message msg = mHandler.obtainMessage(
-                    ServiceHandler.MSG_GET_RECOMMENDATION, sequence, 0 /*arg2*/, callback);
-            final Bundle data = new Bundle();
-            data.putParcelable(EXTRA_RECOMMENDATION_REQUEST, request);
-            msg.setData(data);
-            msg.sendToTarget();
+        public void requestRecommendation(final RecommendationRequest request,
+                final IRemoteCallback callback, final int sequence) throws RemoteException {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    ResultCallback resultCallback = new ResultCallback(callback, sequence);
+                    onRequestRecommendation(request, resultCallback);
+                }
+            });
         }
 
         @Override
-        public void requestScores(NetworkKey[] networks) throws RemoteException {
+        public void requestScores(final NetworkKey[] networks) throws RemoteException {
             if (networks != null && networks.length > 0) {
-                mHandler.obtainMessage(ServiceHandler.MSG_REQUEST_SCORES, networks).sendToTarget();
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        onRequestScores(networks);
+                    }
+                });
             }
         }
     }
diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
index 405be1a..344d947 100644
--- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
+++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
@@ -72,14 +72,6 @@
      */
     public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName);
 
-    /**
-     * Gets the apps that use runtime permissions.
-     *
-     * @param system Whether to return only the system apps or only the non-system ones.
-     * @return The app list.
-     */
-    public abstract List<ApplicationInfo> onGetAppsUsingPermissions(boolean system);
-
     @Override
     public final IBinder onBind(Intent intent) {
         return new IRuntimePermissionPresenter.Stub() {
@@ -91,12 +83,6 @@
                 mHandler.obtainMessage(MyHandler.MSG_GET_APP_PERMISSIONS,
                         args).sendToTarget();
             }
-
-            @Override
-            public void getAppsUsingPermissions(boolean system, RemoteCallback callback) {
-                mHandler.obtainMessage(MyHandler.MSG_GET_APPS_USING_PERMISSIONS,
-                        system ? 1 : 0, 0, callback).sendToTarget();
-            }
         };
     }
 
@@ -127,19 +113,6 @@
                         callback.sendResult(null);
                     }
                 } break;
-
-                case MSG_GET_APPS_USING_PERMISSIONS: {
-                    RemoteCallback callback = (RemoteCallback) msg.obj;
-                    final boolean system = msg.arg1 == 1;
-                    List<ApplicationInfo> apps = onGetAppsUsingPermissions(system);
-                    if (apps != null && !apps.isEmpty()) {
-                        Bundle result = new Bundle();
-                        result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, apps);
-                        callback.sendResult(result);
-                    } else {
-                        callback.sendResult(null);
-                    }
-                } break;
             }
         }
     }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 1b512c6..a0d16bc 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -19,6 +19,7 @@
 import android.accounts.Account;
 import android.annotation.SystemApi;
 import android.app.Activity;
+import android.content.BroadcastReceiver;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
@@ -30,6 +31,7 @@
 import android.content.Entity;
 import android.content.EntityIterator;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.database.Cursor;
@@ -8170,29 +8172,11 @@
         /**
          * The content:// style URI for this table.  Requests to this URI can be
          * performed on the UI thread because they are always unblocking.
-         *
-         * <p>Note when you listen on this URI (or any other sub-URIs), you'll be notified for
-         * regular contact change notifications too, which will be sent on the root URI.
-         * If you only want to be notified for provider status change notifications, listen on
-         * {@link #STATUS_CHANGE_NOTIFICATION_CONTENT_URI} instead.
          */
         public static final Uri CONTENT_URI =
                 Uri.withAppendedPath(AUTHORITY_URI, "provider_status");
 
         /**
-         * URI to listen to provider status changes without listening to regular
-         * contact changes.  If a client only wants to monitor {@link ProviderStatus} with
-         * {@link android.app.job.JobScheduler}, then this URI should be used instead of
-         * {@link #CONTENT_URI}, because a job on {@link #CONTENT_URI} will also be invoked
-         * when contacts are changed.
-         *
-         * <p>Note this URI cannot be queried.  A query should be always made on
-         * {@link #CONTENT_URI}.
-         */
-        public static final Uri STATUS_CHANGE_NOTIFICATION_CONTENT_URI =
-                Uri.parse("content://com.android.contacts.provider_status");
-
-        /**
          * The MIME-type of {@link #CONTENT_URI} providing a directory of
          * settings.
          */
@@ -8794,13 +8778,13 @@
          * This is the intent that is fired when the contacts database is created. <p> The
          * READ_CONTACT permission is required to receive these broadcasts.
          *
-         * <p>As of O, this broadcast will no longer be sent.  Applications can use
-         * use {@link android.app.job.JobScheduler} to monitor
-         * {@link ProviderStatus#STATUS_CHANGE_NOTIFICATION_CONTENT_URI}, and read
-         * {@link ProviderStatus#DATABASE_CREATION_TIMESTAMP} to get when
-         * the contacts database was initialized.
+         * <p>Because this is an implicit broadcast, apps targeting Android O will no longer
+         * receive this broadcast via a manifest broadcast receiver.  (Broadcast receivers
+         * registered at runtime with
+         * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)} will still receive it.)
+         * Instead, an app can use {@link ProviderStatus#DATABASE_CREATION_TIMESTAMP} to see if the
+         * contacts database has been initialized when it starts.
          */
-        @Deprecated
         public static final String CONTACTS_DATABASE_CREATED =
                 "android.provider.Contacts.DATABASE_CREATED";
 
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index bfb8d83..1ef0d17 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -633,6 +633,28 @@
     }
 
     /**
+     * Report a fingerprint gesture to accessibility. Only available for the system process.
+     *
+     * @param keyCode The key code of the gesture
+     * @return {@code true} if accessibility consumes the event. {@code false} if not.
+     * @hide
+     */
+    public boolean sendFingerprintGesture(int keyCode) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+        }
+        try {
+            return service.sendFingerprintGesture(keyCode);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Sets the current state and notifies listeners, if necessary.
      *
      * @param stateFlags The state flags.
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index ed77f68..136bbbe 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -1,5 +1,4 @@
-/* //device/java/android/android/app/INotificationManager.aidl
-**
+/*
 ** Copyright 2009, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -62,4 +61,7 @@
 
     // Requires WRITE_SECURE_SETTINGS
     void performAccessibilityShortcut();
+
+    // System process only
+    boolean sendFingerprintGesture(int gestureKeyCode);
 }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 34f78f3..c548219 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3392,6 +3392,8 @@
             <flag name="flagRetrieveInteractiveWindows" value="0x00000040" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_ENABLE_ACCESSIBILITY_VOLUME} -->
             <flag name="flagEnableAccessibilityVolume" value="0x00000080" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES} -->
+            <flag name="flagCaptureFingerprintGestures" value="0x00000200" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. This setting cannot be changed at runtime. -->
@@ -3440,6 +3442,14 @@
              </p>
          -->
         <attr name="canPerformGestures" format="boolean" />
+        <!-- Attribute whether the accessibility service wants to be able to capture gestures from
+             the fingerprint sensor.
+             <p>
+             Required to allow setting the {@link android.accessibilityservice
+             #AccessibilityServiceInfo#FLAG_CAN_CAPTURE_FINGERPRINT_GESTURES} flag.
+             </p>
+         -->
+        <attr name="canCaptureFingerprintGestures" format="boolean" />
         <!-- Short description of the accessibility service purpose or behavior.-->
         <attr name="description" />
     </declare-styleable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 737dab0..d795d80 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2791,6 +2791,7 @@
         <public name="colorMode" />
         <public name="isolatedSplits" />
         <public name="targetSandboxVersion" />
+        <public name="canCaptureFingerprintGestures" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2ab0914..8b9b3b2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -681,6 +681,12 @@
     <string name="capability_desc_canPerformGestures">Can tap, swipe, pinch, and perform other
         gestures.</string>
 
+    <!-- Title for the capability of an accessibility service to capture fingerprint gestures. -->
+    <string name="capability_title_canCaptureFingerprintGestures">Fingerprint gestures</string>
+    <!-- Description for the capability of an accessibility service to perform gestures. -->
+    <string name="capability_desc_canCaptureFingerprintGestures">Can capture gestures performed on
+        the device's fingerprint sensor.</string>
+
     <!--  Permissions -->
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 15011c8..b2e3728 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2836,4 +2836,8 @@
   <java-symbol type="id" name="autofill_save_title" />
   <java-symbol type="id" name="autofill_save_no" />
   <java-symbol type="id" name="autofill_save_yes" />
+
+  <!-- Accessibility fingerprint gestures -->
+  <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
+  <java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" />
 </resources>
diff --git a/packages/SystemUI/res/layout-land/nav_bar_tuner.xml b/packages/SystemUI/res/layout-land/nav_bar_tuner.xml
deleted file mode 100644
index a430b73..0000000
--- a/packages/SystemUI/res/layout-land/nav_bar_tuner.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="horizontal">
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:elevation="4dp"
-        android:paddingTop="12dp"
-        android:paddingBottom="12dp"
-        android:paddingStart="8dp"
-        android:paddingEnd="8dp"
-        android:background="@android:color/white"
-        android:gravity="center"
-        android:orientation="vertical">
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/preview"
-            android:paddingStart="8dp"
-            android:paddingEnd="8dp"
-            android:textColor="?android:attr/colorAccent"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-
-        <FrameLayout
-            android:id="@+id/nav_preview_frame"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-    </LinearLayout>
-
-    <android.support.v7.widget.RecyclerView
-        android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp-land/nav_bar_tuner.xml b/packages/SystemUI/res/layout-sw600dp-land/nav_bar_tuner.xml
deleted file mode 100644
index 5479157..0000000
--- a/packages/SystemUI/res/layout-sw600dp-land/nav_bar_tuner.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:elevation="4dp"
-        android:paddingTop="8dp"
-        android:paddingBottom="8dp"
-        android:paddingStart="12dp"
-        android:paddingEnd="12dp"
-        android:layout_gravity="bottom"
-        android:background="@android:color/white"
-        android:gravity="center"
-        android:orientation="vertical">
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/preview"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
-            android:textColor="?android:attr/colorAccent"
-            android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        <FrameLayout
-            android:id="@+id/nav_preview_frame"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-    </LinearLayout>
-
-    <android.support.v7.widget.RecyclerView
-        android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/nav_bar_tuner.xml b/packages/SystemUI/res/layout/nav_bar_tuner.xml
deleted file mode 100644
index 5479157..0000000
--- a/packages/SystemUI/res/layout/nav_bar_tuner.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:elevation="4dp"
-        android:paddingTop="8dp"
-        android:paddingBottom="8dp"
-        android:paddingStart="12dp"
-        android:paddingEnd="12dp"
-        android:layout_gravity="bottom"
-        android:background="@android:color/white"
-        android:gravity="center"
-        android:orientation="vertical">
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/preview"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
-            android:textColor="?android:attr/colorAccent"
-            android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        <FrameLayout
-            android:id="@+id/nav_preview_frame"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-    </LinearLayout>
-
-    <android.support.v7.widget.RecyclerView
-        android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 018d888..e3149ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1599,8 +1599,11 @@
         if (mHeadsUpManager.isHeadsUp(key)) {
             // A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the
             // sending look longer than it takes.
+            // Also we should not defer the removal if reordering isn't allowed since otherwise
+            // some notifications can't disappear before the panel is closed.
             boolean ignoreEarliestRemovalTime = mRemoteInputController.isSpinning(key)
-                    && !FORCE_REMOTE_INPUT_HISTORY;
+                    && !FORCE_REMOTE_INPUT_HISTORY
+                    || !mVisualStabilityManager.isReorderingAllowed();
             deferRemoval = !mHeadsUpManager.removeNotification(key,  ignoreEarliestRemovalTime);
         }
         if (key.equals(mMediaNotificationKey)) {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/KeycodeSelectionHelper.java b/packages/SystemUI/src/com/android/systemui/tuner/KeycodeSelectionHelper.java
deleted file mode 100644
index 096ecc0..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/KeycodeSelectionHelper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.tuner;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.view.KeyEvent;
-
-import com.android.systemui.R;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-
-public class KeycodeSelectionHelper {
-
-    private static final ArrayList<String> mKeycodeStrings = new ArrayList<>();
-    private static final ArrayList<Integer> mKeycodes = new ArrayList<>();
-
-    private static final String KEYCODE_STRING = "KEYCODE_";
-
-    static {
-        Class<KeyEvent> cls = KeyEvent.class;
-        for (Field field : cls.getDeclaredFields()) {
-            if (Modifier.isStatic(field.getModifiers())
-                    && field.getName().startsWith(KEYCODE_STRING)
-                    && field.getType().equals(int.class)) {
-                try {
-                    mKeycodeStrings.add(formatString(field.getName()));
-                    mKeycodes.add((Integer) field.get(null));
-                } catch (IllegalAccessException e) {
-                }
-            }
-        }
-    }
-
-    // Force the string into something somewhat readable.
-    private static String formatString(String name) {
-        StringBuilder str = new StringBuilder(name.replace(KEYCODE_STRING, "").replace("_", " ")
-                .toLowerCase());
-        for (int i = 0; i < str.length(); i++) {
-            if (i == 0 || str.charAt(i - 1) == ' ') {
-                str.setCharAt(i, Character.toUpperCase(str.charAt(i)));
-            }
-        }
-        return str.toString();
-    }
-
-    public static void showKeycodeSelect(Context context, final OnSelectionComplete listener) {
-        new AlertDialog.Builder(context)
-                .setTitle(R.string.select_keycode)
-                .setItems(mKeycodeStrings.toArray(new String[0]),
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        listener.onSelectionComplete(mKeycodes.get(which));
-                    }
-                }).show();
-    }
-
-    public static Intent getSelectImageIntent() {
-        return new Intent(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE)
-                .setType("image/*");
-    }
-
-    public interface OnSelectionComplete {
-        void onSelectionComplete(int code);
-    }
-}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ece5149..b68ac3b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -63,11 +63,13 @@
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.hardware.fingerprint.IFingerprintService;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.util.Slog;
@@ -203,6 +205,8 @@
 
     private MotionEventInjector mMotionEventInjector;
 
+    private FingerprintGestureDispatcher mFingerprintGestureDispatcher;
+
     private final Set<ComponentName> mTempComponentNameSet = new HashSet<>();
 
     private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
@@ -1374,6 +1378,10 @@
         mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget();
     }
 
+    private void scheduleUpdateFingerprintGestureHandling(UserState userState) {
+        mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_FINGERPRINT, userState).sendToTarget();
+    }
+
     private void updateInputFilter(UserState userState) {
         boolean setInputFilter = false;
         AccessibilityInputFilter inputFilter = null;
@@ -1501,6 +1509,7 @@
         updateDisplayInversionLocked(userState);
         updateMagnificationLocked(userState);
         updateSoftKeyboardShowModeLocked(userState);
+        scheduleUpdateFingerprintGestureHandling(userState);
         scheduleUpdateInputFilter(userState);
         scheduleUpdateClientsIfNeededLocked(userState);
     }
@@ -1919,6 +1928,35 @@
         }
     }
 
+    private void updateFingerprintGestureHandling(UserState userState) {
+        final List<Service> services;
+        synchronized (mLock) {
+            // Only create the controller when a service wants to use the feature
+            services = userState.mBoundServices;
+            int numServices = services.size();
+            for (int i = 0; i < numServices; i++) {
+                if (services.get(i).isCapturingFingerprintGestures()) {
+                    final long identity = Binder.clearCallingIdentity();
+                    IFingerprintService service = null;
+                    try {
+                        service = IFingerprintService.Stub.asInterface(
+                                ServiceManager.getService(Context.FINGERPRINT_SERVICE));
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                    if (service != null) {
+                        mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(
+                                service, mLock);
+                        break;
+                    }
+                }
+            }
+        }
+        if (mFingerprintGestureDispatcher != null) {
+            mFingerprintGestureDispatcher.updateClientList(services);
+        }
+    }
+
     private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
         IBinder windowToken = mGlobalWindowTokens.get(windowId);
         if (windowToken == null) {
@@ -2001,6 +2039,27 @@
         }
     }
 
+    /**
+     * AIDL-exposed method. System only.
+     * Inform accessibility that a fingerprint gesture was performed
+     *
+     * @param gestureKeyCode The key code corresponding to the fingerprint gesture.
+     * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it
+     * doesn't.
+     */
+    @Override
+    public boolean sendFingerprintGesture(int gestureKeyCode) {
+        synchronized(mLock) {
+            if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
+                throw new SecurityException("Only SYSTEM can call sendFingerprintGesture");
+            }
+        }
+        if (mFingerprintGestureDispatcher == null) {
+            return false;
+        }
+        return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
+    }
+
     private class SettingsStringHelper {
         private static final String SETTINGS_DELIMITER = ":";
         private ContentResolver mContentResolver;
@@ -2131,6 +2190,7 @@
         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
         public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9;
         public static final int MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS = 10;
+        public static final int MSG_UPDATE_FINGERPRINT = 11;
 
         public MainHandler(Looper looper) {
             super(looper);
@@ -2199,6 +2259,10 @@
                 case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: {
                     notifyClientsOfServicesStateChange();
                 } break;
+
+                case MSG_UPDATE_FINGERPRINT: {
+                    updateFingerprintGestureHandling((UserState) msg.obj);
+                } break;
             }
         }
 
@@ -2329,7 +2393,8 @@
      * connection for the service.
      */
     class Service extends IAccessibilityServiceConnection.Stub
-            implements ServiceConnection, DeathRecipient, KeyEventDispatcher.KeyEventFilter {;
+            implements ServiceConnection, DeathRecipient, KeyEventDispatcher.KeyEventFilter,
+            FingerprintGestureDispatcher.FingerprintGestureClient {
 
         final int mUserId;
 
@@ -2359,6 +2424,8 @@
 
         boolean mRetrieveInteractiveWindows;
 
+        boolean mCaptureFingerprintGestures;
+
         int mFetchFlags;
 
         long mNotificationTimeout;
@@ -2438,6 +2505,47 @@
             return true;
         }
 
+        @Override
+        public boolean isCapturingFingerprintGestures() {
+            return (mServiceInterface != null)
+                    && mSecurityPolicy.canCaptureFingerprintGestures(this)
+                    && mCaptureFingerprintGestures;
+        }
+
+        @Override
+        public void onFingerprintGestureDetectionActiveChanged(boolean active) {
+            if (!isCapturingFingerprintGestures()) {
+                return;
+            }
+            IAccessibilityServiceClient serviceInterface;
+            synchronized (mLock) {
+                serviceInterface = mServiceInterface;
+            }
+            if (serviceInterface != null) {
+                try {
+                    mServiceInterface.onFingerprintCapturingGesturesChanged(active);
+                } catch (RemoteException e) {
+                }
+            }
+        }
+
+        @Override
+        public void onFingerprintGesture(int gesture) {
+            if (!isCapturingFingerprintGestures()) {
+                return;
+            }
+            IAccessibilityServiceClient serviceInterface;
+            synchronized (mLock) {
+                serviceInterface = mServiceInterface;
+            }
+            if (serviceInterface != null) {
+                try {
+                    mServiceInterface.onFingerprintGesture(gesture);
+                } catch (RemoteException e) {
+                }
+            }
+        }
+
         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
             mEventTypes = info.eventTypes;
             mFeedbackType = info.feedbackType;
@@ -2471,6 +2579,8 @@
                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
             mRetrieveInteractiveWindows = (info.flags
                     & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
+            mCaptureFingerprintGestures = (info.flags
+                    & AccessibilityServiceInfo.FLAG_CAPTURE_FINGERPRINT_GESTURES) != 0;
         }
 
         /**
@@ -3060,6 +3170,13 @@
         }
 
         @Override
+        public boolean isFingerprintGestureDetectionAvailable() {
+            return isCapturingFingerprintGestures()
+                    && (mFingerprintGestureDispatcher != null)
+                    && mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable();
+        }
+
+        @Override
         public float getMagnificationScale() {
             synchronized (mLock) {
                 if (!isCalledForCurrentUserLocked()) {
@@ -4234,6 +4351,11 @@
                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
         }
 
+        public boolean canCaptureFingerprintGestures(Service service) {
+            return (service.mAccessibilityServiceInfo.getCapabilities()
+                    & AccessibilityServiceInfo.CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES) != 0;
+        }
+
         private int resolveProfileParentLocked(int userId) {
             if (userId != mCurrentUserId) {
                 final long identity = Binder.clearCallingIdentity();
diff --git a/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java b/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java
new file mode 100644
index 0000000..fe787b3
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import android.accessibilityservice.FingerprintGestureController;
+import android.hardware.fingerprint.IFingerprintClientActiveCallback;
+import android.hardware.fingerprint.IFingerprintService;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.KeyEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Encapsulate fingerprint gesture logic
+ */
+public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallback.Stub
+        implements Handler.Callback{
+    private static final int MSG_REGISTER = 1;
+    private static final int MSG_UNREGISTER = 2;
+    private static final String LOG_TAG = "FingerprintGestureDispatcher";
+
+    private final List<FingerprintGestureClient> mCapturingClients = new ArrayList<>(0);
+    private final Object mLock;
+    private final IFingerprintService mFingerprintService;
+    private final Handler mHandler;
+
+    // This field is ground truth for whether or not we are registered. Only write to it in handler.
+    private boolean mRegisteredReadOnlyExceptInHandler;
+
+    /**
+     * @param fingerprintService The system's fingerprint service
+     * @param lock A lock to use when managing internal state
+     */
+    public FingerprintGestureDispatcher(IFingerprintService fingerprintService, Object lock) {
+        mFingerprintService = fingerprintService;
+        mLock = lock;
+        mHandler = new Handler(this);
+    }
+
+    /**
+     * @param fingerprintService The system's fingerprint service
+     * @param lock A lock to use when managing internal state
+     * @param handler A handler to use internally. Used for testing.
+     */
+    public FingerprintGestureDispatcher(IFingerprintService fingerprintService, Object lock,
+            Handler handler) {
+        mFingerprintService = fingerprintService;
+        mLock = lock;
+        mHandler = handler;
+    }
+
+    /**
+     * Update the list of clients that are interested in fingerprint gestures.
+     *
+     * @param clientList The list of potential clients.
+     */
+    public void updateClientList(List<? extends FingerprintGestureClient> clientList) {
+        synchronized (mLock) {
+            mCapturingClients.clear();
+            for (int i = 0; i < clientList.size(); i++) {
+                FingerprintGestureClient client = clientList.get(i);
+                if (client.isCapturingFingerprintGestures()) {
+                    mCapturingClients.add(client);
+                }
+            }
+            if (mCapturingClients.isEmpty()) {
+                if (mRegisteredReadOnlyExceptInHandler) {
+                    mHandler.obtainMessage(MSG_UNREGISTER).sendToTarget();
+                }
+            } else {
+                if(!mRegisteredReadOnlyExceptInHandler) {
+                    mHandler.obtainMessage(MSG_REGISTER).sendToTarget();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onClientActiveChanged(boolean nonGestureFingerprintClientActive) {
+        synchronized (mLock) {
+            for (int i = 0; i < mCapturingClients.size(); i++) {
+                mCapturingClients.get(i).onFingerprintGestureDetectionActiveChanged(
+                        !nonGestureFingerprintClientActive);
+            }
+        }
+    }
+
+    public boolean isFingerprintGestureDetectionAvailable() {
+        long identity = Binder.clearCallingIdentity();
+        try {
+            return !mFingerprintService.isClientActive();
+        } catch (RemoteException re) {
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Called when the fingerprint sensor detects a gesture
+     *
+     * @param fingerprintKeyCode
+     * @return {@code true} if the gesture is consumed. {@code false} otherwise.
+     */
+    public boolean onFingerprintGesture(int fingerprintKeyCode) {
+        int idForFingerprintGestureManager;
+
+        final List<FingerprintGestureClient> clientList;
+        synchronized (mLock) {
+            if (mCapturingClients.isEmpty()) {
+                return false;
+            }
+            switch (fingerprintKeyCode) {
+                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
+                    idForFingerprintGestureManager =
+                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_UP;
+                    break;
+                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
+                    idForFingerprintGestureManager =
+                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN;
+                    break;
+                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT:
+                    idForFingerprintGestureManager =
+                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_RIGHT;
+                    break;
+                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
+                    idForFingerprintGestureManager =
+                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_LEFT;
+                    break;
+                default:
+                    return false;
+            }
+            clientList = new ArrayList<>(mCapturingClients);
+        }
+        for (int i = 0; i < clientList.size(); i++) {
+            clientList.get(i).onFingerprintGesture(idForFingerprintGestureManager);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean handleMessage(Message message) {
+        if (message.what == MSG_REGISTER) {
+            long identity = Binder.clearCallingIdentity();
+            try {
+                mFingerprintService.addClientActiveCallback(this);
+                mRegisteredReadOnlyExceptInHandler = true;
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Failed to register for fingerprint activity callbacks");
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return false;
+        } else if (message.what == MSG_UNREGISTER) {
+            long identity = Binder.clearCallingIdentity();
+            try {
+                mFingerprintService.removeClientActiveCallback(this);
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Failed to unregister for fingerprint activity callbacks");
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            mRegisteredReadOnlyExceptInHandler = false;
+        } else {
+            Slog.e(LOG_TAG, "Unknown message: " + message.what);
+            return false;
+        }
+        return true;
+    }
+
+    // Interface for potential clients.
+    public interface FingerprintGestureClient {
+        /**
+         * @return {@code true} if the client is capturing fingerprint gestures
+         */
+        boolean isCapturingFingerprintGestures();
+
+        /**
+         * Callback when gesture detection becomes active or inactive.
+         *
+         * @param active {@code true} when detection is active
+         */
+        void onFingerprintGestureDetectionActiveChanged(boolean active);
+
+        /**
+         * Callback when gesture is detected
+         *
+         * @param gesture The identifier for the gesture. For example,
+         * {@link FingerprintGestureController#FINGERPRINT_GESTURE_SWIPE_LEFT}
+         */
+        void onFingerprintGesture(int gesture);
+    }
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1f8702a..ebdd8e4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -78,7 +78,7 @@
 import android.net.metrics.DefaultNetworkEvent;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
-import android.net.util.AvoidBadWifiTracker;
+import android.net.util.MultinetworkPolicyTracker;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -499,7 +499,7 @@
     private final IpConnectivityLog mMetricsLog;
 
     @VisibleForTesting
-    final AvoidBadWifiTracker mAvoidBadWifiTracker;
+    final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
 
     /**
      * Implements support for the legacy "one network per network type" model.
@@ -849,9 +849,9 @@
                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
 
-        mAvoidBadWifiTracker = createAvoidBadWifiTracker(
+        mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
                 mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
-        mAvoidBadWifiTracker.start();
+        mMultinetworkPolicyTracker.start();
     }
 
     private NetworkRequest createInternetRequestForTransport(
@@ -2784,7 +2784,7 @@
     }
 
     public boolean avoidBadWifi() {
-        return mAvoidBadWifiTracker.currentValue();
+        return mMultinetworkPolicyTracker.getAvoidBadWifi();
     }
 
     private void rematchForAvoidBadWifiUpdate() {
@@ -2797,9 +2797,9 @@
     }
 
     // TODO: Evaluate whether this is of interest to other consumers of
-    // AvoidBadWifiTracker and worth moving out of here.
+    // MultinetworkPolicyTracker and worth moving out of here.
     private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
-        final boolean configRestrict = mAvoidBadWifiTracker.configRestrictsAvoidBadWifi();
+        final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi();
         if (!configRestrict) {
             pw.println("Bad Wi-Fi avoidance: unrestricted");
             return;
@@ -2809,7 +2809,7 @@
         pw.increaseIndent();
         pw.println("Config restrict:   " + configRestrict);
 
-        final String value = mAvoidBadWifiTracker.getSettingsValue();
+        final String value = mMultinetworkPolicyTracker.getAvoidBadWifiSetting();
         String description;
         // Can't use a switch statement because strings are legal case labels, but null is not.
         if ("0".equals(value)) {
@@ -2877,7 +2877,7 @@
         if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
 
         if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
-            mAvoidBadWifiTracker.shouldNotifyWifiUnvalidated()) {
+            mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
             showValidationNotification(nai, NotificationType.LOST_INTERNET);
         }
     }
@@ -5545,8 +5545,8 @@
     }
 
     @VisibleForTesting
-    AvoidBadWifiTracker createAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
-        return new AvoidBadWifiTracker(c, h, r);
+    MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
+        return new MultinetworkPolicyTracker(c, h, r);
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index c4666dc..0292db9 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -2634,20 +2634,15 @@
         if (!calledFromValidUser()) {
             return;
         }
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (mMethodMap) {
-                if (!calledWithValidToken(token)) {
-                    final int uid = Binder.getCallingUid();
-                    Slog.e(TAG, "Ignoring clearLastInputMethodWindowForTransition due to an "
-                            + "invalid token. uid:" + uid + " token:" + token);
-                    return;
-                }
+        synchronized (mMethodMap) {
+            if (!calledWithValidToken(token)) {
+                final int uid = Binder.getCallingUid();
+                Slog.e(TAG, "Ignoring clearLastInputMethodWindowForTransition due to an "
+                        + "invalid token. uid:" + uid + " token:" + token);
+                return;
             }
-            mWindowManagerInternal.clearLastInputMethodWindowForTransition();
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
+        mWindowManagerInternal.clearLastInputMethodWindowForTransition();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 9ce7ae30..47109f2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3584,6 +3584,7 @@
                 || (prevState == ActivityState.PAUSED
                     && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
                 || finishingActivityInNonFocusedStack
+                || prevState == ActivityState.STOPPING
                 || prevState == ActivityState.STOPPED
                 || prevState == ActivityState.INITIALIZING) {
             r.makeFinishingLocked();
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index e2e0d6b..d1f7cfd 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -30,6 +30,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.hardware.fingerprint.IFingerprintClientActiveCallback;
 import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
 import android.os.Binder;
 import android.os.Bundle;
@@ -82,6 +83,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * A service to manage multiple clients that want to access the fingerprint HAL API.
@@ -109,6 +111,8 @@
 
     private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
             new ArrayList<>();
+    private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
+            new CopyOnWriteArrayList<>();
     private final AppOpsManager mAppOps;
     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
     private static final int MAX_FAILED_ATTEMPTS = 5;
@@ -338,6 +342,9 @@
             if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString());
             mCurrentClient = null;
         }
+        if (mPendingClient == null) {
+            notifyClientActiveCallbacks(false);
+        }
     }
 
     private boolean inLockoutMode() {
@@ -407,6 +414,8 @@
                     + newClient.getClass().getSuperclass().getSimpleName()
                     + "(" + newClient.getOwnerString() + ")"
                     + ", initiatedByClient = " + initiatedByClient + ")");
+            notifyClientActiveCallbacks(true);
+
             newClient.start();
         }
     }
@@ -578,6 +587,18 @@
         }
     }
 
+    private void notifyClientActiveCallbacks(boolean isActive) {
+        List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks;
+        for (int i = 0; i < callbacks.size(); i++) {
+            try {
+                callbacks.get(i).onClientActiveChanged(isActive);
+            } catch (RemoteException re) {
+                // If the remote is dead, stop notifying it
+                mClientActiveCallbacks.remove(callbacks.get(i));
+           }
+        }
+    }
+
     private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
                 IFingerprintServiceReceiver receiver, int flags, boolean restricted,
                 String opPackageName) {
@@ -1047,6 +1068,26 @@
                 }
             });
         }
+
+        @Override
+        public boolean isClientActive() {
+            checkPermission(MANAGE_FINGERPRINT);
+            synchronized(FingerprintService.this) {
+                return (mCurrentClient != null) || (mPendingClient != null);
+            }
+        }
+
+        @Override
+        public void addClientActiveCallback(IFingerprintClientActiveCallback callback) {
+            checkPermission(MANAGE_FINGERPRINT);
+            mClientActiveCallbacks.add(callback);
+        }
+
+        @Override
+        public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) {
+            checkPermission(MANAGE_FINGERPRINT);
+            mClientActiveCallbacks.remove(callback);
+        }
     }
 
     private void dumpInternal(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d623051..37fff68 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6114,13 +6114,18 @@
      * @param event
      */
     private void interceptSystemNavigationKey(KeyEvent event) {
-        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
-            IStatusBarService sbar = getStatusBarService();
-            if (sbar != null) {
-                try {
-                    sbar.handleSystemNavigationKey(event.getKeyCode());
-                } catch (RemoteException e1) {
-                    // oops, no statusbar. Ignore event.
+        if (event.getAction() == KeyEvent.ACTION_UP) {
+            if (!mAccessibilityManager.isEnabled()
+                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
+                if (areSystemNavigationKeysEnabled()) {
+                    IStatusBarService sbar = getStatusBarService();
+                    if (sbar != null) {
+                        try {
+                            sbar.handleSystemNavigationKey(event.getKeyCode());
+                        } catch (RemoteException e1) {
+                            // oops, no statusbar. Ignore event.
+                        }
+                    }
                 }
             }
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 70b0bf2..b911d2d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -55,6 +55,7 @@
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.policy.EmergencyAffordanceManager;
+import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
@@ -117,6 +118,7 @@
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -1580,11 +1582,19 @@
             }
             traceEnd();
 
+            // No dependency on Webview preparation in system server. But this should
+            // be completed before allowring 3rd party
+            final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
+            Future<?> webviewPrep = null;
             if (!mOnlyCore) {
-                Slog.i(TAG, "WebViewFactory preparation");
-                traceBeginAndSlog("WebViewFactoryPreparation");
-                mWebViewUpdateService.prepareWebViewInSystemServer();
-                traceEnd();
+                webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
+                    Slog.i(TAG, WEBVIEW_PREPARATION);
+                    BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
+                            "SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER);
+                    traceLog.traceBegin(WEBVIEW_PREPARATION);
+                    mWebViewUpdateService.prepareWebViewInSystemServer();
+                    traceLog.traceEnd();
+                }, WEBVIEW_PREPARATION);
             }
 
             traceBeginAndSlog("StartSystemUI");
@@ -1641,6 +1651,10 @@
             Watchdog.getInstance().start();
             traceEnd();
 
+            if (webviewPrep != null) {
+                ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
+            }
+
             // It is now okay to let the various system services start their
             // third party code...
             traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index abdf683..76b1c90 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -33,7 +33,7 @@
 import android.net.dhcp.DhcpClient;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.IpManagerEvent;
-import android.net.util.AvoidBadWifiTracker;
+import android.net.util.MultinetworkPolicyTracker;
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.RemoteException;
@@ -398,7 +398,7 @@
     private final NetlinkTracker mNetlinkTracker;
     private final WakeupMessage mProvisioningTimeoutAlarm;
     private final WakeupMessage mDhcpActionTimeoutAlarm;
-    private final AvoidBadWifiTracker mAvoidBadWifiTracker;
+    private final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
     private final LocalLog mLocalLog;
     private final LocalLog mConnectivityPacketLog;
     private final MessageHandlingLogger mMsgStateLogger;
@@ -492,7 +492,7 @@
         mLinkProperties = new LinkProperties();
         mLinkProperties.setInterfaceName(mInterfaceName);
 
-        mAvoidBadWifiTracker = new AvoidBadWifiTracker(mContext, getHandler(),
+        mMultinetworkPolicyTracker = new MultinetworkPolicyTracker(mContext, getHandler(),
                 () -> { mLocalLog.log("OBSERVED AvoidBadWifi changed"); });
 
         mProvisioningTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
@@ -527,7 +527,7 @@
             Log.e(mTag, "Couldn't register NetlinkTracker: " + e.toString());
         }
 
-        mAvoidBadWifiTracker.start();
+        mMultinetworkPolicyTracker.start();
     }
 
     @Override
@@ -538,7 +538,7 @@
     // Shut down this IpManager instance altogether.
     public void shutdown() {
         stop();
-        mAvoidBadWifiTracker.shutdown();
+        mMultinetworkPolicyTracker.shutdown();
         quit();
     }
 
@@ -767,7 +767,7 @@
         // Note that we can still be disconnected by IpReachabilityMonitor
         // if the IPv6 default gateway (but not the IPv6 DNS servers; see
         // accompanying code in IpReachabilityMonitor) is unreachable.
-        final boolean ignoreIPv6ProvisioningLoss = !mAvoidBadWifiTracker.currentValue();
+        final boolean ignoreIPv6ProvisioningLoss = !mMultinetworkPolicyTracker.getAvoidBadWifi();
 
         // Additionally:
         //
@@ -1045,7 +1045,7 @@
                             mCallback.onReachabilityLost(logMsg);
                         }
                     },
-                    mAvoidBadWifiTracker);
+                    mMultinetworkPolicyTracker);
         } catch (IllegalArgumentException iae) {
             // Failed to start IpReachabilityMonitor. Log it and call
             // onProvisioningFailure() immediately.
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index a883e28..20eac62 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -34,7 +34,7 @@
 import android.net.netlink.StructNdaCacheInfo;
 import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
-import android.net.util.AvoidBadWifiTracker;
+import android.net.util.MultinetworkPolicyTracker;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.system.ErrnoException;
@@ -151,7 +151,7 @@
     private final String mInterfaceName;
     private final int mInterfaceIndex;
     private final Callback mCallback;
-    private final AvoidBadWifiTracker mAvoidBadWifiTracker;
+    private final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
     private final NetlinkSocketObserver mNetlinkSocketObserver;
     private final Thread mObserverThread;
     private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
@@ -226,7 +226,7 @@
     }
 
     public IpReachabilityMonitor(Context context, String ifName, Callback callback,
-            AvoidBadWifiTracker tracker) throws IllegalArgumentException {
+            MultinetworkPolicyTracker tracker) throws IllegalArgumentException {
         mInterfaceName = ifName;
         int ifIndex = -1;
         try {
@@ -238,7 +238,7 @@
         mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, TAG + "." + mInterfaceName);
         mCallback = callback;
-        mAvoidBadWifiTracker = tracker;
+        mMultinetworkPolicyTracker = tracker;
         mNetlinkSocketObserver = new NetlinkSocketObserver();
         mObserverThread = new Thread(mNetlinkSocketObserver);
         mObserverThread.start();
@@ -379,7 +379,7 @@
     }
 
     private boolean avoidingBadLinks() {
-        return (mAvoidBadWifiTracker != null) ? mAvoidBadWifiTracker.currentValue() : true;
+        return (mMultinetworkPolicyTracker == null) || mMultinetworkPolicyTracker.getAvoidBadWifi();
     }
 
     public void probeAll() {
diff --git a/services/net/java/android/net/util/AvoidBadWifiTracker.java b/services/net/java/android/net/util/MultinetworkPolicyTracker.java
similarity index 78%
rename from services/net/java/android/net/util/AvoidBadWifiTracker.java
rename to services/net/java/android/net/util/MultinetworkPolicyTracker.java
index 2abaeb1..ebd131b 100644
--- a/services/net/java/android/net/util/AvoidBadWifiTracker.java
+++ b/services/net/java/android/net/util/MultinetworkPolicyTracker.java
@@ -42,8 +42,8 @@
  * This enables the device to switch to another form of connectivity, like
  * mobile, if it's available and working.
  *
- * The Runnable |cb|, if given, is called on the supplied Handler's thread
- * whether the computed "avoid bad wifi" value changes.
+ * The Runnable |avoidBadWifiCallback|, if given, is posted to the supplied
+ * Handler' whenever the computed "avoid bad wifi" value changes.
  *
  * Disabling this reverts the device to a level of networking sophistication
  * circa 2012-13 by disabling disparate code paths each of which contribute to
@@ -51,28 +51,30 @@
  *
  * @hide
  */
-public class AvoidBadWifiTracker {
-    private static String TAG = AvoidBadWifiTracker.class.getSimpleName();
+public class MultinetworkPolicyTracker {
+    private static String TAG = MultinetworkPolicyTracker.class.getSimpleName();
 
     private final Context mContext;
     private final Handler mHandler;
     private final Runnable mReevaluateRunnable;
-    private final Uri mUri;
+    private final Uri mAvoidBadWifiUri;
     private final ContentResolver mResolver;
     private final SettingObserver mSettingObserver;
     private final BroadcastReceiver mBroadcastReceiver;
 
     private volatile boolean mAvoidBadWifi = true;
 
-    public AvoidBadWifiTracker(Context ctx, Handler handler) {
+    public MultinetworkPolicyTracker(Context ctx, Handler handler) {
         this(ctx, handler, null);
     }
 
-    public AvoidBadWifiTracker(Context ctx, Handler handler, Runnable cb) {
+    public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) {
         mContext = ctx;
         mHandler = handler;
-        mReevaluateRunnable = () -> { if (update() && cb != null) cb.run(); };
-        mUri = Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI);
+        mReevaluateRunnable = () -> {
+            if (updateAvoidBadWifi() && avoidBadWifiCallback != null) avoidBadWifiCallback.run();
+        };
+        mAvoidBadWifiUri = Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI);
         mResolver = mContext.getContentResolver();
         mSettingObserver = new SettingObserver();
         mBroadcastReceiver = new BroadcastReceiver() {
@@ -82,11 +84,11 @@
             }
         };
 
-        update();
+        updateAvoidBadWifi();
     }
 
     public void start() {
-        mResolver.registerContentObserver(mUri, false, mSettingObserver);
+        mResolver.registerContentObserver(mAvoidBadWifiUri, false, mSettingObserver);
 
         final IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -102,7 +104,7 @@
         mContext.unregisterReceiver(mBroadcastReceiver);
     }
 
-    public boolean currentValue() {
+    public boolean getAvoidBadWifi() {
         return mAvoidBadWifi;
     }
 
@@ -117,10 +119,10 @@
      * Whether we should display a notification when wifi becomes unvalidated.
      */
     public boolean shouldNotifyWifiUnvalidated() {
-        return configRestrictsAvoidBadWifi() && getSettingsValue() == null;
+        return configRestrictsAvoidBadWifi() && getAvoidBadWifiSetting() == null;
     }
 
-    public String getSettingsValue() {
+    public String getAvoidBadWifiSetting() {
         return Settings.Global.getString(mResolver, NETWORK_AVOID_BAD_WIFI);
     }
 
@@ -129,8 +131,8 @@
         mHandler.post(mReevaluateRunnable);
     }
 
-    public boolean update() {
-        final boolean settingAvoidBadWifi = "1".equals(getSettingsValue());
+    public boolean updateAvoidBadWifi() {
+        final boolean settingAvoidBadWifi = "1".equals(getAvoidBadWifiSetting());
         final boolean prev = mAvoidBadWifi;
         mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi();
         return mAvoidBadWifi != prev;
@@ -148,7 +150,7 @@
 
         @Override
         public void onChange(boolean selfChange, Uri uri) {
-            if (!mUri.equals(uri)) return;
+            if (!mAvoidBadWifiUri.equals(uri)) return;
             reevaluate();
         }
     }
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index f89fd47..f30c466 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -345,6 +345,10 @@
         um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
         // Disallow rebooting in safe mode - controlled by user 0
         um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
+        if (mIsCarrierDemoMode) {
+            // Enable SMS in carrier demo mode.
+            um.setUserRestriction(UserManager.DISALLOW_SMS, false, user);
+        }
 
         Settings.Secure.putIntForUser(mInjector.getContentResolver(),
                 Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
new file mode 100644
index 0000000..cf477f2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import android.accessibilityservice.FingerprintGestureController;
+import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.os.Looper;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static android.accessibilityservice.FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for FingerprintGestureController.
+ * TODO: These tests aren't really for server code, so this isn't their ideal home.
+ */
+public class FingerprintGestureControllerTest {
+    @Mock IAccessibilityServiceConnection mMockAccessibilityServiceConnection;
+    @Mock FingerprintGestureCallback mMockFingerprintGestureCallback;
+    FingerprintGestureController mFingerprintGestureController;
+
+    @BeforeClass
+    public static void oneTimeInitialization() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mFingerprintGestureController =
+                new FingerprintGestureController(mMockAccessibilityServiceConnection);
+    }
+
+    @Test
+    public void testIsGestureDetectionActive_returnsValueFromServer() throws Exception {
+        when(mMockAccessibilityServiceConnection.isFingerprintGestureDetectionAvailable())
+                .thenReturn(true);
+        assertTrue(mFingerprintGestureController.isGestureDetectionAvailable());
+        when(mMockAccessibilityServiceConnection.isFingerprintGestureDetectionAvailable())
+                .thenReturn(false);
+        assertFalse(mFingerprintGestureController.isGestureDetectionAvailable());
+    }
+
+    @Test
+    public void testCallbacks_withNoListeners_shouldNotCrash() {
+        mFingerprintGestureController.onGestureDetectionActiveChanged(true);
+        mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+    }
+
+    @Test
+    public void testDetectionActiveCallback_noHandler_shouldCallback() {
+        mFingerprintGestureController.registerFingerprintGestureCallback(
+                mMockFingerprintGestureCallback, null);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(true);
+        verify(mMockFingerprintGestureCallback, times(1))
+                .onGestureDetectionAvailabilityChanged(true);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(false);
+        verify(mMockFingerprintGestureCallback, times(1))
+                .onGestureDetectionAvailabilityChanged(false);
+
+        reset(mMockFingerprintGestureCallback);
+        mFingerprintGestureController.unregisterFingerprintGestureCallback(
+                mMockFingerprintGestureCallback);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(true);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(false);
+        verifyZeroInteractions(mMockFingerprintGestureCallback);
+    }
+
+    @Test
+    public void testDetectionActiveCallback_withHandler_shouldPostRunnableToHandler() {
+        MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
+            message.getCallback().run();
+            return true;
+        });
+
+        mFingerprintGestureController.registerFingerprintGestureCallback(
+                mMockFingerprintGestureCallback, messageCapturingHandler);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(true);
+        verify(mMockFingerprintGestureCallback, times(0))
+                .onGestureDetectionAvailabilityChanged(true);
+        messageCapturingHandler.sendLastMessage();
+        verify(mMockFingerprintGestureCallback, times(1))
+                .onGestureDetectionAvailabilityChanged(true);
+
+        mFingerprintGestureController.onGestureDetectionActiveChanged(false);
+        verify(mMockFingerprintGestureCallback, times(0))
+                .onGestureDetectionAvailabilityChanged(false);
+        messageCapturingHandler.sendLastMessage();
+        verify(mMockFingerprintGestureCallback, times(1))
+                .onGestureDetectionAvailabilityChanged(false);
+
+        reset(mMockFingerprintGestureCallback);
+        mFingerprintGestureController.unregisterFingerprintGestureCallback(
+                mMockFingerprintGestureCallback);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(true);
+        mFingerprintGestureController.onGestureDetectionActiveChanged(false);
+        assertFalse(messageCapturingHandler.hasMessages());
+        verifyZeroInteractions(mMockFingerprintGestureCallback);
+    }
+
+    @Test
+    public void testGestureCallback_noHandler_shouldCallListener() {
+        mFingerprintGestureController.registerFingerprintGestureCallback(
+                mMockFingerprintGestureCallback, null);
+        mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+        verify(mMockFingerprintGestureCallback, times(1)).onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+
+        reset(mMockFingerprintGestureCallback);
+        mFingerprintGestureController.unregisterFingerprintGestureCallback(
+                mMockFingerprintGestureCallback);
+        mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+        verifyZeroInteractions(mMockFingerprintGestureCallback);
+    }
+
+    @Test
+    public void testGestureCallback_withHandler_shouldPostRunnableToHandler() {
+        MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
+            message.getCallback().run();
+            return true;
+        });
+
+        mFingerprintGestureController.registerFingerprintGestureCallback(
+                mMockFingerprintGestureCallback, messageCapturingHandler);
+        mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+        verify(mMockFingerprintGestureCallback, times(0)).onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+        messageCapturingHandler.sendLastMessage();
+        verify(mMockFingerprintGestureCallback, times(1)).onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+
+        reset(mMockFingerprintGestureCallback);
+        mFingerprintGestureController.unregisterFingerprintGestureCallback(
+                mMockFingerprintGestureCallback);
+        mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
+        assertFalse(messageCapturingHandler.hasMessages());
+        verifyZeroInteractions(mMockFingerprintGestureCallback);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java
new file mode 100644
index 0000000..98bf53c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import android.accessibilityservice.FingerprintGestureController;
+import android.hardware.fingerprint.IFingerprintService;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+
+import com.android.server.accessibility.FingerprintGestureDispatcher.FingerprintGestureClient;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for FingerprintGestureDispatcher
+ */
+public class FingerprintGestureDispatcherTest {
+
+    private @Mock IFingerprintService mMockFingerprintService;
+    private @Mock FingerprintGestureClient mNonGestureCapturingClient;
+    private @Mock FingerprintGestureClient mGestureCapturingClient;
+    private @Mock FingerprintGestureDispatcher mFingerprintGestureDispatcher;
+    private MessageCapturingHandler mMessageCapturingHandler;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mMessageCapturingHandler = new MessageCapturingHandler(
+                msg -> mFingerprintGestureDispatcher.handleMessage(msg));
+        mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(mMockFingerprintService,
+                new Object(), mMessageCapturingHandler);
+        when(mNonGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(false);
+        when(mGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(true);
+    }
+
+    @Test
+    public void testNoServices_doesNotCrashOrConsumeGestures() {
+        mFingerprintGestureDispatcher.onClientActiveChanged(true);
+        mFingerprintGestureDispatcher.onClientActiveChanged(false);
+        assertFalse(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP));
+    }
+
+    @Test
+    public void testOneNonCapturingService_doesNotCrashOrConsumeGestures() {
+        mFingerprintGestureDispatcher.updateClientList(
+                Arrays.asList(mNonGestureCapturingClient));
+        mFingerprintGestureDispatcher.onClientActiveChanged(true);
+        mFingerprintGestureDispatcher.onClientActiveChanged(false);
+        assertFalse(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP));
+        verify(mNonGestureCapturingClient, times(0))
+                .onFingerprintGestureDetectionActiveChanged(anyBoolean());
+        verify(mNonGestureCapturingClient, times(0)).onFingerprintGesture(anyInt());
+    }
+
+    @Test
+    public void testOneCapturingService_notifiesClientOfActivityChanges() {
+        mFingerprintGestureDispatcher.updateClientList(
+                Arrays.asList(mGestureCapturingClient));
+        mFingerprintGestureDispatcher.onClientActiveChanged(true);
+        // Client active means gesture detection isn't.
+        verify(mGestureCapturingClient, times(1)).onFingerprintGestureDetectionActiveChanged(false);
+        verify(mGestureCapturingClient, times(0)).onFingerprintGestureDetectionActiveChanged(true);
+        mFingerprintGestureDispatcher.onClientActiveChanged(false);
+        verify(mGestureCapturingClient, times(1)).onFingerprintGestureDetectionActiveChanged(false);
+        verify(mGestureCapturingClient, times(1)).onFingerprintGestureDetectionActiveChanged(true);
+    }
+
+    @Test
+    public void testOneCapturingService_consumesGesturesAndPassesThemAlong() {
+        mFingerprintGestureDispatcher.updateClientList(
+                Arrays.asList(mGestureCapturingClient));
+        assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP));
+        verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
+                FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_UP);
+        assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN));
+        verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
+                FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN);
+        assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT));
+        verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
+                FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_LEFT);
+        assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT));
+        verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
+                FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_RIGHT);
+    }
+
+    @Test
+    public void testInvalidKeyCodes_areNotCaptured() {
+        mFingerprintGestureDispatcher.updateClientList(
+                Arrays.asList(mGestureCapturingClient));
+        assertFalse(mFingerprintGestureDispatcher.onFingerprintGesture(
+                KeyEvent.KEYCODE_SPACE));
+        verify(mGestureCapturingClient, times(0)).onFingerprintGesture(anyInt());
+    }
+
+    @Test
+    public void testWithCapturingService_registersForFingerprintUpdates() throws Exception {
+        verifyNoMoreInteractions(mMockFingerprintService);
+        mFingerprintGestureDispatcher.updateClientList(
+                Arrays.asList(mGestureCapturingClient));
+        mMessageCapturingHandler.sendOneMessage();
+        verify(mMockFingerprintService).addClientActiveCallback(mFingerprintGestureDispatcher);
+    }
+
+    @Test
+    public void testWhenCapturingServiceStops_unregistersForFingerprintUpdates() throws Exception {
+        verifyNoMoreInteractions(mMockFingerprintService);
+        mFingerprintGestureDispatcher.updateClientList(
+                Arrays.asList(mGestureCapturingClient));
+        mMessageCapturingHandler.sendOneMessage();
+        mFingerprintGestureDispatcher.updateClientList(Collections.emptyList());
+        mMessageCapturingHandler.sendOneMessage();
+        verify(mMockFingerprintService).removeClientActiveCallback(mFingerprintGestureDispatcher);
+    }
+
+    @Test
+    public void testIsGestureDetectionActive_dependsOnFingerprintService() throws Exception {
+        when(mMockFingerprintService.isClientActive()).thenReturn(true);
+        assertFalse(mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable());
+        when(mMockFingerprintService.isClientActive()).thenReturn(false);
+        assertTrue(mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable());
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2d7a68f..39406a11 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -53,7 +53,7 @@
 import android.net.NetworkRequest;
 import android.net.RouteInfo;
 import android.net.metrics.IpConnectivityLog;
-import android.net.util.AvoidBadWifiTracker;
+import android.net.util.MultinetworkPolicyTracker;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -155,25 +155,13 @@
     /**
      * Block until the given handler becomes idle, or until timeoutMs has passed.
      */
-    private static void waitForIdleHandler(HandlerThread handler, int timeoutMs) {
+    private static void waitForIdleHandler(HandlerThread handlerThread, int timeoutMs) {
         final ConditionVariable cv = new ConditionVariable();
-        final MessageQueue queue = handler.getLooper().getQueue();
-        final IdleHandler idleHandler = () -> {
-            synchronized (queue) {
-                cv.open();
-                return false; // Remove the idleHandler.
-            }
-        };
-        synchronized (queue) {
-            if (queue.isIdle()) {
-                return;
-            }
-            queue.addIdleHandler(idleHandler);
-        }
+        final Handler handler = new Handler(handlerThread.getLooper());
+        handler.post(() -> cv.open());
         if (!cv.block(timeoutMs)) {
-            fail("HandlerThread " + handler.getName() +
+            fail("HandlerThread " + handlerThread.getName() +
                     " did not become idle after " + timeoutMs + " ms");
-            queue.removeIdleHandler(idleHandler);
         }
     }
 
@@ -605,10 +593,10 @@
         }
     }
 
-    private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
+    private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
         public volatile boolean configRestrictsAvoidBadWifi;
 
-        public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
+        public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
             super(c, h, r);
         }
 
@@ -619,7 +607,7 @@
     }
 
     private class WrappedConnectivityService extends ConnectivityService {
-        public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
+        public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
 
         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
@@ -666,14 +654,14 @@
         }
 
         @Override
-        public AvoidBadWifiTracker createAvoidBadWifiTracker(
+        public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
                 Context c, Handler h, Runnable r) {
-            final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
+            final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
             return tracker;
         }
 
-        public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
-            return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
+        public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
+            return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
         }
 
         @Override
@@ -695,22 +683,6 @@
         }
     }
 
-    private interface Criteria {
-        public boolean get();
-    }
-
-    /**
-     * Wait up to 500ms for {@code criteria.get()} to become true, polling.
-     * Fails if 500ms goes by before {@code criteria.get()} to become true.
-     */
-    static private void waitFor(Criteria criteria) {
-        int delays = 0;
-        while (!criteria.get()) {
-            sleepFor(50);
-            if (++delays == 10) fail();
-        }
-    }
-
     /**
      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
@@ -846,8 +818,9 @@
         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
         // Test cellular linger timeout.
-        waitFor(new Criteria() {
-                public boolean get() { return mCm.getAllNetworks().length == 1; } });
+        waitFor(mCellNetworkAgent.getDisconnectedCV());
+        mService.waitForIdle();
+        assertEquals(1, mCm.getAllNetworks().length);
         verifyActiveNetwork(TRANSPORT_WIFI);
         assertEquals(1, mCm.getAllNetworks().length);
         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
@@ -1622,8 +1595,8 @@
         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
         mCellNetworkAgent.connectWithoutInternet();
         waitFor(cv);
-        waitFor(new Criteria() {
-                public boolean get() { return mCm.getAllNetworks().length == 0; } });
+        mService.waitForIdle();
+        assertEquals(0, mCm.getAllNetworks().length);
         verifyNoNetwork();
         // Test bringing up validated WiFi.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -1982,7 +1955,6 @@
 
         // Disconnect wifi and check that cell is foreground again.
         mWiFiNetworkAgent.disconnect();
-        mService.waitForIdle();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
@@ -2152,7 +2124,7 @@
     @SmallTest
     public void testAvoidBadWifiSetting() throws Exception {
         final ContentResolver cr = mServiceContext.getContentResolver();
-        final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
+        final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
 
         tracker.configRestrictsAvoidBadWifi = false;
@@ -2162,7 +2134,7 @@
             tracker.reevaluate();
             mService.waitForIdle();
             String msg = String.format("config=false, setting=%s", values[i]);
-            assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
+            assertTrue(mService.avoidBadWifi());
             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
         }
 
@@ -2171,26 +2143,26 @@
         Settings.Global.putInt(cr, settingName, 0);
         tracker.reevaluate();
         mService.waitForIdle();
-        assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
+        assertFalse(mService.avoidBadWifi());
         assertFalse(tracker.shouldNotifyWifiUnvalidated());
 
         Settings.Global.putInt(cr, settingName, 1);
         tracker.reevaluate();
         mService.waitForIdle();
-        assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
+        assertTrue(mService.avoidBadWifi());
         assertFalse(tracker.shouldNotifyWifiUnvalidated());
 
         Settings.Global.putString(cr, settingName, null);
         tracker.reevaluate();
         mService.waitForIdle();
-        assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
+        assertFalse(mService.avoidBadWifi());
         assertTrue(tracker.shouldNotifyWifiUnvalidated());
     }
 
     @SmallTest
     public void testAvoidBadWifi() throws Exception {
         final ContentResolver cr = mServiceContext.getContentResolver();
-        final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
+        final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
 
         // Pretend we're on a carrier that restricts switching away from bad wifi.
         tracker.configRestrictsAvoidBadWifi = true;
@@ -2404,17 +2376,6 @@
         networkCallback.assertNoCallback();
     }
 
-    public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) {
-        long start = SystemClock.elapsedRealtime();
-        while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) {
-            if (fn.getAsBoolean()) {
-                return;
-            }
-            sleepFor(15);
-        }
-        assertTrue(fn.getAsBoolean());
-    }
-
     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
 
         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
@@ -2575,12 +2536,13 @@
         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
         callback.expectStarted();
         mWiFiNetworkAgent.disconnect();
+        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
 
         // ... and that stopping it after that has no adverse effects.
-        // TODO: investigate assertEventuallyTrue is needed and waitForIdle() is not enough
+        mService.waitForIdle();
         final Network myNetAlias = myNet;
-        assertEventuallyTrue(() -> mCm.getNetworkCapabilities(myNetAlias) == null, 100);
+        assertNull(mCm.getNetworkCapabilities(myNetAlias));
         ka.stop();
 
         // Reconnect.
@@ -2592,6 +2554,7 @@
         callback.expectStarted();
         ka.stop();
         mWiFiNetworkAgent.disconnect();
+        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
         mService.waitForIdle();
         callback.expectStopped();
 
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
index 36e4717..04dea1b 100755
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
@@ -19,16 +19,16 @@
 import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.content.Context;
-import android.os.Handler;
 import android.net.INetworkScoreCache;
 import android.net.NetworkKey;
 import android.net.ScoredNetwork;
+import android.os.Handler;
+import android.os.Process;
 import android.util.Log;
 
-import com.android.internal.util.Preconditions;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -76,7 +76,7 @@
     public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) {
         mContext = context.getApplicationContext();
         mListener = listener;
-        mNetworkCache = new HashMap<String, ScoredNetwork>();
+        mNetworkCache = new HashMap<>();
     }
 
     @Override public final void updateScores(List<ScoredNetwork> networks) {
@@ -244,7 +244,9 @@
 
     @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
-        writer.println("WifiNetworkScoreCache");
+        String header = String.format("WifiNetworkScoreCache (%s/%d)",
+                mContext.getPackageName(), Process.myUid());
+        writer.println(header);
         writer.println("  All score curves:");
         for (ScoredNetwork score : mNetworkCache.values()) {
             writer.println("    " + score);
diff --git a/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java b/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
index 96db5d0..78b335d 100644
--- a/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
+++ b/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
@@ -175,7 +175,7 @@
         }
 
         // Credential is needed for storing the certificates and private client key.
-        if (config.credential == null) {
+        if (config.getCredential() == null) {
             throw new IOException("Passpoint profile missing credential");
         }
 
@@ -183,7 +183,7 @@
         byte[] caCertData = mimeParts.get(TYPE_CA_CERT);
         if (caCertData != null) {
             try {
-                config.credential.caCertificate = parseCACert(caCertData);
+                config.getCredential().setCaCertificate(parseCACert(caCertData));
             } catch (CertificateException e) {
                 throw new IOException("Failed to parse CA Certificate");
             }
@@ -194,9 +194,9 @@
         if (pkcs12Data != null) {
             try {
                 Pair<PrivateKey, List<X509Certificate>> clientKey = parsePkcs12(pkcs12Data);
-                config.credential.clientPrivateKey = clientKey.first;
-                config.credential.clientCertificateChain =
-                        clientKey.second.toArray(new X509Certificate[clientKey.second.size()]);
+                config.getCredential().setClientPrivateKey(clientKey.first);
+                config.getCredential().setClientCertificateChain(
+                        clientKey.second.toArray(new X509Certificate[clientKey.second.size()]));
             } catch(GeneralSecurityException | IOException e) {
                 throw new IOException("Failed to parse PCKS12 string");
             }
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index f1174b6..c2b307d 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -30,6 +30,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Class representing Passpoint configuration.  This contains configurations specified in
@@ -58,21 +59,58 @@
      */
     private static final int NULL_VALUE = -1;
 
-    public HomeSP homeSp = null;
-    public Credential credential = null;
-    public Policy policy = null;
+    /**
+     * Configurations under HomeSP subtree.
+     */
+    private HomeSP mHomeSp = null;
+    public void setHomeSp(HomeSP homeSp) { mHomeSp = homeSp; }
+    public HomeSP getHomeSp() { return mHomeSp; }
+
+    /**
+     * Configurations under Credential subtree.
+     */
+    private Credential mCredential = null;
+    public void setCredential(Credential credential) {
+        mCredential = credential;
+    }
+    public Credential getCredential() {
+        return mCredential;
+    }
+
+    /**
+     * Configurations under Policy subtree.
+     */
+    private Policy mPolicy = null;
+    public void setPolicy(Policy policy) {
+        mPolicy = policy;
+    }
+    public Policy getPolicy() {
+        return mPolicy;
+    }
 
     /**
      * Meta data for performing subscription update.
      */
-    public UpdateParameter subscriptionUpdate = null;
+    private UpdateParameter mSubscriptionUpdate = null;
+    public void setSubscriptionUpdate(UpdateParameter subscriptionUpdate) {
+        mSubscriptionUpdate = subscriptionUpdate;
+    }
+    public UpdateParameter getSubscriptionUpdate() {
+        return mSubscriptionUpdate;
+    }
 
     /**
      * List of HTTPS URL for retrieving trust root certificate and the corresponding SHA-256
      * fingerprint of the certificate.  The certificates are used for verifying AAA server's
      * identity during EAP authentication.
      */
-    public Map<String, byte[]> trustRootCertList = null;
+    private Map<String, byte[]> mTrustRootCertList = null;
+    public void setTrustRootCertList(Map<String, byte[]> trustRootCertList) {
+        mTrustRootCertList = trustRootCertList;
+    }
+    public Map<String, byte[]> getTrustRootCertList() {
+        return mTrustRootCertList;
+    }
 
     /**
      * Set by the subscription server, updated every time the configuration is updated by
@@ -80,14 +118,26 @@
      *
      * Use Integer.MIN_VALUE to indicate unset value.
      */
-    public int updateIdentifier = Integer.MIN_VALUE;
+    private int mUpdateIdentifier = Integer.MIN_VALUE;
+    public void setUpdateIdentifier(int updateIdentifier) {
+        mUpdateIdentifier = updateIdentifier;
+    }
+    public int getUpdateIdentififer() {
+        return mUpdateIdentifier;
+    }
 
     /**
      * The priority of the credential.
      *
      * Use Integer.MIN_VALUE to indicate unset value.
      */
-    public int credentialPriority = Integer.MIN_VALUE;
+    private int mCredentialPriority = Integer.MIN_VALUE;
+    public void setCredentialPriority(int credentialPriority) {
+        mCredentialPriority = credentialPriority;
+    }
+    public int getCredentialPriority() {
+        return mCredentialPriority;
+    }
 
     /**
      * The time this subscription is created. It is in the format of number
@@ -95,7 +145,13 @@
      *
      * Use Long.MIN_VALUE to indicate unset value.
      */
-    public long subscriptionCreationTimeInMs = Long.MIN_VALUE;
+    private long mSubscriptionCreationTimeInMs = Long.MIN_VALUE;
+    public void setSubscriptionCreationTimeInMs(long subscriptionCreationTimeInMs) {
+        mSubscriptionCreationTimeInMs = subscriptionCreationTimeInMs;
+    }
+    public long getSubscriptionCreationTimeInMs() {
+        return mSubscriptionCreationTimeInMs;
+    }
 
     /**
      * The time this subscription will expire. It is in the format of number
@@ -103,20 +159,38 @@
      *
      * Use Long.MIN_VALUE to indicate unset value.
      */
-    public long subscriptionExpirationTimeInMs = Long.MIN_VALUE;
+    private long mSubscriptionExpirationTimeInMs = Long.MIN_VALUE;
+    public void setSubscriptionExpirationTimeInMs(long subscriptionExpirationTimeInMs) {
+        mSubscriptionExpirationTimeInMs = subscriptionExpirationTimeInMs;
+    }
+    public long getSubscriptionExpirationTimeInMs() {
+        return mSubscriptionExpirationTimeInMs;
+    }
 
     /**
      * The type of the subscription.  This is defined by the provider and the value is provider
      * specific.
      */
-    public String subscriptionType = null;
+    private String mSubscriptionType = null;
+    public void setSubscriptionType(String subscriptionType) {
+        mSubscriptionType = subscriptionType;
+    }
+    public String getSubscriptionType() {
+        return mSubscriptionType;
+    }
 
     /**
      * The time period for usage statistics accumulation. A value of zero means that usage
      * statistics are not accumulated on a periodic basis (e.g., a one-time limit for
      * “pay as you go” - PAYG service). A non-zero value specifies the usage interval in minutes.
      */
-    public long usageLimitUsageTimePeriodInMinutes = Long.MIN_VALUE;
+    private long mUsageLimitUsageTimePeriodInMinutes = Long.MIN_VALUE;
+    public void setUsageLimitUsageTimePeriodInMinutes(long usageLimitUsageTimePeriodInMinutes) {
+        mUsageLimitUsageTimePeriodInMinutes = usageLimitUsageTimePeriodInMinutes;
+    }
+    public long getUsageLimitUsageTimePeriodInMinutes() {
+        return mUsageLimitUsageTimePeriodInMinutes;
+    }
 
     /**
      * The time at which usage statistic accumulation  begins.  It is in the format of number
@@ -124,7 +198,13 @@
      *
      * Use Long.MIN_VALUE to indicate unset value.
      */
-    public long usageLimitStartTimeInMs = Long.MIN_VALUE;
+    private long mUsageLimitStartTimeInMs = Long.MIN_VALUE;
+    public void setUsageLimitStartTimeInMs(long usageLimitStartTimeInMs) {
+        mUsageLimitStartTimeInMs = usageLimitStartTimeInMs;
+    }
+    public long getUsageLimitStartTimeInMs() {
+        return mUsageLimitStartTimeInMs;
+    }
 
     /**
      * The cumulative data limit in megabytes for the {@link #usageLimitUsageTimePeriodInMinutes}.
@@ -132,14 +212,25 @@
      *
      * Use Long.MIN_VALUE to indicate unset value.
      */
-    public long usageLimitDataLimit = Long.MIN_VALUE;
+    private long mUsageLimitDataLimit = Long.MIN_VALUE;
+    public void setUsageLimitDataLimit(long usageLimitDataLimit) {
+        mUsageLimitDataLimit = usageLimitDataLimit;
+    }
+    public long getUsageLimitDataLimit() {
+        return mUsageLimitDataLimit;
+    }
 
     /**
      * The cumulative time limit in minutes for the {@link #usageLimitUsageTimePeriodInMinutes}.
      * A value of zero indicate unlimited time usage.
      */
-    public long usageLimitTimeLimitInMinutes = Long.MIN_VALUE;
-
+    private long mUsageLimitTimeLimitInMinutes = Long.MIN_VALUE;
+    public void setUsageLimitTimeLimitInMinutes(long usageLimitTimeLimitInMinutes) {
+        mUsageLimitTimeLimitInMinutes = usageLimitTimeLimitInMinutes;
+    }
+    public long getUsageLimitTimeLimitInMinutes() {
+        return mUsageLimitTimeLimitInMinutes;
+    }
 
     /**
      * Constructor for creating PasspointConfiguration with default values.
@@ -156,30 +247,30 @@
             return;
         }
 
-        if (source.homeSp != null) {
-            homeSp = new HomeSP(source.homeSp);
+        if (source.mHomeSp != null) {
+            mHomeSp = new HomeSP(source.mHomeSp);
         }
-        if (source.credential != null) {
-            credential = new Credential(source.credential);
+        if (source.mCredential != null) {
+            mCredential = new Credential(source.mCredential);
         }
-        if (source.policy != null) {
-            policy = new Policy(source.policy);
+        if (source.mPolicy != null) {
+            mPolicy = new Policy(source.mPolicy);
         }
-        if (source.trustRootCertList != null) {
-            trustRootCertList = Collections.unmodifiableMap(source.trustRootCertList);
+        if (source.mTrustRootCertList != null) {
+            mTrustRootCertList = Collections.unmodifiableMap(source.mTrustRootCertList);
         }
-        if (source.subscriptionUpdate != null) {
-            subscriptionUpdate = new UpdateParameter(source.subscriptionUpdate);
+        if (source.mSubscriptionUpdate != null) {
+            mSubscriptionUpdate = new UpdateParameter(source.mSubscriptionUpdate);
         }
-        updateIdentifier = source.updateIdentifier;
-        credentialPriority = source.credentialPriority;
-        subscriptionCreationTimeInMs = source.subscriptionCreationTimeInMs;
-        subscriptionExpirationTimeInMs = source.subscriptionExpirationTimeInMs;
-        subscriptionType = source.subscriptionType;
-        usageLimitDataLimit = source.usageLimitDataLimit;
-        usageLimitStartTimeInMs = source.usageLimitStartTimeInMs;
-        usageLimitTimeLimitInMinutes = source.usageLimitTimeLimitInMinutes;
-        usageLimitUsageTimePeriodInMinutes = source.usageLimitUsageTimePeriodInMinutes;
+        mUpdateIdentifier = source.mUpdateIdentifier;
+        mCredentialPriority = source.mCredentialPriority;
+        mSubscriptionCreationTimeInMs = source.mSubscriptionCreationTimeInMs;
+        mSubscriptionExpirationTimeInMs = source.mSubscriptionExpirationTimeInMs;
+        mSubscriptionType = source.mSubscriptionType;
+        mUsageLimitDataLimit = source.mUsageLimitDataLimit;
+        mUsageLimitStartTimeInMs = source.mUsageLimitStartTimeInMs;
+        mUsageLimitTimeLimitInMinutes = source.mUsageLimitTimeLimitInMinutes;
+        mUsageLimitUsageTimePeriodInMinutes = source.mUsageLimitUsageTimePeriodInMinutes;
     }
 
     @Override
@@ -189,20 +280,20 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(homeSp, flags);
-        dest.writeParcelable(credential, flags);
-        dest.writeParcelable(policy, flags);
-        dest.writeParcelable(subscriptionUpdate, flags);
-        writeTrustRootCerts(dest, trustRootCertList);
-        dest.writeInt(updateIdentifier);
-        dest.writeInt(credentialPriority);
-        dest.writeLong(subscriptionCreationTimeInMs);
-        dest.writeLong(subscriptionExpirationTimeInMs);
-        dest.writeString(subscriptionType);
-        dest.writeLong(usageLimitUsageTimePeriodInMinutes);
-        dest.writeLong(usageLimitStartTimeInMs);
-        dest.writeLong(usageLimitDataLimit);
-        dest.writeLong(usageLimitTimeLimitInMinutes);
+        dest.writeParcelable(mHomeSp, flags);
+        dest.writeParcelable(mCredential, flags);
+        dest.writeParcelable(mPolicy, flags);
+        dest.writeParcelable(mSubscriptionUpdate, flags);
+        writeTrustRootCerts(dest, mTrustRootCertList);
+        dest.writeInt(mUpdateIdentifier);
+        dest.writeInt(mCredentialPriority);
+        dest.writeLong(mSubscriptionCreationTimeInMs);
+        dest.writeLong(mSubscriptionExpirationTimeInMs);
+        dest.writeString(mSubscriptionType);
+        dest.writeLong(mUsageLimitUsageTimePeriodInMinutes);
+        dest.writeLong(mUsageLimitStartTimeInMs);
+        dest.writeLong(mUsageLimitDataLimit);
+        dest.writeLong(mUsageLimitTimeLimitInMinutes);
     }
 
     @Override
@@ -214,22 +305,30 @@
             return false;
         }
         PasspointConfiguration that = (PasspointConfiguration) thatObject;
-        return (homeSp == null ? that.homeSp == null : homeSp.equals(that.homeSp))
-                && (credential == null ? that.credential == null
-                        : credential.equals(that.credential))
-                && (policy == null ? that.policy == null : policy.equals(that.policy))
-                && (subscriptionUpdate == null ? that.subscriptionUpdate == null
-                        : subscriptionUpdate.equals(that.subscriptionUpdate))
-                && isTrustRootCertListEquals(trustRootCertList, that.trustRootCertList)
-                && updateIdentifier == that.updateIdentifier
-                && credentialPriority == that.credentialPriority
-                && subscriptionCreationTimeInMs == that.subscriptionCreationTimeInMs
-                && subscriptionExpirationTimeInMs == that.subscriptionExpirationTimeInMs
-                && TextUtils.equals(subscriptionType, that.subscriptionType)
-                && usageLimitUsageTimePeriodInMinutes == that.usageLimitUsageTimePeriodInMinutes
-                && usageLimitStartTimeInMs == that.usageLimitStartTimeInMs
-                && usageLimitDataLimit == that.usageLimitDataLimit
-                && usageLimitTimeLimitInMinutes == that .usageLimitTimeLimitInMinutes;
+        return (mHomeSp == null ? that.mHomeSp == null : mHomeSp.equals(that.mHomeSp))
+                && (mCredential == null ? that.mCredential == null
+                        : mCredential.equals(that.mCredential))
+                && (mPolicy == null ? that.mPolicy == null : mPolicy.equals(that.mPolicy))
+                && (mSubscriptionUpdate == null ? that.mSubscriptionUpdate == null
+                        : mSubscriptionUpdate.equals(that.mSubscriptionUpdate))
+                && isTrustRootCertListEquals(mTrustRootCertList, that.mTrustRootCertList)
+                && mUpdateIdentifier == that.mUpdateIdentifier
+                && mCredentialPriority == that.mCredentialPriority
+                && mSubscriptionCreationTimeInMs == that.mSubscriptionCreationTimeInMs
+                && mSubscriptionExpirationTimeInMs == that.mSubscriptionExpirationTimeInMs
+                && TextUtils.equals(mSubscriptionType, that.mSubscriptionType)
+                && mUsageLimitUsageTimePeriodInMinutes == that.mUsageLimitUsageTimePeriodInMinutes
+                && mUsageLimitStartTimeInMs == that.mUsageLimitStartTimeInMs
+                && mUsageLimitDataLimit == that.mUsageLimitDataLimit
+                && mUsageLimitTimeLimitInMinutes == that.mUsageLimitTimeLimitInMinutes;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mHomeSp, mCredential, mPolicy, mSubscriptionUpdate, mTrustRootCertList,
+                mUpdateIdentifier, mCredentialPriority, mSubscriptionCreationTimeInMs,
+                mSubscriptionExpirationTimeInMs, mUsageLimitUsageTimePeriodInMinutes,
+                mUsageLimitStartTimeInMs, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes);
     }
 
     /**
@@ -238,20 +337,20 @@
      * @return true on success or false on failure
      */
     public boolean validate() {
-        if (homeSp == null || !homeSp.validate()) {
+        if (mHomeSp == null || !mHomeSp.validate()) {
             return false;
         }
-        if (credential == null || !credential.validate()) {
+        if (mCredential == null || !mCredential.validate()) {
             return false;
         }
-        if (policy != null && !policy.validate()) {
+        if (mPolicy != null && !mPolicy.validate()) {
             return false;
         }
-        if (subscriptionUpdate != null && !subscriptionUpdate.validate()) {
+        if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
             return false;
         }
-        if (trustRootCertList != null) {
-            for (Map.Entry<String, byte[]> entry : trustRootCertList.entrySet()) {
+        if (mTrustRootCertList != null) {
+            for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
                 String url = entry.getKey();
                 byte[] certFingerprint = entry.getValue();
                 if (TextUtils.isEmpty(url)) {
@@ -283,20 +382,20 @@
             @Override
             public PasspointConfiguration createFromParcel(Parcel in) {
                 PasspointConfiguration config = new PasspointConfiguration();
-                config.homeSp = in.readParcelable(null);
-                config.credential = in.readParcelable(null);
-                config.policy = in.readParcelable(null);
-                config.subscriptionUpdate = in.readParcelable(null);
-                config.trustRootCertList = readTrustRootCerts(in);
-                config.updateIdentifier = in.readInt();
-                config.credentialPriority = in.readInt();
-                config.subscriptionCreationTimeInMs = in.readLong();
-                config.subscriptionExpirationTimeInMs = in.readLong();
-                config.subscriptionType = in.readString();
-                config.usageLimitUsageTimePeriodInMinutes = in.readLong();
-                config.usageLimitStartTimeInMs = in.readLong();
-                config.usageLimitDataLimit = in.readLong();
-                config.usageLimitTimeLimitInMinutes = in.readLong();
+                config.setHomeSp(in.readParcelable(null));
+                config.setCredential(in.readParcelable(null));
+                config.setPolicy(in.readParcelable(null));
+                config.setSubscriptionUpdate(in.readParcelable(null));
+                config.setTrustRootCertList(readTrustRootCerts(in));
+                config.setUpdateIdentifier(in.readInt());
+                config.setCredentialPriority(in.readInt());
+                config.setSubscriptionCreationTimeInMs(in.readLong());
+                config.setSubscriptionExpirationTimeInMs(in.readLong());
+                config.setSubscriptionType(in.readString());
+                config.setUsageLimitUsageTimePeriodInMinutes(in.readLong());
+                config.setUsageLimitStartTimeInMs(in.readLong());
+                config.setUsageLimitDataLimit(in.readLong());
+                config.setUsageLimitTimeLimitInMinutes(in.readLong());
                 return config;
             }
 
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
index 22b0f97..24672d4 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
@@ -450,7 +450,7 @@
             }
         }
         if (config != null && updateIdentifier != Integer.MIN_VALUE) {
-            config.updateIdentifier = updateIdentifier;
+            config.setUpdateIdentifier(updateIdentifier);
         }
         return config;
     }
@@ -606,25 +606,25 @@
         for (PPSNode child : root.getChildren()) {
             switch(child.getName()) {
                 case NODE_HOMESP:
-                    config.homeSp = parseHomeSP(child);
+                    config.setHomeSp(parseHomeSP(child));
                     break;
                 case NODE_CREDENTIAL:
-                    config.credential = parseCredential(child);
+                    config.setCredential(parseCredential(child));
                     break;
                 case NODE_POLICY:
-                    config.policy = parsePolicy(child);
+                    config.setPolicy(parsePolicy(child));
                     break;
                 case NODE_AAA_SERVER_TRUST_ROOT:
-                    config.trustRootCertList = parseAAAServerTrustRootList(child);
+                    config.setTrustRootCertList(parseAAAServerTrustRootList(child));
                     break;
                 case NODE_SUBSCRIPTION_UPDATE:
-                    config.subscriptionUpdate = parseUpdateParameter(child);
+                    config.setSubscriptionUpdate(parseUpdateParameter(child));
                     break;
                 case NODE_SUBSCRIPTION_PARAMETER:
                     parseSubscriptionParameter(child, config);
                     break;
                 case NODE_CREDENTIAL_PRIORITY:
-                    config.credentialPriority = parseInteger(getPpsNodeValue(child));
+                    config.setCredentialPriority(parseInteger(getPpsNodeValue(child)));
                     break;
                 default:
                     throw new ParsingException("Unknown node: " + child.getName());
@@ -649,28 +649,28 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_FQDN:
-                    homeSp.fqdn = getPpsNodeValue(child);
+                    homeSp.setFqdn(getPpsNodeValue(child));
                     break;
                 case NODE_FRIENDLY_NAME:
-                    homeSp.friendlyName = getPpsNodeValue(child);
+                    homeSp.setFriendlyName(getPpsNodeValue(child));
                     break;
                 case NODE_ROAMING_CONSORTIUM_OI:
-                    homeSp.roamingConsortiumOIs =
-                            parseRoamingConsortiumOI(getPpsNodeValue(child));
+                    homeSp.setRoamingConsortiumOIs(
+                            parseRoamingConsortiumOI(getPpsNodeValue(child)));
                     break;
                 case NODE_ICON_URL:
-                    homeSp.iconUrl = getPpsNodeValue(child);
+                    homeSp.setIconUrl(getPpsNodeValue(child));
                     break;
                 case NODE_NETWORK_ID:
-                    homeSp.homeNetworkIds = parseNetworkIds(child);
+                    homeSp.setHomeNetworkIds(parseNetworkIds(child));
                     break;
                 case NODE_HOME_OI_LIST:
                     Pair<List<Long>, List<Long>> homeOIs = parseHomeOIList(child);
-                    homeSp.matchAllOIs = convertFromLongList(homeOIs.first);
-                    homeSp.matchAnyOIs = convertFromLongList(homeOIs.second);
+                    homeSp.setMatchAllOIs(convertFromLongList(homeOIs.first));
+                    homeSp.setMatchAnyOIs(convertFromLongList(homeOIs.second));
                     break;
                 case NODE_OTHER_HOME_PARTNERS:
-                    homeSp.otherHomePartners = parseOtherHomePartners(child);
+                    homeSp.setOtherHomePartners(parseOtherHomePartners(child));
                     break;
                 default:
                     throw new ParsingException("Unknown node under HomeSP: " + child.getName());
@@ -894,26 +894,26 @@
         for (PPSNode child: node.getChildren()) {
             switch (child.getName()) {
                 case NODE_CREATION_DATE:
-                    credential.creationTimeInMs = parseDate(getPpsNodeValue(child));
+                    credential.setCreationTimeInMs(parseDate(getPpsNodeValue(child)));
                     break;
                 case NODE_EXPIRATION_DATE:
-                    credential.expirationTimeInMs = parseDate(getPpsNodeValue(child));
+                    credential.setExpirationTimeInMs(parseDate(getPpsNodeValue(child)));
                     break;
                 case NODE_USERNAME_PASSWORD:
-                    credential.userCredential = parseUserCredential(child);
+                    credential.setUserCredential(parseUserCredential(child));
                     break;
                 case NODE_DIGITAL_CERTIFICATE:
-                    credential.certCredential = parseCertificateCredential(child);
+                    credential.setCertCredential(parseCertificateCredential(child));
                     break;
                 case NODE_REALM:
-                    credential.realm = getPpsNodeValue(child);
+                    credential.setRealm(getPpsNodeValue(child));
                     break;
                 case NODE_CHECK_AAA_SERVER_CERT_STATUS:
-                    credential.checkAAAServerCertStatus =
-                            Boolean.parseBoolean(getPpsNodeValue(child));
+                    credential.setCheckAAAServerCertStatus(
+                            Boolean.parseBoolean(getPpsNodeValue(child)));
                     break;
                 case NODE_SIM:
-                    credential.simCredential = parseSimCredential(child);
+                    credential.setSimCredential(parseSimCredential(child));
                     break;
                 default:
                     throw new ParsingException("Unknown node under Credential: " +
@@ -941,19 +941,19 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_USERNAME:
-                    userCred.username = getPpsNodeValue(child);
+                    userCred.setUsername(getPpsNodeValue(child));
                     break;
                 case NODE_PASSWORD:
-                    userCred.password = getPpsNodeValue(child);
+                    userCred.setPassword(getPpsNodeValue(child));
                     break;
                 case NODE_MACHINE_MANAGED:
-                    userCred.machineManaged = Boolean.parseBoolean(getPpsNodeValue(child));
+                    userCred.setMachineManaged(Boolean.parseBoolean(getPpsNodeValue(child)));
                     break;
                 case NODE_SOFT_TOKEN_APP:
-                    userCred.softTokenApp = getPpsNodeValue(child);
+                    userCred.setSoftTokenApp(getPpsNodeValue(child));
                     break;
                 case NODE_ABLE_TO_SHARE:
-                    userCred.ableToShare = Boolean.parseBoolean(getPpsNodeValue(child));
+                    userCred.setAbleToShare(Boolean.parseBoolean(getPpsNodeValue(child)));
                     break;
                 case NODE_EAP_METHOD:
                     parseEAPMethod(child, userCred);
@@ -984,10 +984,10 @@
         for (PPSNode child : node.getChildren()) {
             switch(child.getName()) {
                 case NODE_EAP_TYPE:
-                    userCred.eapType = parseInteger(getPpsNodeValue(child));
+                    userCred.setEapType(parseInteger(getPpsNodeValue(child)));
                     break;
                 case NODE_INNER_METHOD:
-                    userCred.nonEapInnerMethod = getPpsNodeValue(child);
+                    userCred.setNonEapInnerMethod(getPpsNodeValue(child));
                     break;
                 case NODE_VENDOR_ID:
                 case NODE_VENDOR_TYPE:
@@ -1022,10 +1022,10 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_CERTIFICATE_TYPE:
-                    certCred.certType = getPpsNodeValue(child);
+                    certCred.setCertType(getPpsNodeValue(child));
                     break;
                 case NODE_CERT_SHA256_FINGERPRINT:
-                    certCred.certSha256FingerPrint = parseHexString(getPpsNodeValue(child));
+                    certCred.setCertSha256Fingerprint(parseHexString(getPpsNodeValue(child)));
                     break;
                 default:
                     throw new ParsingException("Unknown node under DigitalCertificate: " +
@@ -1053,10 +1053,10 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_SIM_IMSI:
-                    simCred.imsi = getPpsNodeValue(child);
+                    simCred.setImsi(getPpsNodeValue(child));
                     break;
                 case NODE_EAP_TYPE:
-                    simCred.eapType = parseInteger(getPpsNodeValue(child));
+                    simCred.setEapType(parseInteger(getPpsNodeValue(child)));
                     break;
                 default:
                     throw new ParsingException("Unknown node under SIM: " + child.getName());
@@ -1081,22 +1081,22 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_PREFERRED_ROAMING_PARTNER_LIST:
-                    policy.preferredRoamingPartnerList = parsePreferredRoamingPartnerList(child);
+                    policy.setPreferredRoamingPartnerList(parsePreferredRoamingPartnerList(child));
                     break;
                 case NODE_MIN_BACKHAUL_THRESHOLD:
                     parseMinBackhaulThreshold(child, policy);
                     break;
                 case NODE_POLICY_UPDATE:
-                    policy.policyUpdate = parseUpdateParameter(child);
+                    policy.setPolicyUpdate(parseUpdateParameter(child));
                     break;
                 case NODE_SP_EXCLUSION_LIST:
-                    policy.excludedSsidList = parseSpExclusionList(child);
+                    policy.setExcludedSsidList(parseSpExclusionList(child));
                     break;
                 case NODE_REQUIRED_PROTO_PORT_TUPLE:
-                    policy.requiredProtoPortMap = parseRequiredProtoPortTuple(child);
+                    policy.setRequiredProtoPortMap(parseRequiredProtoPortTuple(child));
                     break;
                 case NODE_MAXIMUM_BSS_LOAD_VALUE:
-                    policy.maximumBssLoadValue = parseInteger(getPpsNodeValue(child));
+                    policy.setMaximumBssLoadValue(parseInteger(getPpsNodeValue(child)));
                     break;
                 default:
                     throw new ParsingException("Unknown node under Policy: " + child.getName());
@@ -1154,20 +1154,20 @@
                     if (fqdnMatchArray.length != 2) {
                         throw new ParsingException("Invalid FQDN_Match: " + fqdnMatch);
                     }
-                    roamingPartner.fqdn = fqdnMatchArray[0];
+                    roamingPartner.setFqdn(fqdnMatchArray[0]);
                     if (TextUtils.equals(fqdnMatchArray[1], "exactMatch")) {
-                        roamingPartner.fqdnExactMatch = true;
+                        roamingPartner.setFqdnExactMatch(true);
                     } else if (TextUtils.equals(fqdnMatchArray[1], "includeSubdomains")) {
-                        roamingPartner.fqdnExactMatch = false;
+                        roamingPartner.setFqdnExactMatch(false);
                     } else {
                         throw new ParsingException("Invalid FQDN_Match: " + fqdnMatch);
                     }
                     break;
                 case NODE_PRIORITY:
-                    roamingPartner.priority = parseInteger(getPpsNodeValue(child));
+                    roamingPartner.setPriority(parseInteger(getPpsNodeValue(child)));
                     break;
                 case NODE_COUNTRY:
-                    roamingPartner.countries = getPpsNodeValue(child);
+                    roamingPartner.setCountries(getPpsNodeValue(child));
                     break;
                 default:
                     throw new ParsingException("Unknown node under PreferredRoamingPartnerList "
@@ -1234,11 +1234,11 @@
         }
 
         if (TextUtils.equals(networkType, "home")) {
-            policy.minHomeDownlinkBandwidth = downlinkBandwidth;
-            policy.minHomeUplinkBandwidth = uplinkBandwidth;
+            policy.setMinHomeDownlinkBandwidth(downlinkBandwidth);
+            policy.setMinHomeUplinkBandwidth(uplinkBandwidth);
         } else if (TextUtils.equals(networkType, "roaming")) {
-            policy.minRoamingDownlinkBandwidth = downlinkBandwidth;
-            policy.minRoamingUplinkBandwidth = uplinkBandwidth;
+            policy.setMinRoamingDownlinkBandwidth(downlinkBandwidth);
+            policy.setMinRoamingUplinkBandwidth(uplinkBandwidth);
         } else {
             throw new ParsingException("Invalid network type: " + networkType);
         }
@@ -1264,26 +1264,26 @@
         for (PPSNode child : node.getChildren()) {
             switch(child.getName()) {
                 case NODE_UPDATE_INTERVAL:
-                    updateParam.updateIntervalInMinutes = parseLong(getPpsNodeValue(child), 10);
+                    updateParam.setUpdateIntervalInMinutes(parseLong(getPpsNodeValue(child), 10));
                     break;
                 case NODE_UPDATE_METHOD:
-                    updateParam.updateMethod = getPpsNodeValue(child);
+                    updateParam.setUpdateMethod(getPpsNodeValue(child));
                     break;
                 case NODE_RESTRICTION:
-                    updateParam.restriction = getPpsNodeValue(child);
+                    updateParam.setRestriction(getPpsNodeValue(child));
                     break;
                 case NODE_URI:
-                    updateParam.serverUri = getPpsNodeValue(child);
+                    updateParam.setServerUri(getPpsNodeValue(child));
                     break;
                 case NODE_USERNAME_PASSWORD:
                     Pair<String, String> usernamePassword = parseUpdateUserCredential(child);
-                    updateParam.username = usernamePassword.first;
-                    updateParam.base64EncodedPassword = usernamePassword.second;
+                    updateParam.setUsername(usernamePassword.first);
+                    updateParam.setBase64EncodedPassword(usernamePassword.second);
                     break;
                 case NODE_TRUST_ROOT:
                     Pair<String, byte[]> trustRoot = parseTrustRoot(child);
-                    updateParam.trustRootCertUrl = trustRoot.first;
-                    updateParam.trustRootCertSha256Fingerprint = trustRoot.second;
+                    updateParam.setTrustRootCertUrl(trustRoot.first);
+                    updateParam.setTrustRootCertSha256Fingerprint(trustRoot.second);
                     break;
                 case NODE_OTHER:
                     Log.d(TAG, "Ignore unsupported paramter: " + child.getName());
@@ -1508,13 +1508,13 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_CREATION_DATE:
-                    config.subscriptionCreationTimeInMs = parseDate(getPpsNodeValue(child));
+                    config.setSubscriptionCreationTimeInMs(parseDate(getPpsNodeValue(child)));
                     break;
                 case NODE_EXPIRATION_DATE:
-                    config.subscriptionExpirationTimeInMs = parseDate(getPpsNodeValue(child));
+                    config.setSubscriptionExpirationTimeInMs(parseDate(getPpsNodeValue(child)));
                     break;
                 case NODE_TYPE_OF_SUBSCRIPTION:
-                    config.subscriptionType = getPpsNodeValue(child);
+                    config.setSubscriptionType(getPpsNodeValue(child));
                     break;
                 case NODE_USAGE_LIMITS:
                     parseUsageLimits(child, config);
@@ -1543,17 +1543,17 @@
         for (PPSNode child : node.getChildren()) {
             switch (child.getName()) {
                 case NODE_DATA_LIMIT:
-                    config.usageLimitDataLimit = parseLong(getPpsNodeValue(child), 10);
+                    config.setUsageLimitDataLimit(parseLong(getPpsNodeValue(child), 10));
                     break;
                 case NODE_START_DATE:
-                    config.usageLimitStartTimeInMs = parseDate(getPpsNodeValue(child));
+                    config.setUsageLimitStartTimeInMs(parseDate(getPpsNodeValue(child)));
                     break;
                 case NODE_TIME_LIMIT:
-                    config.usageLimitTimeLimitInMinutes = parseLong(getPpsNodeValue(child), 10);
+                    config.setUsageLimitTimeLimitInMinutes(parseLong(getPpsNodeValue(child), 10));
                     break;
                 case NODE_USAGE_TIME_PERIOD:
-                    config.usageLimitUsageTimePeriodInMinutes =
-                            parseLong(getPpsNodeValue(child), 10);
+                    config.setUsageLimitUsageTimePeriodInMinutes(
+                            parseLong(getPpsNodeValue(child), 10));
                     break;
                 default:
                     throw new ParsingException("Unknown node under UsageLimits"
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/XMLNode.java b/wifi/java/android/net/wifi/hotspot2/omadm/XMLNode.java
index e87698c..959d505 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/XMLNode.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/XMLNode.java
@@ -20,6 +20,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * A class represent a node in an XML tree. Each node is an XML element.
@@ -100,4 +101,9 @@
                 TextUtils.equals(mText, that.mText) &&
                 mChildren.equals(that.mChildren);
     }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mTag, mText, mChildren);
+    }
 }
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 3374f42d..ff93486 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -31,6 +31,7 @@
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -58,28 +59,52 @@
      * of milliseconds since January 1, 1970, 00:00:00 GMT.
      * Using Long.MIN_VALUE to indicate unset value.
      */
-    public long creationTimeInMs = Long.MIN_VALUE;
+    private long mCreationTimeInMs = Long.MIN_VALUE;
+    public void setCreationTimeInMs(long creationTimeInMs) {
+        mCreationTimeInMs = creationTimeInMs;
+    }
+    public long getCreationTimeInMs() {
+        return mCreationTimeInMs;
+    }
 
     /**
      * The time this credential will expire. It is in the format of number
      * of milliseconds since January 1, 1970, 00:00:00 GMT.
     * Using Long.MIN_VALUE to indicate unset value.
      */
-    public long expirationTimeInMs = Long.MIN_VALUE;
+    private long mExpirationTimeInMs = Long.MIN_VALUE;
+    public void setExpirationTimeInMs(long expirationTimeInMs) {
+        mExpirationTimeInMs = expirationTimeInMs;
+    }
+    public long getExpirationTimeInMs() {
+        return mExpirationTimeInMs;
+    }
 
     /**
      * The realm associated with this credential.  It will be used to determine
      * if this credential can be used to authenticate with a given hotspot by
      * comparing the realm specified in that hotspot's ANQP element.
      */
-    public String realm = null;
+    private String mRealm = null;
+    public void setRealm(String realm) {
+        mRealm = realm;
+    }
+    public String getRealm() {
+        return mRealm;
+    }
 
     /**
      * When set to true, the device should check AAA (Authentication, Authorization,
      * and Accounting) server's certificate during EAP (Extensible Authentication
      * Protocol) authentication.
      */
-    public boolean checkAAAServerCertStatus = false;
+    private boolean mCheckAAAServerCertStatus = false;
+    public void setCheckAAAServerCertStatus(boolean checkAAAServerCertStatus) {
+        mCheckAAAServerCertStatus = checkAAAServerCertStatus;
+    }
+    public boolean getCheckAAAServerStatus() {
+        return mCheckAAAServerCertStatus;
+    }
 
     /**
      * Username-password based credential.
@@ -109,27 +134,57 @@
         /**
          * Username of the credential.
          */
-        public String username = null;
+        private String mUsername = null;
+        public void setUsername(String username) {
+            mUsername = username;
+        }
+        public String getUsername() {
+            return mUsername;
+        }
 
         /**
          * Base64-encoded password.
          */
-        public String password = null;
+        private String mPassword = null;
+        public void setPassword(String password) {
+            mPassword = password;
+        }
+        public String getPassword() {
+            return mPassword;
+        }
 
         /**
          * Flag indicating if the password is machine managed.
          */
-        public boolean machineManaged = false;
+        private boolean mMachineManaged = false;
+        public void setMachineManaged(boolean machineManaged) {
+            mMachineManaged = machineManaged;
+        }
+        public boolean getMachineManaged() {
+            return mMachineManaged;
+        }
 
         /**
          * The name of the application used to generate the password.
          */
-        public String softTokenApp = null;
+        private String mSoftTokenApp = null;
+        public void setSoftTokenApp(String softTokenApp) {
+            mSoftTokenApp = softTokenApp;
+        }
+        public String getSoftTokenApp() {
+            return mSoftTokenApp;
+        }
 
         /**
          * Flag indicating if this credential is usable on other mobile devices as well.
          */
-        public boolean ableToShare = false;
+        private boolean mAbleToShare = false;
+        public void setAbleToShare(boolean ableToShare) {
+            mAbleToShare = ableToShare;
+        }
+        public boolean getAbleToShare() {
+            return mAbleToShare;
+        }
 
         /**
          * EAP (Extensible Authentication Protocol) method type.
@@ -137,12 +192,24 @@
          * for valid values.
          * Using Integer.MIN_VALUE to indicate unset value.
          */
-        public int eapType = Integer.MIN_VALUE;
+        private int mEapType = Integer.MIN_VALUE;
+        public void setEapType(int eapType) {
+            mEapType = eapType;
+        }
+        public int getEapType() {
+            return mEapType;
+        }
 
         /**
          * Non-EAP inner authentication method.
          */
-        public String nonEapInnerMethod = null;
+        private String mNonEapInnerMethod = null;
+        public void setNonEapInnerMethod(String nonEapInnerMethod) {
+            mNonEapInnerMethod = nonEapInnerMethod;
+        }
+        public String getNonEapInnerMethod() {
+            return mNonEapInnerMethod;
+        }
 
         /**
          * Constructor for creating UserCredential with default values.
@@ -156,13 +223,13 @@
          */
         public UserCredential(UserCredential source) {
             if (source != null) {
-                username = source.username;
-                password = source.password;
-                machineManaged = source.machineManaged;
-                softTokenApp = source.softTokenApp;
-                ableToShare = source.ableToShare;
-                eapType = source.eapType;
-                nonEapInnerMethod = source.nonEapInnerMethod;
+                mUsername = source.mUsername;
+                mPassword = source.mPassword;
+                mMachineManaged = source.mMachineManaged;
+                mSoftTokenApp = source.mSoftTokenApp;
+                mAbleToShare = source.mAbleToShare;
+                mEapType = source.mEapType;
+                mNonEapInnerMethod = source.mNonEapInnerMethod;
             }
         }
 
@@ -173,13 +240,13 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(username);
-            dest.writeString(password);
-            dest.writeInt(machineManaged ? 1 : 0);
-            dest.writeString(softTokenApp);
-            dest.writeInt(ableToShare ? 1 : 0);
-            dest.writeInt(eapType);
-            dest.writeString(nonEapInnerMethod);
+            dest.writeString(mUsername);
+            dest.writeString(mPassword);
+            dest.writeInt(mMachineManaged ? 1 : 0);
+            dest.writeString(mSoftTokenApp);
+            dest.writeInt(mAbleToShare ? 1 : 0);
+            dest.writeInt(mEapType);
+            dest.writeString(mNonEapInnerMethod);
         }
 
         @Override
@@ -192,13 +259,19 @@
             }
 
             UserCredential that = (UserCredential) thatObject;
-            return TextUtils.equals(username, that.username)
-                    && TextUtils.equals(password, that.password)
-                    && machineManaged == that.machineManaged
-                    && TextUtils.equals(softTokenApp, that.softTokenApp)
-                    && ableToShare == that.ableToShare
-                    && eapType == that.eapType
-                    && TextUtils.equals(nonEapInnerMethod, that.nonEapInnerMethod);
+            return TextUtils.equals(mUsername, that.mUsername)
+                    && TextUtils.equals(mPassword, that.mPassword)
+                    && mMachineManaged == that.mMachineManaged
+                    && TextUtils.equals(mSoftTokenApp, that.mSoftTokenApp)
+                    && mAbleToShare == that.mAbleToShare
+                    && mEapType == that.mEapType
+                    && TextUtils.equals(mNonEapInnerMethod, that.mNonEapInnerMethod);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mUsername, mPassword, mMachineManaged, mSoftTokenApp,
+                    mAbleToShare, mEapType, mNonEapInnerMethod);
         }
 
         /**
@@ -207,35 +280,35 @@
          * @return true on success or false on failure
          */
         public boolean validate() {
-            if (TextUtils.isEmpty(username)) {
+            if (TextUtils.isEmpty(mUsername)) {
                 Log.d(TAG, "Missing username");
                 return false;
             }
-            if (username.getBytes(StandardCharsets.UTF_8).length > MAX_USERNAME_BYTES) {
+            if (mUsername.getBytes(StandardCharsets.UTF_8).length > MAX_USERNAME_BYTES) {
                 Log.d(TAG, "username exceeding maximum length: "
-                        + username.getBytes(StandardCharsets.UTF_8).length);
+                        + mUsername.getBytes(StandardCharsets.UTF_8).length);
                 return false;
             }
 
-            if (TextUtils.isEmpty(password)) {
+            if (TextUtils.isEmpty(mPassword)) {
                 Log.d(TAG, "Missing password");
                 return false;
             }
-            if (password.getBytes(StandardCharsets.UTF_8).length > MAX_PASSWORD_BYTES) {
+            if (mPassword.getBytes(StandardCharsets.UTF_8).length > MAX_PASSWORD_BYTES) {
                 Log.d(TAG, "password exceeding maximum length: "
-                        + password.getBytes(StandardCharsets.UTF_8).length);
+                        + mPassword.getBytes(StandardCharsets.UTF_8).length);
                 return false;
             }
 
             // Only supports EAP-TTLS for user credential.
-            if (eapType != EAPConstants.EAP_TTLS) {
-                Log.d(TAG, "Invalid EAP Type for user credential: " + eapType);
+            if (mEapType != EAPConstants.EAP_TTLS) {
+                Log.d(TAG, "Invalid EAP Type for user credential: " + mEapType);
                 return false;
             }
 
             // Verify Non-EAP inner method for EAP-TTLS.
-            if (!SUPPORTED_AUTH.contains(nonEapInnerMethod)) {
-                Log.d(TAG, "Invalid non-EAP inner method for EAP-TTLS: " + nonEapInnerMethod);
+            if (!SUPPORTED_AUTH.contains(mNonEapInnerMethod)) {
+                Log.d(TAG, "Invalid non-EAP inner method for EAP-TTLS: " + mNonEapInnerMethod);
                 return false;
             }
             return true;
@@ -246,13 +319,13 @@
                 @Override
                 public UserCredential createFromParcel(Parcel in) {
                     UserCredential userCredential = new UserCredential();
-                    userCredential.username = in.readString();
-                    userCredential.password = in.readString();
-                    userCredential.machineManaged = in.readInt() != 0;
-                    userCredential.softTokenApp = in.readString();
-                    userCredential.ableToShare = in.readInt() != 0;
-                    userCredential.eapType = in.readInt();
-                    userCredential.nonEapInnerMethod = in.readString();
+                    userCredential.setUsername(in.readString());
+                    userCredential.setPassword(in.readString());
+                    userCredential.setMachineManaged(in.readInt() != 0);
+                    userCredential.setSoftTokenApp(in.readString());
+                    userCredential.setAbleToShare(in.readInt() != 0);
+                    userCredential.setEapType(in.readInt());
+                    userCredential.setNonEapInnerMethod(in.readString());
                     return userCredential;
                 }
 
@@ -262,7 +335,13 @@
                 }
             };
     }
-    public UserCredential userCredential = null;
+    private UserCredential mUserCredential = null;
+    public void setUserCredential(UserCredential userCredential) {
+        mUserCredential = userCredential;
+    }
+    public UserCredential getUserCredential() {
+        return mUserCredential;
+    }
 
     /**
      * Certificate based credential.  This is used for EAP-TLS.
@@ -282,12 +361,24 @@
         /**
          * Certificate type.
          */
-        public String certType = null;
+        private String mCertType = null;
+        public void setCertType(String certType) {
+            mCertType = certType;
+        }
+        public String getCertType() {
+            return mCertType;
+        }
 
         /**
          * The SHA-256 fingerprint of the certificate.
          */
-        public byte[] certSha256FingerPrint = null;
+        private byte[] mCertSha256Fingerprint = null;
+        public void setCertSha256Fingerprint(byte[] certSha256Fingerprint) {
+            mCertSha256Fingerprint = certSha256Fingerprint;
+        }
+        public byte[] getCertSha256Fingerprint() {
+            return mCertSha256Fingerprint;
+        }
 
         /**
          * Constructor for creating CertificateCredential with default values.
@@ -301,10 +392,10 @@
          */
         public CertificateCredential(CertificateCredential source) {
             if (source != null) {
-                certType = source.certType;
-                if (source.certSha256FingerPrint != null) {
-                    certSha256FingerPrint = Arrays.copyOf(source.certSha256FingerPrint,
-                                                          source.certSha256FingerPrint.length);
+                mCertType = source.mCertType;
+                if (source.mCertSha256Fingerprint != null) {
+                    mCertSha256Fingerprint = Arrays.copyOf(source.mCertSha256Fingerprint,
+                                                          source.mCertSha256Fingerprint.length);
                 }
             }
         }
@@ -316,8 +407,8 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(certType);
-            dest.writeByteArray(certSha256FingerPrint);
+            dest.writeString(mCertType);
+            dest.writeByteArray(mCertSha256Fingerprint);
         }
 
         @Override
@@ -330,8 +421,13 @@
             }
 
             CertificateCredential that = (CertificateCredential) thatObject;
-            return TextUtils.equals(certType, that.certType)
-                    && Arrays.equals(certSha256FingerPrint, that.certSha256FingerPrint);
+            return TextUtils.equals(mCertType, that.mCertType)
+                    && Arrays.equals(mCertSha256Fingerprint, that.mCertSha256Fingerprint);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mCertType, mCertSha256Fingerprint);
         }
 
         /**
@@ -340,12 +436,12 @@
          * @return true on success or false on failure
          */
         public boolean validate() {
-            if (!TextUtils.equals(CERT_TYPE_X509V3, certType)) {
-                Log.d(TAG, "Unsupported certificate type: " + certType);
+            if (!TextUtils.equals(CERT_TYPE_X509V3, mCertType)) {
+                Log.d(TAG, "Unsupported certificate type: " + mCertType);
                 return false;
             }
-            if (certSha256FingerPrint == null
-                    || certSha256FingerPrint.length != CERT_SHA256_FINGER_PRINT_LENGTH) {
+            if (mCertSha256Fingerprint == null
+                    || mCertSha256Fingerprint.length != CERT_SHA256_FINGER_PRINT_LENGTH) {
                 Log.d(TAG, "Invalid SHA-256 fingerprint");
                 return false;
             }
@@ -357,8 +453,8 @@
                 @Override
                 public CertificateCredential createFromParcel(Parcel in) {
                     CertificateCredential certCredential = new CertificateCredential();
-                    certCredential.certType = in.readString();
-                    certCredential.certSha256FingerPrint = in.createByteArray();
+                    certCredential.setCertType(in.readString());
+                    certCredential.setCertSha256Fingerprint(in.createByteArray());
                     return certCredential;
                 }
 
@@ -368,7 +464,13 @@
                 }
             };
     }
-    public CertificateCredential certCredential = null;
+    private CertificateCredential mCertCredential = null;
+    public void setCertCredential(CertificateCredential certCredential) {
+        mCertCredential = certCredential;
+    }
+    public CertificateCredential getCertCredential() {
+        return mCertCredential;
+    }
 
     /**
      * SIM (Subscriber Identify Module) based credential.
@@ -378,14 +480,20 @@
         /**
          * Maximum string length for IMSI.
          */
-        public static final int MAX_IMSI_LENGTH = 15;
+        private static final int MAX_IMSI_LENGTH = 15;
 
         /**
          * International Mobile Subscriber Identity, is used to identify the user
          * of a cellular network and is a unique identification associated with all
          * cellular networks
          */
-        public String imsi = null;
+        private String mImsi = null;
+        public void setImsi(String imsi) {
+            mImsi = imsi;
+        }
+        public String getImsi() {
+            return mImsi;
+        }
 
         /**
          * EAP (Extensible Authentication Protocol) method type for using SIM credential.
@@ -393,7 +501,13 @@
          * for valid values.
          * Using Integer.MIN_VALUE to indicate unset value.
          */
-        public int eapType = Integer.MIN_VALUE;
+        private int mEapType = Integer.MIN_VALUE;
+        public void setEapType(int eapType) {
+            mEapType = eapType;
+        }
+        public int getEapType() {
+            return mEapType;
+        }
 
         /**
          * Constructor for creating SimCredential with default values.
@@ -407,8 +521,8 @@
          */
         public SimCredential(SimCredential source) {
             if (source != null) {
-                imsi = source.imsi;
-                eapType = source.eapType;
+                mImsi = source.mImsi;
+                mEapType = source.mEapType;
             }
         }
 
@@ -427,14 +541,19 @@
             }
 
             SimCredential that = (SimCredential) thatObject;
-            return TextUtils.equals(imsi, that.imsi)
-                    && eapType == that.eapType;
+            return TextUtils.equals(mImsi, that.mImsi)
+                    && mEapType == that.mEapType;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mImsi, mEapType);
         }
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(imsi);
-            dest.writeInt(eapType);
+            dest.writeString(mImsi);
+            dest.writeInt(mEapType);
         }
 
         /**
@@ -449,9 +568,9 @@
             if (!verifyImsi()) {
                 return false;
             }
-            if (eapType != EAPConstants.EAP_SIM && eapType != EAPConstants.EAP_AKA
-                    && eapType != EAPConstants.EAP_AKA_PRIME) {
-                Log.d(TAG, "Invalid EAP Type for SIM credential: " + eapType);
+            if (mEapType != EAPConstants.EAP_SIM && mEapType != EAPConstants.EAP_AKA
+                    && mEapType != EAPConstants.EAP_AKA_PRIME) {
+                Log.d(TAG, "Invalid EAP Type for SIM credential: " + mEapType);
                 return false;
             }
             return true;
@@ -462,8 +581,8 @@
                 @Override
                 public SimCredential createFromParcel(Parcel in) {
                     SimCredential simCredential = new SimCredential();
-                    simCredential.imsi = in.readString();
-                    simCredential.eapType = in.readInt();
+                    simCredential.setImsi(in.readString());
+                    simCredential.setEapType(in.readInt());
                     return simCredential;
                 }
 
@@ -481,51 +600,75 @@
          * @return true if IMSI is valid, false otherwise.
          */
         private boolean verifyImsi() {
-            if (TextUtils.isEmpty(imsi)) {
+            if (TextUtils.isEmpty(mImsi)) {
                 Log.d(TAG, "Missing IMSI");
                 return false;
             }
-            if (imsi.length() > MAX_IMSI_LENGTH) {
-                Log.d(TAG, "IMSI exceeding maximum length: " + imsi.length());
+            if (mImsi.length() > MAX_IMSI_LENGTH) {
+                Log.d(TAG, "IMSI exceeding maximum length: " + mImsi.length());
                 return false;
             }
 
             // Locate the first non-digit character.
             int nonDigit;
             char stopChar = '\0';
-            for (nonDigit = 0; nonDigit < imsi.length(); nonDigit++) {
-                stopChar = imsi.charAt(nonDigit);
+            for (nonDigit = 0; nonDigit < mImsi.length(); nonDigit++) {
+                stopChar = mImsi.charAt(nonDigit);
                 if (stopChar < '0' || stopChar > '9') {
                     break;
                 }
             }
 
-            if (nonDigit == imsi.length()) {
+            if (nonDigit == mImsi.length()) {
                 return true;
             }
-            else if (nonDigit == imsi.length()-1 && stopChar == '*') {
+            else if (nonDigit == mImsi.length()-1 && stopChar == '*') {
                 // Prefix matching.
                 return true;
             }
             return false;
         }
     }
-    public SimCredential simCredential = null;
+    private SimCredential mSimCredential = null;
+    public void setSimCredential(SimCredential simCredential) {
+        mSimCredential = simCredential;
+    }
+    public SimCredential getSimCredential() {
+        return mSimCredential;
+    }
 
     /**
      * CA (Certificate Authority) X509 certificate.
      */
-    public X509Certificate caCertificate = null;
+    private X509Certificate mCaCertificate = null;
+    public void setCaCertificate(X509Certificate caCertificate) {
+        mCaCertificate = caCertificate;
+    }
+    public X509Certificate getCaCertificate() {
+        return mCaCertificate;
+    }
 
     /**
      * Client side X509 certificate chain.
      */
-    public X509Certificate[] clientCertificateChain = null;
+    private X509Certificate[] mClientCertificateChain = null;
+    public void setClientCertificateChain(X509Certificate[] certificateChain) {
+        mClientCertificateChain = certificateChain;
+    }
+    public X509Certificate[] getClientCertificateChain() {
+        return mClientCertificateChain;
+    }
 
     /**
      * Client side private key.
      */
-    public PrivateKey clientPrivateKey = null;
+    private PrivateKey mClientPrivateKey = null;
+    public void setClientPrivateKey(PrivateKey clientPrivateKey) {
+        mClientPrivateKey = clientPrivateKey;
+    }
+    public PrivateKey getClientPrivateKey() {
+        return mClientPrivateKey;
+    }
 
     /**
      * Constructor for creating Credential with default values.
@@ -539,25 +682,25 @@
      */
     public Credential(Credential source) {
         if (source != null) {
-            creationTimeInMs = source.creationTimeInMs;
-            expirationTimeInMs = source.expirationTimeInMs;
-            realm = source.realm;
-            checkAAAServerCertStatus = source.checkAAAServerCertStatus;
-            if (source.userCredential != null) {
-                userCredential = new UserCredential(source.userCredential);
+            mCreationTimeInMs = source.mCreationTimeInMs;
+            mExpirationTimeInMs = source.mExpirationTimeInMs;
+            mRealm = source.mRealm;
+            mCheckAAAServerCertStatus = source.mCheckAAAServerCertStatus;
+            if (source.mUserCredential != null) {
+                mUserCredential = new UserCredential(source.mUserCredential);
             }
-            if (source.certCredential != null) {
-                certCredential = new CertificateCredential(source.certCredential);
+            if (source.mCertCredential != null) {
+                mCertCredential = new CertificateCredential(source.mCertCredential);
             }
-            if (source.simCredential != null) {
-                simCredential = new SimCredential(source.simCredential);
+            if (source.mSimCredential != null) {
+                mSimCredential = new SimCredential(source.mSimCredential);
             }
-            if (source.clientCertificateChain != null) {
-                clientCertificateChain = Arrays.copyOf(source.clientCertificateChain,
-                                                       source.clientCertificateChain.length);
+            if (source.mClientCertificateChain != null) {
+                mClientCertificateChain = Arrays.copyOf(source.mClientCertificateChain,
+                                                        source.mClientCertificateChain.length);
             }
-            caCertificate = source.caCertificate;
-            clientPrivateKey = source.clientPrivateKey;
+            mCaCertificate = source.mCaCertificate;
+            mClientPrivateKey = source.mClientPrivateKey;
         }
     }
 
@@ -568,16 +711,16 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(creationTimeInMs);
-        dest.writeLong(expirationTimeInMs);
-        dest.writeString(realm);
-        dest.writeInt(checkAAAServerCertStatus ? 1 : 0);
-        dest.writeParcelable(userCredential, flags);
-        dest.writeParcelable(certCredential, flags);
-        dest.writeParcelable(simCredential, flags);
-        ParcelUtil.writeCertificate(dest, caCertificate);
-        ParcelUtil.writeCertificates(dest, clientCertificateChain);
-        ParcelUtil.writePrivateKey(dest, clientPrivateKey);
+        dest.writeLong(mCreationTimeInMs);
+        dest.writeLong(mExpirationTimeInMs);
+        dest.writeString(mRealm);
+        dest.writeInt(mCheckAAAServerCertStatus ? 1 : 0);
+        dest.writeParcelable(mUserCredential, flags);
+        dest.writeParcelable(mCertCredential, flags);
+        dest.writeParcelable(mSimCredential, flags);
+        ParcelUtil.writeCertificate(dest, mCaCertificate);
+        ParcelUtil.writeCertificates(dest, mClientCertificateChain);
+        ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
     }
 
     @Override
@@ -590,19 +733,26 @@
         }
 
         Credential that = (Credential) thatObject;
-        return TextUtils.equals(realm, that.realm)
-                && creationTimeInMs == that.creationTimeInMs
-                && expirationTimeInMs == that.expirationTimeInMs
-                && checkAAAServerCertStatus == that.checkAAAServerCertStatus
-                && (userCredential == null ? that.userCredential == null
-                    : userCredential.equals(that.userCredential))
-                && (certCredential == null ? that.certCredential == null
-                    : certCredential.equals(that.certCredential))
-                && (simCredential == null ? that.simCredential == null
-                    : simCredential.equals(that.simCredential))
-                && isX509CertificateEquals(caCertificate, that.caCertificate)
-                && isX509CertificatesEquals(clientCertificateChain, that.clientCertificateChain)
-                && isPrivateKeyEquals(clientPrivateKey, that.clientPrivateKey);
+        return TextUtils.equals(mRealm, that.mRealm)
+                && mCreationTimeInMs == that.mCreationTimeInMs
+                && mExpirationTimeInMs == that.mExpirationTimeInMs
+                && mCheckAAAServerCertStatus == that.mCheckAAAServerCertStatus
+                && (mUserCredential == null ? that.mUserCredential == null
+                    : mUserCredential.equals(that.mUserCredential))
+                && (mCertCredential == null ? that.mCertCredential == null
+                    : mCertCredential.equals(that.mCertCredential))
+                && (mSimCredential == null ? that.mSimCredential == null
+                    : mSimCredential.equals(that.mSimCredential))
+                && isX509CertificateEquals(mCaCertificate, that.mCaCertificate)
+                && isX509CertificatesEquals(mClientCertificateChain, that.mClientCertificateChain)
+                && isPrivateKeyEquals(mClientPrivateKey, that.mClientPrivateKey);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mRealm, mCreationTimeInMs, mExpirationTimeInMs,
+                mCheckAAAServerCertStatus, mUserCredential, mCertCredential, mSimCredential,
+                mCaCertificate, mClientCertificateChain, mClientPrivateKey);
     }
 
     /**
@@ -611,26 +761,26 @@
      * @return true on success or false on failure
      */
     public boolean validate() {
-        if (TextUtils.isEmpty(realm)) {
+        if (TextUtils.isEmpty(mRealm)) {
             Log.d(TAG, "Missing realm");
             return false;
         }
-        if (realm.getBytes(StandardCharsets.UTF_8).length > MAX_REALM_BYTES) {
+        if (mRealm.getBytes(StandardCharsets.UTF_8).length > MAX_REALM_BYTES) {
             Log.d(TAG, "realm exceeding maximum length: "
-                    + realm.getBytes(StandardCharsets.UTF_8).length);
+                    + mRealm.getBytes(StandardCharsets.UTF_8).length);
             return false;
         }
 
         // Verify the credential.
-        if (userCredential != null) {
+        if (mUserCredential != null) {
             if (!verifyUserCredential()) {
                 return false;
             }
-        } else if (certCredential != null) {
+        } else if (mCertCredential != null) {
             if (!verifyCertCredential()) {
                 return false;
             }
-        } else if (simCredential != null) {
+        } else if (mSimCredential != null) {
             if (!verifySimCredential()) {
                 return false;
             }
@@ -647,16 +797,16 @@
             @Override
             public Credential createFromParcel(Parcel in) {
                 Credential credential = new Credential();
-                credential.creationTimeInMs = in.readLong();
-                credential.expirationTimeInMs = in.readLong();
-                credential.realm = in.readString();
-                credential.checkAAAServerCertStatus = in.readInt() != 0;
-                credential.userCredential = in.readParcelable(null);
-                credential.certCredential = in.readParcelable(null);
-                credential.simCredential = in.readParcelable(null);
-                credential.caCertificate = ParcelUtil.readCertificate(in);
-                credential.clientCertificateChain = ParcelUtil.readCertificates(in);
-                credential.clientPrivateKey = ParcelUtil.readPrivateKey(in);
+                credential.setCreationTimeInMs(in.readLong());
+                credential.setExpirationTimeInMs(in.readLong());
+                credential.setRealm(in.readString());
+                credential.setCheckAAAServerCertStatus(in.readInt() != 0);
+                credential.setUserCredential(in.readParcelable(null));
+                credential.setCertCredential(in.readParcelable(null));
+                credential.setSimCredential(in.readParcelable(null));
+                credential.setCaCertificate(ParcelUtil.readCertificate(in));
+                credential.setClientCertificateChain(ParcelUtil.readCertificates(in));
+                credential.setClientPrivateKey(ParcelUtil.readPrivateKey(in));
                 return credential;
             }
 
@@ -672,18 +822,18 @@
      * @return true if user credential is valid, false otherwise.
      */
     private boolean verifyUserCredential() {
-        if (userCredential == null) {
+        if (mUserCredential == null) {
             Log.d(TAG, "Missing user credential");
             return false;
         }
-        if (certCredential != null || simCredential != null) {
+        if (mCertCredential != null || mSimCredential != null) {
             Log.d(TAG, "Contained more than one type of credential");
             return false;
         }
-        if (!userCredential.validate()) {
+        if (!mUserCredential.validate()) {
             return false;
         }
-        if (caCertificate == null) {
+        if (mCaCertificate == null) {
             Log.d(TAG, "Missing CA Certificate for user credential");
             return false;
         }
@@ -697,32 +847,32 @@
      * @return true if certificate credential is valid, false otherwise.
      */
     private boolean verifyCertCredential() {
-        if (certCredential == null) {
+        if (mCertCredential == null) {
             Log.d(TAG, "Missing certificate credential");
             return false;
         }
-        if (userCredential != null || simCredential != null) {
+        if (mUserCredential != null || mSimCredential != null) {
             Log.d(TAG, "Contained more than one type of credential");
             return false;
         }
 
-        if (!certCredential.validate()) {
+        if (!mCertCredential.validate()) {
             return false;
         }
 
         // Verify required key and certificates for certificate credential.
-        if (caCertificate == null) {
+        if (mCaCertificate == null) {
             Log.d(TAG, "Missing CA Certificate for certificate credential");
             return false;
         }
-        if (clientPrivateKey == null) {
+        if (mClientPrivateKey == null) {
             Log.d(TAG, "Missing client private key for certificate credential");
             return false;
         }
         try {
             // Verify SHA-256 fingerprint for client certificate.
-            if (!verifySha256Fingerprint(clientCertificateChain,
-                    certCredential.certSha256FingerPrint)) {
+            if (!verifySha256Fingerprint(mClientCertificateChain,
+                    mCertCredential.getCertSha256Fingerprint())) {
                 Log.d(TAG, "SHA-256 fingerprint mismatch");
                 return false;
             }
@@ -740,15 +890,15 @@
      * @return true if SIM credential is valid, false otherwise.
      */
     private boolean verifySimCredential() {
-        if (simCredential == null) {
+        if (mSimCredential == null) {
             Log.d(TAG, "Missing SIM credential");
             return false;
         }
-        if (userCredential != null || certCredential != null) {
+        if (mUserCredential != null || mCertCredential != null) {
             Log.d(TAG, "Contained more than one type of credential");
             return false;
         }
-        return simCredential.validate();
+        return mSimCredential.validate();
     }
 
     private static boolean isPrivateKeyEquals(PrivateKey key1, PrivateKey key2) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
index 4ddf210..8b3b79c 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
@@ -26,6 +26,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Class representing HomeSP subtree in PerProviderSubscription (PPS)
@@ -52,17 +53,35 @@
     /**
      * FQDN (Fully Qualified Domain Name) of this home service provider.
      */
-    public String fqdn = null;
+    private String mFqdn = null;
+    public void setFqdn(String fqdn) {
+        mFqdn = fqdn;
+    }
+    public String getFqdn() {
+        return mFqdn;
+    }
 
     /**
      * Friendly name of this home service provider.
      */
-    public String friendlyName = null;
+    private String mFriendlyName = null;
+    public void setFriendlyName(String friendlyName) {
+        mFriendlyName = friendlyName;
+    }
+    public String getFriendlyName() {
+        return mFriendlyName;
+    }
 
     /**
      * Icon URL of this home service provider.
      */
-    public String iconUrl = null;
+    private String mIconUrl = null;
+    public void setIconUrl(String iconUrl) {
+        mIconUrl = iconUrl;
+    }
+    public String getIconUrl() {
+        return mIconUrl;
+    }
 
     /**
      * <SSID, HESSID> duple of the networks that are consider home networks.
@@ -71,7 +90,13 @@
      * all nodes in the PSS MO are encoded using UTF-8 unless stated otherwise.  Thus, the SSID
      * string is assumed to be encoded using UTF-8.
      */
-    public Map<String, Long> homeNetworkIds = null;
+    private Map<String, Long> mHomeNetworkIds = null;
+    public void setHomeNetworkIds(Map<String, Long> homeNetworkIds) {
+        mHomeNetworkIds = homeNetworkIds;
+    }
+    public Map<String, Long> getHomeNetworkIds() {
+        return mHomeNetworkIds;
+    }
 
     /**
      * Used for determining if this provider is a member of a given Hotspot provider.
@@ -83,7 +108,13 @@
      * Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object
      * (MO) tree for more detail.
      */
-    public long[] matchAllOIs = null;
+    private long[] mMatchAllOIs = null;
+    public void setMatchAllOIs(long[] matchAllOIs) {
+        mMatchAllOIs = matchAllOIs;
+    }
+    public long[] getMatchAllOIs() {
+        return mMatchAllOIs;
+    }
 
     /**
      * Used for determining if this provider is a member of a given Hotspot provider.
@@ -92,13 +123,19 @@
      * of that Hotspot provider (e.g. successful authentication with such Hotspot
      * is possible).
      *
-     * {@link #matchAllOIs} will have precedence over this one, meaning this list will
-     * only be used for matching if {@link #matchAllOIs} is null or empty.
+     * {@link #mMatchAllOIs} will have precedence over this one, meaning this list will
+     * only be used for matching if {@link #mMatchAllOIs} is null or empty.
      *
      * Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object
      * (MO) tree for more detail.
      */
-    public long[] matchAnyOIs = null;
+    private long[] mMatchAnyOIs = null;
+    public void setMatchAnyOIs(long[] matchAnyOIs) {
+        mMatchAnyOIs = matchAnyOIs;
+    }
+    public long[] getMatchAnysOIs() {
+        return mMatchAnyOIs;
+    }
 
     /**
      * List of FQDN (Fully Qualified Domain Name) of partner providers.
@@ -106,13 +143,25 @@
      * This relationship is most likely achieved via a commercial agreement or
      * operator merges between the providers.
      */
-    public String[] otherHomePartners = null;
+    private String[] mOtherHomePartners = null;
+    public void setOtherHomePartners(String[] otherHomePartners) {
+        mOtherHomePartners = otherHomePartners;
+    }
+    public String[] getOtherHomePartners() {
+        return mOtherHomePartners;
+    }
 
     /**
      * List of Organization Identifiers (OIs) identifying a roaming consortium of
      * which this provider is a member.
      */
-    public long[] roamingConsortiumOIs = null;
+    private long[] mRoamingConsortiumOIs = null;
+    public void setRoamingConsortiumOIs(long[] roamingConsortiumOIs) {
+        mRoamingConsortiumOIs = roamingConsortiumOIs;
+    }
+    public long[] getRoamingConsortiumOIs() {
+        return mRoamingConsortiumOIs;
+    }
 
     /**
      * Constructor for creating HomeSP with default values.
@@ -128,25 +177,25 @@
         if (source == null) {
             return;
         }
-        fqdn = source.fqdn;
-        friendlyName = source.friendlyName;
-        iconUrl = source.iconUrl;
-        if (source.homeNetworkIds != null) {
-            homeNetworkIds = Collections.unmodifiableMap(source.homeNetworkIds);
+        mFqdn = source.mFqdn;
+        mFriendlyName = source.mFriendlyName;
+        mIconUrl = source.mIconUrl;
+        if (source.mHomeNetworkIds != null) {
+            mHomeNetworkIds = Collections.unmodifiableMap(source.mHomeNetworkIds);
         }
-        if (source.matchAllOIs != null) {
-            matchAllOIs = Arrays.copyOf(source.matchAllOIs, source.matchAllOIs.length);
+        if (source.mMatchAllOIs != null) {
+            mMatchAllOIs = Arrays.copyOf(source.mMatchAllOIs, source.mMatchAllOIs.length);
         }
-        if (source.matchAnyOIs != null) {
-            matchAnyOIs = Arrays.copyOf(source.matchAnyOIs, source.matchAnyOIs.length);
+        if (source.mMatchAnyOIs != null) {
+            mMatchAnyOIs = Arrays.copyOf(source.mMatchAnyOIs, source.mMatchAnyOIs.length);
         }
-        if (source.otherHomePartners != null) {
-            otherHomePartners = Arrays.copyOf(source.otherHomePartners,
-                    source.otherHomePartners.length);
+        if (source.mOtherHomePartners != null) {
+            mOtherHomePartners = Arrays.copyOf(source.mOtherHomePartners,
+                    source.mOtherHomePartners.length);
         }
-        if (source.roamingConsortiumOIs != null) {
-            roamingConsortiumOIs = Arrays.copyOf(source.roamingConsortiumOIs,
-                    source.roamingConsortiumOIs.length);
+        if (source.mRoamingConsortiumOIs != null) {
+            mRoamingConsortiumOIs = Arrays.copyOf(source.mRoamingConsortiumOIs,
+                    source.mRoamingConsortiumOIs.length);
         }
     }
 
@@ -157,14 +206,14 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(fqdn);
-        dest.writeString(friendlyName);
-        dest.writeString(iconUrl);
-        writeHomeNetworkIds(dest, homeNetworkIds);
-        dest.writeLongArray(matchAllOIs);
-        dest.writeLongArray(matchAnyOIs);
-        dest.writeStringArray(otherHomePartners);
-        dest.writeLongArray(roamingConsortiumOIs);
+        dest.writeString(mFqdn);
+        dest.writeString(mFriendlyName);
+        dest.writeString(mIconUrl);
+        writeHomeNetworkIds(dest, mHomeNetworkIds);
+        dest.writeLongArray(mMatchAllOIs);
+        dest.writeLongArray(mMatchAnyOIs);
+        dest.writeStringArray(mOtherHomePartners);
+        dest.writeLongArray(mRoamingConsortiumOIs);
     }
 
     @Override
@@ -177,15 +226,21 @@
         }
         HomeSP that = (HomeSP) thatObject;
 
-        return TextUtils.equals(fqdn, that.fqdn)
-                && TextUtils.equals(friendlyName, that.friendlyName)
-                && TextUtils.equals(iconUrl, that.iconUrl)
-                && (homeNetworkIds == null ? that.homeNetworkIds == null
-                        : homeNetworkIds.equals(that.homeNetworkIds))
-                && Arrays.equals(matchAllOIs, that.matchAllOIs)
-                && Arrays.equals(matchAnyOIs, that.matchAnyOIs)
-                && Arrays.equals(otherHomePartners, that.otherHomePartners)
-                && Arrays.equals(roamingConsortiumOIs, that.roamingConsortiumOIs);
+        return TextUtils.equals(mFqdn, that.mFqdn)
+                && TextUtils.equals(mFriendlyName, that.mFriendlyName)
+                && TextUtils.equals(mIconUrl, that.mIconUrl)
+                && (mHomeNetworkIds == null ? that.mHomeNetworkIds == null
+                        : mHomeNetworkIds.equals(that.mHomeNetworkIds))
+                && Arrays.equals(mMatchAllOIs, that.mMatchAllOIs)
+                && Arrays.equals(mMatchAnyOIs, that.mMatchAnyOIs)
+                && Arrays.equals(mOtherHomePartners, that.mOtherHomePartners)
+                && Arrays.equals(mRoamingConsortiumOIs, that.mRoamingConsortiumOIs);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mFqdn, mFriendlyName, mIconUrl, mHomeNetworkIds, mMatchAllOIs,
+                mMatchAnyOIs, mOtherHomePartners, mRoamingConsortiumOIs);
     }
 
     /**
@@ -194,17 +249,17 @@
      * @return true on success or false on failure
      */
     public boolean validate() {
-        if (TextUtils.isEmpty(fqdn)) {
+        if (TextUtils.isEmpty(mFqdn)) {
             Log.d(TAG, "Missing FQDN");
             return false;
         }
-        if (TextUtils.isEmpty(friendlyName)) {
+        if (TextUtils.isEmpty(mFriendlyName)) {
             Log.d(TAG, "Missing friendly name");
             return false;
         }
         // Verify SSIDs specified in the NetworkID
-        if (homeNetworkIds != null) {
-            for (Map.Entry<String, Long> entry : homeNetworkIds.entrySet()) {
+        if (mHomeNetworkIds != null) {
+            for (Map.Entry<String, Long> entry : mHomeNetworkIds.entrySet()) {
                 if (entry.getKey() == null ||
                         entry.getKey().getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
                     Log.d(TAG, "Invalid SSID in HomeNetworkIDs");
@@ -220,14 +275,14 @@
             @Override
             public HomeSP createFromParcel(Parcel in) {
                 HomeSP homeSp = new HomeSP();
-                homeSp.fqdn = in.readString();
-                homeSp.friendlyName = in.readString();
-                homeSp.iconUrl = in.readString();
-                homeSp.homeNetworkIds = readHomeNetworkIds(in);
-                homeSp.matchAllOIs = in.createLongArray();
-                homeSp.matchAnyOIs = in.createLongArray();
-                homeSp.otherHomePartners = in.createStringArray();
-                homeSp.roamingConsortiumOIs = in.createLongArray();
+                homeSp.setFqdn(in.readString());
+                homeSp.setFriendlyName(in.readString());
+                homeSp.setIconUrl(in.readString());
+                homeSp.setHomeNetworkIds(readHomeNetworkIds(in));
+                homeSp.setMatchAllOIs(in.createLongArray());
+                homeSp.setMatchAnyOIs(in.createLongArray());
+                homeSp.setOtherHomePartners(in.createStringArray());
+                homeSp.setRoamingConsortiumOIs(in.createLongArray());
                 return homeSp;
             }
 
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index bc29402..ceaada4 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -28,6 +28,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Class representing Policy subtree in PerProviderSubscription (PPS)
@@ -79,8 +80,20 @@
      *
      * Using Long.MIN_VALUE to indicate unset value.
      */
-    public long minHomeDownlinkBandwidth = Long.MIN_VALUE;
-    public long minHomeUplinkBandwidth = Long.MIN_VALUE;
+    private long mMinHomeDownlinkBandwidth = Long.MIN_VALUE;
+    public void setMinHomeDownlinkBandwidth(long minHomeDownlinkBandwidth) {
+        mMinHomeDownlinkBandwidth = minHomeDownlinkBandwidth;
+    }
+    public long getMinHomeDownlinkBandWidht() {
+        return mMinHomeDownlinkBandwidth;
+    }
+    private long mMinHomeUplinkBandwidth = Long.MIN_VALUE;
+    public void setMinHomeUplinkBandwidth(long minHomeUplinkBandwidth) {
+        mMinHomeUplinkBandwidth = minHomeUplinkBandwidth;
+    }
+    public long getMinHomeUplinkBandwidth() {
+        return mMinHomeUplinkBandwidth;
+    }
 
     /**
      * Minimum available downlink/uplink bandwidth (in kilobits per second) required when
@@ -91,26 +104,56 @@
      *
      * Using Long.MIN_VALUE to indicate unset value.
      */
-    public long minRoamingDownlinkBandwidth = Long.MIN_VALUE;
-    public long minRoamingUplinkBandwidth = Long.MIN_VALUE;
+    private long mMinRoamingDownlinkBandwidth = Long.MIN_VALUE;
+    public void setMinRoamingDownlinkBandwidth(long minRoamingDownlinkBandwidth) {
+        mMinRoamingDownlinkBandwidth = minRoamingDownlinkBandwidth;
+    }
+    public long getMinRoamingDownlinkBandwidth() {
+        return mMinRoamingDownlinkBandwidth;
+    }
+    private long mMinRoamingUplinkBandwidth = Long.MIN_VALUE;
+    public void setMinRoamingUplinkBandwidth(long minRoamingUplinkBandwidth) {
+        mMinRoamingUplinkBandwidth = minRoamingUplinkBandwidth;
+    }
+    public long getMinRoamingUplinkBandwidth() {
+        return mMinRoamingUplinkBandwidth;
+    }
 
     /**
      * List of SSIDs that are not preferred by the Home SP.
      */
-    public String[] excludedSsidList = null;
+    private String[] mExcludedSsidList = null;
+    public void setExcludedSsidList(String[] excludedSsidList) {
+        mExcludedSsidList = excludedSsidList;
+    }
+    public String[] getExcludedSsidList() {
+        return mExcludedSsidList;
+    }
 
     /**
      * List of IP protocol and port number required by one or more operator supported application.
      * The port string contained one or more port numbers delimited by ",".
      */
-    public Map<Integer, String> requiredProtoPortMap = null;
+    private Map<Integer, String> mRequiredProtoPortMap = null;
+    public void setRequiredProtoPortMap(Map<Integer, String> requiredProtoPortMap) {
+        mRequiredProtoPortMap = requiredProtoPortMap;
+    }
+    public Map<Integer, String> getRequiredProtoPortMap() {
+        return mRequiredProtoPortMap;
+    }
 
     /**
      * This specifies the maximum acceptable BSS load policy.  This is used to prevent device
      * from joining an AP whose channel is overly congested with traffic.
      * Using Integer.MIN_VALUE to indicate unset value.
      */
-    public int maximumBssLoadValue = Integer.MIN_VALUE;
+    private int mMaximumBssLoadValue = Integer.MIN_VALUE;
+    public void setMaximumBssLoadValue(int maximumBssLoadValue) {
+        mMaximumBssLoadValue = maximumBssLoadValue;
+    }
+    public int getMaximumBssLoadValue() {
+        return mMaximumBssLoadValue;
+    }
 
     /**
      * Policy associated with a roaming provider.  This specifies a priority associated
@@ -122,7 +165,13 @@
         /**
          * FQDN of the roaming partner.
          */
-        public String fqdn = null;
+        private String mFqdn = null;
+        public void setFqdn(String fqdn) {
+            mFqdn = fqdn;
+        }
+        public String getFqdn() {
+            return mFqdn;
+        }
 
         /**
          * Flag indicating the exact match of FQDN is required for FQDN matching.
@@ -130,27 +179,45 @@
          * When this flag is set to false, sub-domain matching is used.  For example, when
          * {@link #fqdn} s set to "example.com", "host.example.com" would be a match.
          */
-        public boolean fqdnExactMatch = false;
+        private boolean mFqdnExactMatch = false;
+        public void setFqdnExactMatch(boolean fqdnExactMatch) {
+            mFqdnExactMatch = fqdnExactMatch;
+        }
+        public boolean getFqdnExactMatch() {
+            return mFqdnExactMatch;
+        }
 
         /**
          * Priority associated with this roaming partner policy.
          */
-        public int priority = PREFERRED_ROAMING_PARTNER_DEFAULT_PRIORITY;
+        private int mPriority = PREFERRED_ROAMING_PARTNER_DEFAULT_PRIORITY;
+        public void setPriority(int priority) {
+            mPriority = priority;
+        }
+        public int getPriority() {
+            return mPriority;
+        }
 
         /**
          * A string contained One or more, comma delimited (i.e., ",") ISO/IEC 3166-1 two
          * character country strings or the country-independent value, "*".
          */
-        public String countries = null;
+        private String mCountries = null;
+        public void setCountries(String countries) {
+            mCountries = countries;
+        }
+        public String getCountries() {
+            return mCountries;
+        }
 
         public RoamingPartner() {}
 
         public RoamingPartner(RoamingPartner source) {
             if (source != null) {
-                fqdn = source.fqdn;
-                fqdnExactMatch = source.fqdnExactMatch;
-                priority = source.priority;
-                countries = source.countries;
+                mFqdn = source.mFqdn;
+                mFqdnExactMatch = source.mFqdnExactMatch;
+                mPriority = source.mPriority;
+                mCountries = source.mCountries;
             }
         }
 
@@ -161,10 +228,10 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(fqdn);
-            dest.writeInt(fqdnExactMatch ? 1 : 0);
-            dest.writeInt(priority);
-            dest.writeString(countries);
+            dest.writeString(mFqdn);
+            dest.writeInt(mFqdnExactMatch ? 1 : 0);
+            dest.writeInt(mPriority);
+            dest.writeString(mCountries);
         }
 
         @Override
@@ -177,10 +244,15 @@
             }
 
             RoamingPartner that = (RoamingPartner) thatObject;
-            return TextUtils.equals(fqdn, that.fqdn)
-                    && fqdnExactMatch == that.fqdnExactMatch
-                    && priority == that.priority
-                    && TextUtils.equals(countries, that.countries);
+            return TextUtils.equals(mFqdn, that.mFqdn)
+                    && mFqdnExactMatch == that.mFqdnExactMatch
+                    && mPriority == that.mPriority
+                    && TextUtils.equals(mCountries, that.mCountries);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mFqdn, mFqdnExactMatch, mPriority, mCountries);
         }
 
         /**
@@ -189,11 +261,11 @@
          * @return true on success
          */
         public boolean validate() {
-            if (TextUtils.isEmpty(fqdn)) {
+            if (TextUtils.isEmpty(mFqdn)) {
                 Log.d(TAG, "Missing FQDN");
                 return false;
             }
-            if (TextUtils.isEmpty(countries)) {
+            if (TextUtils.isEmpty(mCountries)) {
                 Log.d(TAG, "Missing countries");
                 return false;
             }
@@ -205,10 +277,10 @@
                 @Override
                 public RoamingPartner createFromParcel(Parcel in) {
                     RoamingPartner roamingPartner = new RoamingPartner();
-                    roamingPartner.fqdn = in.readString();
-                    roamingPartner.fqdnExactMatch = in.readInt() != 0;
-                    roamingPartner.priority = in.readInt();
-                    roamingPartner.countries = in.readString();
+                    roamingPartner.setFqdn(in.readString());
+                    roamingPartner.setFqdnExactMatch(in.readInt() != 0);
+                    roamingPartner.setPriority(in.readInt());
+                    roamingPartner.setCountries(in.readString());
                     return roamingPartner;
                 }
 
@@ -218,12 +290,24 @@
                 }
             };
     }
-    public List<RoamingPartner> preferredRoamingPartnerList = null;
+    private List<RoamingPartner> mPreferredRoamingPartnerList = null;
+    public void setPreferredRoamingPartnerList(List<RoamingPartner> partnerList) {
+        mPreferredRoamingPartnerList = partnerList;
+    }
+    public List<RoamingPartner> getPreferredRoamingPartnerList() {
+        return mPreferredRoamingPartnerList;
+    }
 
     /**
      * Meta data used for policy update.
      */
-    public UpdateParameter policyUpdate = null;
+    private UpdateParameter mPolicyUpdate = null;
+    public void setPolicyUpdate(UpdateParameter policyUpdate) {
+        mPolicyUpdate = policyUpdate;
+    }
+    public UpdateParameter getPolicyUpdate() {
+        return mPolicyUpdate;
+    }
 
     /**
      * Constructor for creating Policy with default values.
@@ -239,24 +323,24 @@
         if (source == null) {
             return;
         }
-        minHomeDownlinkBandwidth = source.minHomeDownlinkBandwidth;
-        minHomeUplinkBandwidth = source.minHomeUplinkBandwidth;
-        minRoamingDownlinkBandwidth = source.minRoamingDownlinkBandwidth;
-        minRoamingUplinkBandwidth = source.minRoamingUplinkBandwidth;
-        maximumBssLoadValue = source.maximumBssLoadValue;
-        if (source.excludedSsidList != null) {
-            excludedSsidList = Arrays.copyOf(source.excludedSsidList,
-                    source.excludedSsidList.length);
+        mMinHomeDownlinkBandwidth = source.mMinHomeDownlinkBandwidth;
+        mMinHomeUplinkBandwidth = source.mMinHomeUplinkBandwidth;
+        mMinRoamingDownlinkBandwidth = source.mMinRoamingDownlinkBandwidth;
+        mMinRoamingUplinkBandwidth = source.mMinRoamingUplinkBandwidth;
+        mMaximumBssLoadValue = source.mMaximumBssLoadValue;
+        if (source.mExcludedSsidList != null) {
+            mExcludedSsidList = Arrays.copyOf(source.mExcludedSsidList,
+                    source.mExcludedSsidList.length);
         }
-        if (source.requiredProtoPortMap != null) {
-            requiredProtoPortMap = Collections.unmodifiableMap(source.requiredProtoPortMap);
+        if (source.mRequiredProtoPortMap != null) {
+            mRequiredProtoPortMap = Collections.unmodifiableMap(source.mRequiredProtoPortMap);
         }
-        if (source.preferredRoamingPartnerList != null) {
-            preferredRoamingPartnerList = Collections.unmodifiableList(
-                    source.preferredRoamingPartnerList);
+        if (source.mPreferredRoamingPartnerList != null) {
+            mPreferredRoamingPartnerList = Collections.unmodifiableList(
+                    source.mPreferredRoamingPartnerList);
         }
-        if (source.policyUpdate != null) {
-            policyUpdate = new UpdateParameter(source.policyUpdate);
+        if (source.mPolicyUpdate != null) {
+            mPolicyUpdate = new UpdateParameter(source.mPolicyUpdate);
         }
     }
 
@@ -267,15 +351,15 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(minHomeDownlinkBandwidth);
-        dest.writeLong(minHomeUplinkBandwidth);
-        dest.writeLong(minRoamingDownlinkBandwidth);
-        dest.writeLong(minRoamingUplinkBandwidth);
-        dest.writeStringArray(excludedSsidList);
-        writeProtoPortMap(dest, requiredProtoPortMap);
-        dest.writeInt(maximumBssLoadValue);
-        writeRoamingPartnerList(dest, flags, preferredRoamingPartnerList);
-        dest.writeParcelable(policyUpdate, flags);
+        dest.writeLong(mMinHomeDownlinkBandwidth);
+        dest.writeLong(mMinHomeUplinkBandwidth);
+        dest.writeLong(mMinRoamingDownlinkBandwidth);
+        dest.writeLong(mMinRoamingUplinkBandwidth);
+        dest.writeStringArray(mExcludedSsidList);
+        writeProtoPortMap(dest, mRequiredProtoPortMap);
+        dest.writeInt(mMaximumBssLoadValue);
+        writeRoamingPartnerList(dest, flags, mPreferredRoamingPartnerList);
+        dest.writeParcelable(mPolicyUpdate, flags);
     }
 
     @Override
@@ -288,18 +372,27 @@
         }
         Policy that = (Policy) thatObject;
 
-        return minHomeDownlinkBandwidth == that.minHomeDownlinkBandwidth
-                && minHomeUplinkBandwidth == that.minHomeUplinkBandwidth
-                && minRoamingDownlinkBandwidth == that.minRoamingDownlinkBandwidth
-                && minRoamingUplinkBandwidth == that.minRoamingUplinkBandwidth
-                && Arrays.equals(excludedSsidList, that.excludedSsidList)
-                && (requiredProtoPortMap == null ? that.requiredProtoPortMap == null
-                        : requiredProtoPortMap.equals(that.requiredProtoPortMap))
-                && maximumBssLoadValue == that.maximumBssLoadValue
-                && (preferredRoamingPartnerList == null ? that.preferredRoamingPartnerList == null
-                        : preferredRoamingPartnerList.equals(that.preferredRoamingPartnerList))
-                && (policyUpdate == null ? that.policyUpdate == null
-                        : policyUpdate.equals(that.policyUpdate));
+        return mMinHomeDownlinkBandwidth == that.mMinHomeDownlinkBandwidth
+                && mMinHomeUplinkBandwidth == that.mMinHomeUplinkBandwidth
+                && mMinRoamingDownlinkBandwidth == that.mMinRoamingDownlinkBandwidth
+                && mMinRoamingUplinkBandwidth == that.mMinRoamingUplinkBandwidth
+                && Arrays.equals(mExcludedSsidList, that.mExcludedSsidList)
+                && (mRequiredProtoPortMap == null ? that.mRequiredProtoPortMap == null
+                        : mRequiredProtoPortMap.equals(that.mRequiredProtoPortMap))
+                && mMaximumBssLoadValue == that.mMaximumBssLoadValue
+                && (mPreferredRoamingPartnerList == null
+                        ? that.mPreferredRoamingPartnerList == null
+                        : mPreferredRoamingPartnerList.equals(that.mPreferredRoamingPartnerList))
+                && (mPolicyUpdate == null ? that.mPolicyUpdate == null
+                        : mPolicyUpdate.equals(that.mPolicyUpdate));
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mMinHomeDownlinkBandwidth, mMinHomeUplinkBandwidth,
+                mMinRoamingDownlinkBandwidth, mMinRoamingUplinkBandwidth, mExcludedSsidList,
+                mRequiredProtoPortMap, mMaximumBssLoadValue, mPreferredRoamingPartnerList,
+                mPolicyUpdate);
     }
 
     /**
@@ -308,22 +401,22 @@
      * @return true on success
      */
     public boolean validate() {
-        if (policyUpdate == null) {
+        if (mPolicyUpdate == null) {
             Log.d(TAG, "PolicyUpdate not specified");
             return false;
         }
-        if (!policyUpdate.validate()) {
+        if (!mPolicyUpdate.validate()) {
             return false;
         }
 
         // Validate SSID exclusion list.
-        if (excludedSsidList != null) {
-            if (excludedSsidList.length > MAX_EXCLUSION_SSIDS) {
+        if (mExcludedSsidList != null) {
+            if (mExcludedSsidList.length > MAX_EXCLUSION_SSIDS) {
                 Log.d(TAG, "SSID exclusion list size exceeded the max: "
-                        + excludedSsidList.length);
+                        + mExcludedSsidList.length);
                 return false;
             }
-            for (String ssid : excludedSsidList) {
+            for (String ssid : mExcludedSsidList) {
                 if (ssid.getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
                     Log.d(TAG, "Invalid SSID: " + ssid);
                     return false;
@@ -331,8 +424,8 @@
             }
         }
         // Validate required protocol to port map.
-        if (requiredProtoPortMap != null) {
-            for (Map.Entry<Integer, String> entry : requiredProtoPortMap.entrySet()) {
+        if (mRequiredProtoPortMap != null) {
+            for (Map.Entry<Integer, String> entry : mRequiredProtoPortMap.entrySet()) {
                 String portNumber = entry.getValue();
                 if (portNumber.getBytes(StandardCharsets.UTF_8).length > MAX_PORT_STRING_BYTES) {
                     Log.d(TAG, "PortNumber string bytes exceeded the max: " + portNumber);
@@ -341,8 +434,8 @@
             }
         }
         // Validate preferred roaming partner list.
-        if (preferredRoamingPartnerList != null) {
-            for (RoamingPartner partner : preferredRoamingPartnerList) {
+        if (mPreferredRoamingPartnerList != null) {
+            for (RoamingPartner partner : mPreferredRoamingPartnerList) {
                 if (!partner.validate()) {
                     return false;
                 }
@@ -356,15 +449,15 @@
             @Override
             public Policy createFromParcel(Parcel in) {
                 Policy policy = new Policy();
-                policy.minHomeDownlinkBandwidth = in.readLong();
-                policy.minHomeUplinkBandwidth = in.readLong();
-                policy.minRoamingDownlinkBandwidth = in.readLong();
-                policy.minRoamingUplinkBandwidth = in.readLong();
-                policy.excludedSsidList = in.createStringArray();
-                policy.requiredProtoPortMap = readProtoPortMap(in);
-                policy.maximumBssLoadValue = in.readInt();
-                policy.preferredRoamingPartnerList = readRoamingPartnerList(in);
-                policy.policyUpdate = in.readParcelable(null);
+                policy.setMinHomeDownlinkBandwidth(in.readLong());
+                policy.setMinHomeUplinkBandwidth(in.readLong());
+                policy.setMinRoamingDownlinkBandwidth(in.readLong());
+                policy.setMinRoamingUplinkBandwidth(in.readLong());
+                policy.setExcludedSsidList(in.createStringArray());
+                policy.setRequiredProtoPortMap(readProtoPortMap(in));
+                policy.setMaximumBssLoadValue(in.readInt());
+                policy.setPreferredRoamingPartnerList(readRoamingPartnerList(in));
+                policy.setPolicyUpdate(in.readParcelable(null));
                 return policy;
             }
 
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
index a390df7..17fbf9f 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
@@ -24,6 +24,7 @@
 
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Class representing configuration parameters for subscription or policy update in
@@ -88,45 +89,93 @@
      *
      * Using Long.MIN_VALUE to indicate unset value.
      */
-    public long updateIntervalInMinutes = Long.MIN_VALUE;
+    private long mUpdateIntervalInMinutes = Long.MIN_VALUE;
+    public void setUpdateIntervalInMinutes(long updateIntervalInMinutes) {
+        mUpdateIntervalInMinutes = updateIntervalInMinutes;
+    }
+    public long getUpdateIntervalInMinutes() {
+        return mUpdateIntervalInMinutes;
+    }
 
     /**
      * The method used to update the policy.  Permitted values are "OMA-DM-ClientInitiated"
      * and "SPP-ClientInitiated".
      */
-    public String updateMethod = null;
+    private String mUpdateMethod = null;
+    public void setUpdateMethod(String updateMethod) {
+        mUpdateMethod = updateMethod;
+    }
+    public String getUpdateMethod() {
+        return mUpdateMethod;
+    }
 
     /**
      * This specifies the hotspots at which the subscription update is permitted.  Permitted
      * values are "HomeSP", "RoamingPartner", or "Unrestricted";
      */
-    public String restriction = null;
+    private String mRestriction = null;
+    public void setRestriction(String restriction) {
+        mRestriction = restriction;
+    }
+    public String getRestriction() {
+        return mRestriction;
+    }
 
     /**
      * The URI of the update server.
      */
-    public String serverUri = null;
+    private String mServerUri = null;
+    public void setServerUri(String serverUri) {
+        mServerUri = serverUri;
+    }
+    public String getServerUri() {
+        return mServerUri;
+    }
 
     /**
      * Username used to authenticate with the policy server.
      */
-    public String username = null;
+    private String mUsername = null;
+    public void setUsername(String username) {
+        mUsername = username;
+    }
+    public String getUsername() {
+        return mUsername;
+    }
 
     /**
      * Base64 encoded password used to authenticate with the policy server.
      */
-    public String base64EncodedPassword = null;
+    private String mBase64EncodedPassword = null;
+    public void setBase64EncodedPassword(String password) {
+        mBase64EncodedPassword = password;
+    }
+    public String getBase64EncodedPassword() {
+        return mBase64EncodedPassword;
+    }
 
     /**
      * HTTPS URL for retrieving certificate for trust root.  The trust root is used to validate
      * policy server's identity.
      */
-    public String trustRootCertUrl = null;
+    private String mTrustRootCertUrl = null;
+    public void setTrustRootCertUrl(String trustRootCertUrl) {
+        mTrustRootCertUrl = trustRootCertUrl;
+    }
+    public String getTrustRootCertUrl() {
+        return mTrustRootCertUrl;
+    }
 
     /**
      * SHA-256 fingerprint of the certificate located at {@link #trustRootCertUrl}
      */
-    public byte[] trustRootCertSha256Fingerprint = null;
+    private byte[] mTrustRootCertSha256Fingerprint = null;
+    public void setTrustRootCertSha256Fingerprint(byte[] fingerprint) {
+        mTrustRootCertSha256Fingerprint = fingerprint;
+    }
+    public byte[] getTrustRootCertSha256Fingerprint() {
+        return mTrustRootCertSha256Fingerprint;
+    }
 
     /**
      * Constructor for creating Policy with default values.
@@ -142,16 +191,16 @@
         if (source == null) {
             return;
         }
-        updateIntervalInMinutes = source.updateIntervalInMinutes;
-        updateMethod = source.updateMethod;
-        restriction = source.restriction;
-        serverUri = source.serverUri;
-        username = source.username;
-        base64EncodedPassword = source.base64EncodedPassword;
-        trustRootCertUrl = source.trustRootCertUrl;
-        if (source.trustRootCertSha256Fingerprint != null) {
-            trustRootCertSha256Fingerprint = Arrays.copyOf(source.trustRootCertSha256Fingerprint,
-                    source.trustRootCertSha256Fingerprint.length);
+        mUpdateIntervalInMinutes = source.mUpdateIntervalInMinutes;
+        mUpdateMethod = source.mUpdateMethod;
+        mRestriction = source.mRestriction;
+        mServerUri = source.mServerUri;
+        mUsername = source.mUsername;
+        mBase64EncodedPassword = source.mBase64EncodedPassword;
+        mTrustRootCertUrl = source.mTrustRootCertUrl;
+        if (source.mTrustRootCertSha256Fingerprint != null) {
+            mTrustRootCertSha256Fingerprint = Arrays.copyOf(source.mTrustRootCertSha256Fingerprint,
+                    source.mTrustRootCertSha256Fingerprint.length);
         }
     }
 
@@ -162,14 +211,14 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(updateIntervalInMinutes);
-        dest.writeString(updateMethod);
-        dest.writeString(restriction);
-        dest.writeString(serverUri);
-        dest.writeString(username);
-        dest.writeString(base64EncodedPassword);
-        dest.writeString(trustRootCertUrl);
-        dest.writeByteArray(trustRootCertSha256Fingerprint);
+        dest.writeLong(mUpdateIntervalInMinutes);
+        dest.writeString(mUpdateMethod);
+        dest.writeString(mRestriction);
+        dest.writeString(mServerUri);
+        dest.writeString(mUsername);
+        dest.writeString(mBase64EncodedPassword);
+        dest.writeString(mTrustRootCertUrl);
+        dest.writeByteArray(mTrustRootCertSha256Fingerprint);
     }
 
     @Override
@@ -182,15 +231,22 @@
         }
         UpdateParameter that = (UpdateParameter) thatObject;
 
-        return updateIntervalInMinutes == that.updateIntervalInMinutes
-                && TextUtils.equals(updateMethod, that.updateMethod)
-                && TextUtils.equals(restriction, that.restriction)
-                && TextUtils.equals(serverUri, that.serverUri)
-                && TextUtils.equals(username, that.username)
-                && TextUtils.equals(base64EncodedPassword, that.base64EncodedPassword)
-                && TextUtils.equals(trustRootCertUrl, that.trustRootCertUrl)
-                && Arrays.equals(trustRootCertSha256Fingerprint,
-                        that.trustRootCertSha256Fingerprint);
+        return mUpdateIntervalInMinutes == that.mUpdateIntervalInMinutes
+                && TextUtils.equals(mUpdateMethod, that.mUpdateMethod)
+                && TextUtils.equals(mRestriction, that.mRestriction)
+                && TextUtils.equals(mServerUri, that.mServerUri)
+                && TextUtils.equals(mUsername, that.mUsername)
+                && TextUtils.equals(mBase64EncodedPassword, that.mBase64EncodedPassword)
+                && TextUtils.equals(mTrustRootCertUrl, that.mTrustRootCertUrl)
+                && Arrays.equals(mTrustRootCertSha256Fingerprint,
+                        that.mTrustRootCertSha256Fingerprint);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mUpdateIntervalInMinutes, mUpdateMethod, mRestriction, mServerUri,
+                mUsername, mBase64EncodedPassword, mTrustRootCertUrl,
+                mTrustRootCertSha256Fingerprint);
     }
 
     /**
@@ -199,81 +255,81 @@
      * @return true on success
      */
     public boolean validate() {
-        if (updateIntervalInMinutes == Long.MIN_VALUE) {
+        if (mUpdateIntervalInMinutes == Long.MIN_VALUE) {
             Log.d(TAG, "Update interval not specified");
             return false;
         }
         // Update not applicable.
-        if (updateIntervalInMinutes == UPDATE_CHECK_INTERVAL_NEVER) {
+        if (mUpdateIntervalInMinutes == UPDATE_CHECK_INTERVAL_NEVER) {
             return true;
         }
 
-        if (!TextUtils.equals(updateMethod, UPDATE_METHOD_OMADM)
-                && !TextUtils.equals(updateMethod, UPDATE_METHOD_SSP)) {
-            Log.d(TAG, "Unknown update method: " + updateMethod);
+        if (!TextUtils.equals(mUpdateMethod, UPDATE_METHOD_OMADM)
+                && !TextUtils.equals(mUpdateMethod, UPDATE_METHOD_SSP)) {
+            Log.d(TAG, "Unknown update method: " + mUpdateMethod);
             return false;
         }
 
-        if (!TextUtils.equals(restriction, UPDATE_RESTRICTION_HOMESP)
-                && !TextUtils.equals(restriction, UPDATE_RESTRICTION_ROAMING_PARTNER)
-                && !TextUtils.equals(restriction, UPDATE_RESTRICTION_UNRESTRICTED)) {
-            Log.d(TAG, "Unknown restriction: " + restriction);
+        if (!TextUtils.equals(mRestriction, UPDATE_RESTRICTION_HOMESP)
+                && !TextUtils.equals(mRestriction, UPDATE_RESTRICTION_ROAMING_PARTNER)
+                && !TextUtils.equals(mRestriction, UPDATE_RESTRICTION_UNRESTRICTED)) {
+            Log.d(TAG, "Unknown restriction: " + mRestriction);
             return false;
         }
 
-        if (TextUtils.isEmpty(serverUri)) {
+        if (TextUtils.isEmpty(mServerUri)) {
             Log.d(TAG, "Missing update server URI");
             return false;
         }
-        if (serverUri.getBytes(StandardCharsets.UTF_8).length > MAX_URI_BYTES) {
+        if (mServerUri.getBytes(StandardCharsets.UTF_8).length > MAX_URI_BYTES) {
             Log.d(TAG, "URI bytes exceeded the max: "
-                    + serverUri.getBytes(StandardCharsets.UTF_8).length);
+                    + mServerUri.getBytes(StandardCharsets.UTF_8).length);
             return false;
         }
 
-        if (TextUtils.isEmpty(username)) {
+        if (TextUtils.isEmpty(mUsername)) {
             Log.d(TAG, "Missing username");
             return false;
         }
-        if (username.getBytes(StandardCharsets.UTF_8).length > MAX_USERNAME_BYTES) {
+        if (mUsername.getBytes(StandardCharsets.UTF_8).length > MAX_USERNAME_BYTES) {
             Log.d(TAG, "Username bytes exceeded the max: "
-                    + username.getBytes(StandardCharsets.UTF_8).length);
+                    + mUsername.getBytes(StandardCharsets.UTF_8).length);
             return false;
         }
 
-        if (TextUtils.isEmpty(base64EncodedPassword)) {
+        if (TextUtils.isEmpty(mBase64EncodedPassword)) {
             Log.d(TAG, "Missing username");
             return false;
         }
-        if (base64EncodedPassword.getBytes(StandardCharsets.UTF_8).length > MAX_PASSWORD_BYTES) {
+        if (mBase64EncodedPassword.getBytes(StandardCharsets.UTF_8).length > MAX_PASSWORD_BYTES) {
             Log.d(TAG, "Password bytes exceeded the max: "
-                    + base64EncodedPassword.getBytes(StandardCharsets.UTF_8).length);
+                    + mBase64EncodedPassword.getBytes(StandardCharsets.UTF_8).length);
             return false;
         }
         try {
-            Base64.decode(base64EncodedPassword, Base64.DEFAULT);
+            Base64.decode(mBase64EncodedPassword, Base64.DEFAULT);
         } catch (IllegalArgumentException e) {
-            Log.d(TAG, "Invalid encoding for password: " + base64EncodedPassword);
+            Log.d(TAG, "Invalid encoding for password: " + mBase64EncodedPassword);
             return false;
         }
 
-        if (TextUtils.isEmpty(trustRootCertUrl)) {
+        if (TextUtils.isEmpty(mTrustRootCertUrl)) {
             Log.d(TAG, "Missing trust root certificate URL");
             return false;
         }
-        if (trustRootCertUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
+        if (mTrustRootCertUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
             Log.d(TAG, "Trust root cert URL bytes exceeded the max: "
-                    + trustRootCertUrl.getBytes(StandardCharsets.UTF_8).length);
+                    + mTrustRootCertUrl.getBytes(StandardCharsets.UTF_8).length);
             return false;
         }
 
-        if (trustRootCertSha256Fingerprint == null) {
+        if (mTrustRootCertSha256Fingerprint == null) {
             Log.d(TAG, "Missing trust root certificate SHA-256 fingerprint");
             return false;
         }
-        if (trustRootCertSha256Fingerprint.length != CERTIFICATE_SHA256_BYTES) {
+        if (mTrustRootCertSha256Fingerprint.length != CERTIFICATE_SHA256_BYTES) {
             Log.d(TAG, "Incorrect size of trust root certificate SHA-256 fingerprint: "
-                    + trustRootCertSha256Fingerprint.length);
+                    + mTrustRootCertSha256Fingerprint.length);
             return false;
         }
         return true;
@@ -284,14 +340,14 @@
             @Override
             public UpdateParameter createFromParcel(Parcel in) {
                 UpdateParameter updateParam = new UpdateParameter();
-                updateParam.updateIntervalInMinutes = in.readLong();
-                updateParam.updateMethod = in.readString();
-                updateParam.restriction = in.readString();
-                updateParam.serverUri = in.readString();
-                updateParam.username = in.readString();
-                updateParam.base64EncodedPassword = in.readString();
-                updateParam.trustRootCertUrl = in.readString();
-                updateParam.trustRootCertSha256Fingerprint = in.createByteArray();
+                updateParam.setUpdateIntervalInMinutes(in.readLong());
+                updateParam.setUpdateMethod(in.readString());
+                updateParam.setRestriction(in.readString());
+                updateParam.setServerUri(in.readString());
+                updateParam.setUsername(in.readString());
+                updateParam.setBase64EncodedPassword(in.readString());
+                updateParam.setTrustRootCertUrl(in.readString());
+                updateParam.setTrustRootCertSha256Fingerprint(in.createByteArray());
                 return updateParam;
             }
 
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
index 6095929..f7dbf7e 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
@@ -83,27 +83,33 @@
         PasspointConfiguration config = new PasspointConfiguration();
 
         // HomeSP configuration.
-        config.homeSp = new HomeSP();
-        config.homeSp.friendlyName = "Century House";
-        config.homeSp.fqdn = "mi6.co.uk";
-        config.homeSp.roamingConsortiumOIs = new long[] {0x112233L, 0x445566L};
+        HomeSP homeSp = new HomeSP();
+        homeSp.setFriendlyName("Century House");
+        homeSp.setFqdn("mi6.co.uk");
+        homeSp.setRoamingConsortiumOIs(new long[] {0x112233L, 0x445566L});
+        config.setHomeSp(homeSp);
 
         // Credential configuration.
-        config.credential = new Credential();
-        config.credential.realm = "shaken.stirred.com";
-        config.credential.userCredential = new Credential.UserCredential();
-        config.credential.userCredential.username = "james";
-        config.credential.userCredential.password = "Ym9uZDAwNw==";
-        config.credential.userCredential.eapType = 21;
-        config.credential.userCredential.nonEapInnerMethod = "MS-CHAP-V2";
-        config.credential.certCredential = new Credential.CertificateCredential();
-        config.credential.certCredential.certType = "x509v3";
-        config.credential.certCredential.certSha256FingerPrint = new byte[32];
-        Arrays.fill(config.credential.certCredential.certSha256FingerPrint, (byte)0x1f);
-        config.credential.simCredential = new Credential.SimCredential();
-        config.credential.simCredential.imsi = "imsi";
-        config.credential.simCredential.eapType = 24;
-        config.credential.caCertificate = FakeKeys.CA_CERT0;
+        Credential credential = new Credential();
+        credential.setRealm("shaken.stirred.com");
+        Credential.UserCredential userCredential = new Credential.UserCredential();
+        userCredential.setUsername("james");
+        userCredential.setPassword("Ym9uZDAwNw==");
+        userCredential.setEapType(21);
+        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
+        credential.setUserCredential(userCredential);
+        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
+        certCredential.setCertType("x509v3");
+        byte[] certSha256Fingerprint = new byte[32];
+        Arrays.fill(certSha256Fingerprint, (byte)0x1f);
+        certCredential.setCertSha256Fingerprint(certSha256Fingerprint);
+        credential.setCertCredential(certCredential);
+        Credential.SimCredential simCredential = new Credential.SimCredential();
+        simCredential.setImsi("imsi");
+        simCredential.setEapType(24);
+        credential.setSimCredential(simCredential);
+        credential.setCaCertificate(FakeKeys.CA_CERT0);
+        config.setCredential(credential);
         return config;
     }
 
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 1eb08e0..3aed918 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -34,6 +34,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Unit tests for {@link android.net.wifi.hotspot2.PasspointConfiguration}.
@@ -50,9 +52,9 @@
      */
     private static HomeSP createHomeSp() {
         HomeSP homeSp = new HomeSP();
-        homeSp.fqdn = "fqdn";
-        homeSp.friendlyName = "friendly name";
-        homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
+        homeSp.setFqdn("fqdn");
+        homeSp.setFriendlyName("friendly name");
+        homeSp.setRoamingConsortiumOIs(new long[] {0x55, 0x66});
         return homeSp;
     }
 
@@ -63,15 +65,15 @@
      */
     private static Credential createCredential() {
         Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = null;
-        cred.certCredential = null;
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "1234*";
-        cred.simCredential.eapType = EAPConstants.EAP_SIM;
-        cred.caCertificate = null;
-        cred.clientCertificateChain = null;
-        cred.clientPrivateKey = null;
+        cred.setRealm("realm");
+        cred.setUserCredential(null);
+        cred.setCertCredential(null);
+        cred.setSimCredential(new Credential.SimCredential());
+        cred.getSimCredential().setImsi("1234*");
+        cred.getSimCredential().setEapType(EAPConstants.EAP_SIM);
+        cred.setCaCertificate(null);
+        cred.setClientCertificateChain(null);
+        cred.setClientPrivateKey(null);
         return cred;
     }
 
@@ -82,56 +84,59 @@
      */
     private static Policy createPolicy() {
         Policy policy = new Policy();
-        policy.minHomeDownlinkBandwidth = 123;
-        policy.minHomeUplinkBandwidth = 345;
-        policy.minRoamingDownlinkBandwidth = 567;
-        policy.minRoamingUplinkBandwidth = 789;
-        policy.maximumBssLoadValue = 12;
-        policy.excludedSsidList = new String[] {"ssid1", "ssid2"};
-        policy.requiredProtoPortMap = new HashMap<>();
-        policy.requiredProtoPortMap.put(12, "23,342,123");
-        policy.requiredProtoPortMap.put(23, "789,372,1235");
+        policy.setMinHomeDownlinkBandwidth(123);
+        policy.setMinHomeUplinkBandwidth(345);
+        policy.setMinRoamingDownlinkBandwidth(567);
+        policy.setMinRoamingUplinkBandwidth(789);
+        policy.setMaximumBssLoadValue(12);
+        policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"});
+        HashMap<Integer, String> requiredProtoPortMap = new HashMap<>();
+        requiredProtoPortMap.put(12, "23,342,123");
+        requiredProtoPortMap.put(23, "789,372,1235");
+        policy.setRequiredProtoPortMap(requiredProtoPortMap);
 
-        policy.preferredRoamingPartnerList = new ArrayList<>();
+        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
         Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
-        partner1.fqdn = "partner1.com";
-        partner1.fqdnExactMatch = true;
-        partner1.priority = 12;
-        partner1.countries = "us,jp";
+        partner1.setFqdn("partner1.com");
+        partner1.setFqdnExactMatch(true);
+        partner1.setPriority(12);
+        partner1.setCountries("us,jp");
         Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
-        partner2.fqdn = "partner2.com";
-        partner2.fqdnExactMatch = false;
-        partner2.priority = 42;
-        partner2.countries = "ca,fr";
-        policy.preferredRoamingPartnerList.add(partner1);
-        policy.preferredRoamingPartnerList.add(partner2);
+        partner2.setFqdn("partner2.com");
+        partner2.setFqdnExactMatch(false);
+        partner2.setPriority(42);
+        partner2.setCountries("ca,fr");
+        preferredRoamingPartnerList.add(partner1);
+        preferredRoamingPartnerList.add(partner2);
+        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
 
-        policy.policyUpdate = new UpdateParameter();
-        policy.policyUpdate.updateIntervalInMinutes = 1712;
-        policy.policyUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
-        policy.policyUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
-        policy.policyUpdate.serverUri = "policy.update.com";
-        policy.policyUpdate.username = "username";
-        policy.policyUpdate.base64EncodedPassword =
-                Base64.encodeToString("password".getBytes(), Base64.DEFAULT);
-        policy.policyUpdate.trustRootCertUrl = "trust.cert.com";
-        policy.policyUpdate.trustRootCertSha256Fingerprint =
-                new byte[CERTIFICATE_FINGERPRINT_BYTES];
+        UpdateParameter policyUpdate = new UpdateParameter();
+        policyUpdate.setUpdateIntervalInMinutes(1712);
+        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
+        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
+        policyUpdate.setServerUri("policy.update.com");
+        policyUpdate.setUsername("username");
+        policyUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
+        policyUpdate.setTrustRootCertUrl("trust.cert.com");
+        policyUpdate.setTrustRootCertSha256Fingerprint(
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        policy.setPolicyUpdate(policyUpdate);
 
         return policy;
     }
 
     private static UpdateParameter createSubscriptionUpdate() {
         UpdateParameter subUpdate = new UpdateParameter();
-        subUpdate.updateIntervalInMinutes = 9021;
-        subUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_SSP;
-        subUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER;
-        subUpdate.serverUri = "subscription.update.com";
-        subUpdate.username = "subUsername";
-        subUpdate.base64EncodedPassword =
-                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT);
-        subUpdate.trustRootCertUrl = "subscription.trust.cert.com";
-        subUpdate.trustRootCertSha256Fingerprint = new byte[CERTIFICATE_FINGERPRINT_BYTES];
+        subUpdate.setUpdateIntervalInMinutes(9021);
+        subUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
+        subUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
+        subUpdate.setServerUri("subscription.update.com");
+        subUpdate.setUsername("subUsername");
+        subUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT));
+        subUpdate.setTrustRootCertUrl("subscription.trust.cert.com");
+        subUpdate.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_FINGERPRINT_BYTES]);
         return subUpdate;
     }
     /**
@@ -141,24 +146,25 @@
      */
     private static PasspointConfiguration createConfig() {
         PasspointConfiguration config = new PasspointConfiguration();
-        config.homeSp = createHomeSp();
-        config.credential = createCredential();
-        config.policy = createPolicy();
-        config.subscriptionUpdate = createSubscriptionUpdate();
-        config.trustRootCertList = new HashMap<>();
-        config.trustRootCertList.put("trustRoot.cert1.com",
+        config.setHomeSp(createHomeSp());
+        config.setCredential(createCredential());
+        config.setPolicy(createPolicy());
+        config.setSubscriptionUpdate(createSubscriptionUpdate());
+        Map<String, byte[]> trustRootCertList = new HashMap<>();
+        trustRootCertList.put("trustRoot.cert1.com",
                 new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        config.trustRootCertList.put("trustRoot.cert2.com",
+        trustRootCertList.put("trustRoot.cert2.com",
                 new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        config.updateIdentifier = 1;
-        config.credentialPriority = 120;
-        config.subscriptionCreationTimeInMs = 231200;
-        config.subscriptionExpirationTimeInMs = 2134232;
-        config.subscriptionType = "Gold";
-        config.usageLimitUsageTimePeriodInMinutes = 3600;
-        config.usageLimitStartTimeInMs = 124214213;
-        config.usageLimitDataLimit = 14121;
-        config.usageLimitTimeLimitInMinutes = 78912;
+        config.setTrustRootCertList(trustRootCertList);
+        config.setUpdateIdentifier(1);
+        config.setCredentialPriority(120);
+        config.setSubscriptionCreationTimeInMs(231200);
+        config.setSubscriptionExpirationTimeInMs(2134232);
+        config.setSubscriptionType("Gold");
+        config.setUsageLimitUsageTimePeriodInMinutes(3600);
+        config.setUsageLimitStartTimeInMs(124214213);
+        config.setUsageLimitDataLimit(14121);
+        config.setUsageLimitTimeLimitInMinutes(78912);
         return config;
     }
 
@@ -206,7 +212,7 @@
     @Test
     public void verifyParcelWithoutHomeSP() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.homeSp = null;
+        config.setHomeSp(null);
         verifyParcel(config);
     }
 
@@ -218,7 +224,7 @@
     @Test
     public void verifyParcelWithoutCredential() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.credential = null;
+        config.setCredential(null);
         verifyParcel(config);
     }
 
@@ -230,7 +236,7 @@
     @Test
     public void verifyParcelWithoutPolicy() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.policy = null;
+        config.setPolicy(null);
         verifyParcel(config);
     }
 
@@ -242,7 +248,7 @@
     @Test
     public void verifyParcelWithoutSubscriptionUpdate() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.subscriptionUpdate = null;
+        config.setSubscriptionUpdate(null);
         verifyParcel(config);
     }
 
@@ -255,7 +261,7 @@
     @Test
     public void verifyParcelWithoutTrustRootCertList() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.trustRootCertList = null;
+        config.setTrustRootCertList(null);
         verifyParcel(config);
     }
 
@@ -289,7 +295,7 @@
     @Test
     public void validateConfigWithoutCredential() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.credential = null;
+        config.setCredential(null);
         assertFalse(config.validate());
     }
 
@@ -301,7 +307,7 @@
     @Test
     public void validateConfigWithoutHomeSp() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.homeSp = null;
+        config.setHomeSp(null);
         assertFalse(config.validate());
     }
 
@@ -314,7 +320,7 @@
     @Test
     public void validateConfigWithoutPolicy() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.policy = null;
+        config.setPolicy(null);
         assertTrue(config.validate());
     }
 
@@ -327,7 +333,7 @@
     @Test
     public void validateConfigWithoutSubscriptionUpdate() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.subscriptionUpdate = null;
+        config.setSubscriptionUpdate(null);
         assertTrue(config.validate());
     }
 
@@ -341,13 +347,16 @@
     public void validateConfigWithInvalidTrustRootCertUrl() throws Exception {
         PasspointConfiguration config = createConfig();
         byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1];
+        Map<String, byte[]> trustRootCertList = new HashMap<>();
         Arrays.fill(rawUrlBytes, (byte) 'a');
-        config.trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
+        trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
                 new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
 
-        config.trustRootCertList = new HashMap<>();
-        config.trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        trustRootCertList = new HashMap<>();
+        trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
     }
 
@@ -359,16 +368,19 @@
     @Test
     public void validateConfigWithInvalidTrustRootCertFingerprint() throws Exception {
         PasspointConfiguration config = createConfig();
-        config.trustRootCertList = new HashMap<>();
-        config.trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES + 1]);
+        Map<String, byte[]> trustRootCertList = new HashMap<>();
+        trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES + 1]);
+        config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
 
-        config.trustRootCertList = new HashMap<>();
-        config.trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES - 1]);
+        trustRootCertList = new HashMap<>();
+        trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES - 1]);
+        config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
 
-        config.trustRootCertList = new HashMap<>();
-        config.trustRootCertList.put("test.cert.com", null);
+        trustRootCertList = new HashMap<>();
+        trustRootCertList.put("test.cert.com", null);
+        config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
     }
 
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
index 055204c..15de5c7 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
@@ -39,6 +39,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Unit tests for {@link android.net.wifi.hotspot2.omadm.PPSMOParser}.
@@ -86,107 +88,115 @@
      */
     private PasspointConfiguration generateConfigurationFromPPSMOTree() throws Exception {
         DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
-
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.updateIdentifier = 12;
-        config.credentialPriority = 99;
-
-        // AAA Server trust root.
-        config.trustRootCertList = new HashMap<>();
         byte[] certFingerprint = new byte[32];
         Arrays.fill(certFingerprint, (byte) 0x1f);
-        config.trustRootCertList.put("server1.trust.root.com", certFingerprint);
+
+        PasspointConfiguration config = new PasspointConfiguration();
+        config.setUpdateIdentifier(12);
+        config.setCredentialPriority(99);
+
+        // AAA Server trust root.
+        Map<String, byte[]> trustRootCertList = new HashMap<>();
+        trustRootCertList.put("server1.trust.root.com", certFingerprint);
+        config.setTrustRootCertList(trustRootCertList);
 
         // Subscription update.
-        config.subscriptionUpdate = new UpdateParameter();
-        config.subscriptionUpdate.updateIntervalInMinutes = 120;
-        config.subscriptionUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_SSP;
-        config.subscriptionUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER;
-        config.subscriptionUpdate.serverUri = "subscription.update.com";
-        config.subscriptionUpdate.username = "subscriptionUser";
-        config.subscriptionUpdate.base64EncodedPassword = "subscriptionPass";
-        config.subscriptionUpdate.trustRootCertUrl = "subscription.update.cert.com";
-        config.subscriptionUpdate.trustRootCertSha256Fingerprint = new byte[32];
-        Arrays.fill(config.subscriptionUpdate.trustRootCertSha256Fingerprint, (byte) 0x1f);
+        UpdateParameter subscriptionUpdate = new UpdateParameter();
+        subscriptionUpdate.setUpdateIntervalInMinutes(120);
+        subscriptionUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
+        subscriptionUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
+        subscriptionUpdate.setServerUri("subscription.update.com");
+        subscriptionUpdate.setUsername("subscriptionUser");
+        subscriptionUpdate.setBase64EncodedPassword("subscriptionPass");
+        subscriptionUpdate.setTrustRootCertUrl("subscription.update.cert.com");
+        subscriptionUpdate.setTrustRootCertSha256Fingerprint(certFingerprint);
+        config.setSubscriptionUpdate(subscriptionUpdate);
 
         // Subscription parameters.
-        config.subscriptionCreationTimeInMs = format.parse("2016-02-01T10:00:00Z").getTime();
-        config.subscriptionExpirationTimeInMs = format.parse("2016-03-01T10:00:00Z").getTime();
-        config.subscriptionType = "Gold";
-        config.usageLimitDataLimit = 921890;
-        config.usageLimitStartTimeInMs = format.parse("2016-12-01T10:00:00Z").getTime();
-        config.usageLimitTimeLimitInMinutes = 120;
-        config.usageLimitUsageTimePeriodInMinutes = 99910;
+        config.setSubscriptionCreationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
+        config.setSubscriptionExpirationTimeInMs(format.parse("2016-03-01T10:00:00Z").getTime());
+        config.setSubscriptionType("Gold");
+        config.setUsageLimitDataLimit(921890);
+        config.setUsageLimitStartTimeInMs(format.parse("2016-12-01T10:00:00Z").getTime());
+        config.setUsageLimitTimeLimitInMinutes(120);
+        config.setUsageLimitUsageTimePeriodInMinutes(99910);
 
         // HomeSP configuration.
-        config.homeSp = new HomeSP();
-        config.homeSp.friendlyName = "Century House";
-        config.homeSp.fqdn = "mi6.co.uk";
-        config.homeSp.roamingConsortiumOIs = new long[] {0x112233L, 0x445566L};
-        config.homeSp.iconUrl = "icon.test.com";
-        config.homeSp.homeNetworkIds = new HashMap<>();
-        config.homeSp.homeNetworkIds.put("TestSSID", 0x12345678L);
-        config.homeSp.homeNetworkIds.put("NullHESSID", null);
-        config.homeSp.matchAllOIs = new long[] {0x11223344};
-        config.homeSp.matchAnyOIs = new long[] {0x55667788};
-        config.homeSp.otherHomePartners = new String[] {"other.fqdn.com"};
+        HomeSP homeSp = new HomeSP();
+        homeSp.setFriendlyName("Century House");
+        homeSp.setFqdn("mi6.co.uk");
+        homeSp.setRoamingConsortiumOIs(new long[] {0x112233L, 0x445566L});
+        homeSp.setIconUrl("icon.test.com");
+        Map<String, Long> homeNetworkIds = new HashMap<>();
+        homeNetworkIds.put("TestSSID", 0x12345678L);
+        homeNetworkIds.put("NullHESSID", null);
+        homeSp.setHomeNetworkIds(homeNetworkIds);
+        homeSp.setMatchAllOIs(new long[] {0x11223344});
+        homeSp.setMatchAnyOIs(new long[] {0x55667788});
+        homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"});
+        config.setHomeSp(homeSp);
 
         // Credential configuration.
-        config.credential = new Credential();
-        config.credential.creationTimeInMs = format.parse("2016-01-01T10:00:00Z").getTime();
-        config.credential.expirationTimeInMs = format.parse("2016-02-01T10:00:00Z").getTime();
-        config.credential.realm = "shaken.stirred.com";
-        config.credential.checkAAAServerCertStatus = true;
-        config.credential.userCredential = new Credential.UserCredential();
-        config.credential.userCredential.username = "james";
-        config.credential.userCredential.password = "Ym9uZDAwNw==";
-        config.credential.userCredential.machineManaged = true;
-        config.credential.userCredential.softTokenApp = "TestApp";
-        config.credential.userCredential.ableToShare = true;
-        config.credential.userCredential.eapType = 21;
-        config.credential.userCredential.nonEapInnerMethod = "MS-CHAP-V2";
-        config.credential.certCredential = new Credential.CertificateCredential();
-        config.credential.certCredential.certType = "x509v3";
-        config.credential.certCredential.certSha256FingerPrint = new byte[32];
-        Arrays.fill(config.credential.certCredential.certSha256FingerPrint, (byte)0x1f);
-        config.credential.simCredential = new Credential.SimCredential();
-        config.credential.simCredential.imsi = "imsi";
-        config.credential.simCredential.eapType = 24;
+        Credential credential = new Credential();
+        credential.setCreationTimeInMs(format.parse("2016-01-01T10:00:00Z").getTime());
+        credential.setExpirationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
+        credential.setRealm("shaken.stirred.com");
+        credential.setCheckAAAServerCertStatus(true);
+        Credential.UserCredential userCredential = new Credential.UserCredential();
+        userCredential.setUsername("james");
+        userCredential.setPassword("Ym9uZDAwNw==");
+        userCredential.setMachineManaged(true);
+        userCredential.setSoftTokenApp("TestApp");
+        userCredential.setAbleToShare(true);
+        userCredential.setEapType(21);
+        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
+        credential.setUserCredential(userCredential);
+        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
+        certCredential.setCertType("x509v3");
+        certCredential.setCertSha256Fingerprint(certFingerprint);
+        credential.setCertCredential(certCredential);
+        Credential.SimCredential simCredential = new Credential.SimCredential();
+        simCredential.setImsi("imsi");
+        simCredential.setEapType(24);
+        credential.setSimCredential(simCredential);
+        config.setCredential(credential);
 
         // Policy configuration.
-        config.policy = new Policy();
-        config.policy.preferredRoamingPartnerList = new ArrayList<>();
+        Policy policy = new Policy();
+        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
         Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
-        partner1.fqdn = "test1.fqdn.com";
-        partner1.fqdnExactMatch = true;
-        partner1.priority = 127;
-        partner1.countries = "us,fr";
+        partner1.setFqdn("test1.fqdn.com");
+        partner1.setFqdnExactMatch(true);
+        partner1.setPriority(127);
+        partner1.setCountries("us,fr");
         Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
-        partner2.fqdn = "test2.fqdn.com";
-        partner2.fqdnExactMatch = false;
-        partner2.priority = 200;
-        partner2.countries = "*";
-        config.policy.preferredRoamingPartnerList.add(partner1);
-        config.policy.preferredRoamingPartnerList.add(partner2);
-        config.policy.minHomeDownlinkBandwidth = 23412;
-        config.policy.minHomeUplinkBandwidth = 9823;
-        config.policy.minRoamingDownlinkBandwidth = 9271;
-        config.policy.minRoamingUplinkBandwidth = 2315;
-        config.policy.excludedSsidList = new String[] {"excludeSSID"};
-        config.policy.requiredProtoPortMap = new HashMap<>();
-        config.policy.requiredProtoPortMap.put(12, "34,92,234");
-        config.policy.maximumBssLoadValue = 23;
-        config.policy.policyUpdate = new UpdateParameter();
-        config.policy.policyUpdate.updateIntervalInMinutes = 120;
-        config.policy.policyUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
-        config.policy.policyUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
-        config.policy.policyUpdate.serverUri = "policy.update.com";
-        config.policy.policyUpdate.username = "updateUser";
-        config.policy.policyUpdate.base64EncodedPassword = "updatePass";
-        config.policy.policyUpdate.trustRootCertUrl = "update.cert.com";
-        config.policy.policyUpdate.trustRootCertSha256Fingerprint = new byte[32];
-        Arrays.fill(config.policy.policyUpdate.trustRootCertSha256Fingerprint, (byte) 0x1f);
-
+        partner2.setFqdn("test2.fqdn.com");
+        partner2.setFqdnExactMatch(false);
+        partner2.setPriority(200);
+        partner2.setCountries("*");
+        preferredRoamingPartnerList.add(partner1);
+        preferredRoamingPartnerList.add(partner2);
+        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
+        policy.setMinHomeDownlinkBandwidth(23412);
+        policy.setMinHomeUplinkBandwidth(9823);
+        policy.setMinRoamingDownlinkBandwidth(9271);
+        policy.setMinRoamingUplinkBandwidth(2315);
+        policy.setExcludedSsidList(new String[] {"excludeSSID"});
+        Map<Integer, String> requiredProtoPortMap = new HashMap<>();
+        requiredProtoPortMap.put(12, "34,92,234");
+        policy.setRequiredProtoPortMap(requiredProtoPortMap);
+        policy.setMaximumBssLoadValue(23);
+        UpdateParameter policyUpdate = new UpdateParameter();
+        policyUpdate.setUpdateIntervalInMinutes(120);
+        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
+        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
+        policyUpdate.setServerUri("policy.update.com");
+        policyUpdate.setUsername("updateUser");
+        policyUpdate.setBase64EncodedPassword("updatePass");
+        policyUpdate.setTrustRootCertUrl("update.cert.com");
+        policyUpdate.setTrustRootCertSha256Fingerprint(certFingerprint);
+        policy.setPolicyUpdate(policyUpdate);
+        config.setPolicy(policy);
         return config;
     }
 
@@ -249,10 +259,3 @@
                 loadResourceFile(PPS_MO_XML_FILE_INVALID_NAME)));
     }
 }
-
-
-
-
-
-
-
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index f571c7fc..6f68e1c 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -23,10 +23,11 @@
 import android.net.wifi.FakeKeys;
 import android.os.Parcel;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 
@@ -55,16 +56,16 @@
                                                X509Certificate[] clientCertificateChain,
                                                PrivateKey clientPrivateKey) {
         Credential cred = new Credential();
-        cred.creationTimeInMs = 123455L;
-        cred.expirationTimeInMs = 2310093L;
-        cred.realm = "realm";
-        cred.checkAAAServerCertStatus = true;
-        cred.userCredential = userCred;
-        cred.certCredential = certCred;
-        cred.simCredential = simCred;
-        cred.caCertificate = caCert;
-        cred.clientCertificateChain = clientCertificateChain;
-        cred.clientPrivateKey = clientPrivateKey;
+        cred.setCreationTimeInMs(123455L);
+        cred.setExpirationTimeInMs(2310093L);
+        cred.setRealm("realm");
+        cred.setCheckAAAServerCertStatus(true);
+        cred.setUserCredential(userCred);
+        cred.setCertCredential(certCred);
+        cred.setSimCredential(simCred);
+        cred.setCaCertificate(caCert);
+        cred.setClientCertificateChain(clientCertificateChain);
+        cred.setClientPrivateKey(clientPrivateKey);
         return cred;
     }
 
@@ -73,10 +74,12 @@
      *
      * @return {@link Credential}
      */
-    private static Credential createCredentialWithCertificateCredential() {
+    private static Credential createCredentialWithCertificateCredential()
+            throws NoSuchAlgorithmException, CertificateEncodingException {
         Credential.CertificateCredential certCred = new Credential.CertificateCredential();
-        certCred.certType = "x509v3";
-        certCred.certSha256FingerPrint = new byte[32];
+        certCred.setCertType("x509v3");
+        certCred.setCertSha256Fingerprint(
+                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
         return createCredential(null, certCred, null, FakeKeys.CA_CERT0,
                 new X509Certificate[] {FakeKeys.CLIENT_CERT}, FakeKeys.RSA_KEY1);
     }
@@ -88,8 +91,8 @@
      */
     private static Credential createCredentialWithSimCredential() {
         Credential.SimCredential simCred = new Credential.SimCredential();
-        simCred.imsi = "1234*";
-        simCred.eapType = EAPConstants.EAP_SIM;
+        simCred.setImsi("1234*");
+        simCred.setEapType(EAPConstants.EAP_SIM);
         return createCredential(null, null, simCred, null, null, null);
     }
 
@@ -100,15 +103,14 @@
      */
     private static Credential createCredentialWithUserCredential() {
         Credential.UserCredential userCred = new Credential.UserCredential();
-        userCred.username = "username";
-        userCred.password = "password";
-        userCred.machineManaged = true;
-        userCred.ableToShare = true;
-        userCred.softTokenApp = "TestApp";
-        userCred.eapType = EAPConstants.EAP_TTLS;
-        userCred.nonEapInnerMethod = "MS-CHAP";
-        return createCredential(userCred, null, null, FakeKeys.CA_CERT0,
-                new X509Certificate[] {FakeKeys.CLIENT_CERT}, FakeKeys.RSA_KEY1);
+        userCred.setUsername("username");
+        userCred.setPassword("password");
+        userCred.setMachineManaged(true);
+        userCred.setAbleToShare(true);
+        userCred.setSoftTokenApp("TestApp");
+        userCred.setEapType(EAPConstants.EAP_TTLS);
+        userCred.setNonEapInnerMethod("MS-CHAP");
+        return createCredential(userCred, null, null, FakeKeys.CA_CERT0, null, null);
     }
 
     private static void verifyParcel(Credential writeCred) {
@@ -166,14 +168,7 @@
      */
     @Test
     public void validateUserCredential() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
         assertTrue(cred.validate());
     }
 
@@ -184,13 +179,8 @@
      */
     @Test
     public void validateUserCredentialWithoutCaCert() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
+        Credential cred = createCredentialWithUserCredential();
+        cred.setCaCertificate(null);
         assertFalse(cred.validate());
     }
 
@@ -201,14 +191,8 @@
      */
     @Test
     public void validateUserCredentialWithEapTls() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
+        cred.getUserCredential().setEapType(EAPConstants.EAP_TLS);
         assertFalse(cred.validate());
     }
 
@@ -220,13 +204,8 @@
      */
     @Test
     public void validateUserCredentialWithoutRealm() throws Exception {
-        Credential cred = new Credential();
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
+        cred.setRealm(null);
         assertFalse(cred.validate());
     }
 
@@ -237,13 +216,8 @@
      */
     @Test
     public void validateUserCredentialWithoutUsername() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
+        cred.getUserCredential().setUsername(null);
         assertFalse(cred.validate());
     }
 
@@ -254,13 +228,8 @@
      */
     @Test
     public void validateUserCredentialWithoutPassword() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
+        cred.getUserCredential().setPassword(null);
         assertFalse(cred.validate());
     }
 
@@ -271,13 +240,8 @@
      */
     @Test
     public void validateUserCredentialWithoutAuthMethod() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
+        cred.getUserCredential().setNonEapInnerMethod(null);
         assertFalse(cred.validate());
     }
 
@@ -290,17 +254,7 @@
      */
     @Test
     public void validateCertCredential() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup certificate credential.
-        cred.certCredential = new Credential.CertificateCredential();
-        cred.certCredential.certType = "x509v3";
-        cred.certCredential.certSha256FingerPrint =
-                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded());
-        // Setup certificates and private key.
-        cred.caCertificate = FakeKeys.CA_CERT0;
-        cred.clientCertificateChain = new X509Certificate[] {FakeKeys.CLIENT_CERT};
-        cred.clientPrivateKey = FakeKeys.RSA_KEY1;
+        Credential cred = createCredentialWithCertificateCredential();
         assertTrue(cred.validate());
     }
 
@@ -310,16 +264,8 @@
      * @throws Exception
      */
     public void validateCertCredentialWithoutCaCert() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup certificate credential.
-        cred.certCredential = new Credential.CertificateCredential();
-        cred.certCredential.certType = "x509v3";
-        cred.certCredential.certSha256FingerPrint =
-                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded());
-        // Setup certificates and private key.
-        cred.clientCertificateChain = new X509Certificate[] {FakeKeys.CLIENT_CERT};
-        cred.clientPrivateKey = FakeKeys.RSA_KEY1;
+        Credential cred = createCredentialWithCertificateCredential();
+        cred.setCaCertificate(null);
         assertFalse(cred.validate());
     }
 
@@ -330,16 +276,8 @@
      */
     @Test
     public void validateCertCredentialWithoutClientCertChain() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup certificate credential.
-        cred.certCredential = new Credential.CertificateCredential();
-        cred.certCredential.certType = "x509v3";
-        cred.certCredential.certSha256FingerPrint =
-                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded());
-        // Setup certificates and private key.
-        cred.caCertificate = FakeKeys.CA_CERT0;
-        cred.clientPrivateKey = FakeKeys.RSA_KEY1;
+        Credential cred = createCredentialWithCertificateCredential();
+        cred.setClientCertificateChain(null);
         assertFalse(cred.validate());
     }
 
@@ -350,16 +288,8 @@
      */
     @Test
     public void validateCertCredentialWithoutClientPrivateKey() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup certificate credential.
-        cred.certCredential = new Credential.CertificateCredential();
-        cred.certCredential.certType = "x509v3";
-        cred.certCredential.certSha256FingerPrint =
-                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded());
-        // Setup certificates and private key.
-        cred.caCertificate = FakeKeys.CA_CERT0;
-        cred.clientCertificateChain = new X509Certificate[] {FakeKeys.CLIENT_CERT};
+        Credential cred = createCredentialWithCertificateCredential();
+        cred.setClientPrivateKey(null);
         assertFalse(cred.validate());
     }
 
@@ -371,17 +301,8 @@
      */
     @Test
     public void validateCertCredentialWithMismatchFingerprint() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup certificate credential.
-        cred.certCredential = new Credential.CertificateCredential();
-        cred.certCredential.certType = "x509v3";
-        cred.certCredential.certSha256FingerPrint = new byte[32];
-        Arrays.fill(cred.certCredential.certSha256FingerPrint, (byte)0);
-        // Setup certificates and private key.
-        cred.caCertificate = FakeKeys.CA_CERT0;
-        cred.clientCertificateChain = new X509Certificate[] {FakeKeys.CLIENT_CERT};
-        cred.clientPrivateKey = FakeKeys.RSA_KEY1;
+        Credential cred = createCredentialWithCertificateCredential();
+        cred.getCertCredential().setCertSha256Fingerprint(new byte[32]);
         assertFalse(cred.validate());
     }
 
@@ -392,12 +313,7 @@
      */
     @Test
     public void validateSimCredentialWithEapSim() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "1234*";
-        cred.simCredential.eapType = EAPConstants.EAP_SIM;
+        Credential cred = createCredentialWithSimCredential();
         assertTrue(cred.validate());
     }
 
@@ -408,12 +324,8 @@
      */
     @Test
     public void validateSimCredentialWithEapAka() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "1234*";
-        cred.simCredential.eapType = EAPConstants.EAP_AKA;
+        Credential cred = createCredentialWithSimCredential();
+        cred.getSimCredential().setEapType(EAPConstants.EAP_AKA);
         assertTrue(cred.validate());
     }
 
@@ -424,12 +336,8 @@
      */
     @Test
     public void validateSimCredentialWithEapAkaPrime() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "1234*";
-        cred.simCredential.eapType = EAPConstants.EAP_AKA_PRIME;
+        Credential cred = createCredentialWithSimCredential();
+        cred.getSimCredential().setEapType(EAPConstants.EAP_AKA_PRIME);
         assertTrue(cred.validate());
     }
 
@@ -440,11 +348,8 @@
      */
     @Test
     public void validateSimCredentialWithoutIMSI() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.eapType = EAPConstants.EAP_SIM;
+        Credential cred = createCredentialWithSimCredential();
+        cred.getSimCredential().setImsi(null);
         assertFalse(cred.validate());
     }
 
@@ -455,12 +360,8 @@
      */
     @Test
     public void validateSimCredentialWithInvalidIMSI() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "dummy";
-        cred.simCredential.eapType = EAPConstants.EAP_SIM;
+        Credential cred = createCredentialWithSimCredential();
+        cred.getSimCredential().setImsi("dummy");
         assertFalse(cred.validate());
     }
 
@@ -471,12 +372,8 @@
      */
     @Test
     public void validateSimCredentialWithEapTls() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "1234*";
-        cred.simCredential.eapType = EAPConstants.EAP_TLS;
+        Credential cred = createCredentialWithSimCredential();
+        cred.getSimCredential().setEapType(EAPConstants.EAP_TLS);
         assertFalse(cred.validate());
     }
 
@@ -487,19 +384,12 @@
      */
     @Test
     public void validateCredentialWithUserAndSimCredential() throws Exception {
-        Credential cred = new Credential();
-        cred.realm = "realm";
-        // Setup user credential with EAP-TTLS.
-        cred.userCredential = new Credential.UserCredential();
-        cred.userCredential.username = "username";
-        cred.userCredential.password = "password";
-        cred.userCredential.eapType = EAPConstants.EAP_TTLS;
-        cred.userCredential.nonEapInnerMethod = "MS-CHAP";
-        cred.caCertificate = FakeKeys.CA_CERT0;
+        Credential cred = createCredentialWithUserCredential();
         // Setup SIM credential.
-        cred.simCredential = new Credential.SimCredential();
-        cred.simCredential.imsi = "1234*";
-        cred.simCredential.eapType = EAPConstants.EAP_SIM;
+        Credential.SimCredential simCredential = new Credential.SimCredential();
+        simCredential.setImsi("1234*");
+        simCredential.setEapType(EAPConstants.EAP_SIM);
+        cred.setSimCredential(simCredential);
         assertFalse(cred.validate());
     }
 
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
index 45fdbea..92e94ee 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
@@ -55,14 +55,14 @@
      */
     private static HomeSP createHomeSp(Map<String, Long> homeNetworkIds) {
         HomeSP homeSp = new HomeSP();
-        homeSp.fqdn = "fqdn";
-        homeSp.friendlyName = "friendly name";
-        homeSp.iconUrl = "icon.url";
-        homeSp.homeNetworkIds = homeNetworkIds;
-        homeSp.matchAllOIs = new long[] {0x11L, 0x22L};
-        homeSp.matchAnyOIs = new long[] {0x33L, 0x44L};
-        homeSp.otherHomePartners = new String[] {"partner1", "partner2"};
-        homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
+        homeSp.setFqdn("fqdn");
+        homeSp.setFriendlyName("friendly name");
+        homeSp.setIconUrl("icon.url");
+        homeSp.setHomeNetworkIds(homeNetworkIds);
+        homeSp.setMatchAllOIs(new long[] {0x11L, 0x22L});
+        homeSp.setMatchAnyOIs(new long[] {0x33L, 0x44L});
+        homeSp.setOtherHomePartners(new String[] {"partner1", "partner2"});
+        homeSp.setRoamingConsortiumOIs(new long[] {0x55, 0x66});
         return homeSp;
     }
 
@@ -136,9 +136,7 @@
      */
     @Test
     public void validateValidHomeSP() throws Exception {
-        HomeSP homeSp = new HomeSP();
-        homeSp.fqdn = "fqdn";
-        homeSp.friendlyName = "friendly name";
+        HomeSP homeSp = createHomeSpWithHomeNetworkIds();
         assertTrue(homeSp.validate());
     }
 
@@ -149,8 +147,8 @@
      */
     @Test
     public void validateHomeSpWithoutFqdn() throws Exception {
-        HomeSP homeSp = new HomeSP();
-        homeSp.friendlyName = "friendly name";
+        HomeSP homeSp = createHomeSpWithHomeNetworkIds();
+        homeSp.setFqdn(null);
         assertFalse(homeSp.validate());
     }
 
@@ -161,36 +159,9 @@
      */
     @Test
     public void validateHomeSpWithoutFriendlyName() throws Exception {
-        HomeSP homeSp = new HomeSP();
-        homeSp.fqdn = "fqdn";
-        assertFalse(homeSp.validate());
-    }
-
-    /**
-     * Verify that a HomeSP is valid when the optional Roaming Consortium OIs are
-     * provided.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void validateHomeSpWithRoamingConsoritums() throws Exception {
-        HomeSP homeSp = new HomeSP();
-        homeSp.fqdn = "fqdn";
-        homeSp.friendlyName = "friendly name";
-        homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
-        assertTrue(homeSp.validate());
-    }
-
-    /**
-     * Verify that a HomeSP is valid when the optional Home Network IDs are
-     * provided.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void validateHomeSpWithHomeNetworkIds() throws Exception {
         HomeSP homeSp = createHomeSpWithHomeNetworkIds();
-        assertTrue(homeSp.validate());
+        homeSp.setFriendlyName(null);
+        assertFalse(homeSp.validate());
     }
 
     /**
@@ -213,14 +184,14 @@
      */
     @Test
     public void validateHomeSpWithInvalidHomeNetworkIds() throws Exception {
-        HomeSP homeSp = new HomeSP();
-        homeSp.fqdn = "fqdn";
-        homeSp.friendlyName = "friendly name";
-        homeSp.homeNetworkIds = new HashMap<>();
+        HomeSP homeSp = createHomeSpWithoutHomeNetworkIds();
+        // HomeNetworkID with SSID exceeding the maximum length.
+        Map<String, Long> homeNetworkIds = new HashMap<>();
         byte[] rawSsidBytes = new byte[33];
         Arrays.fill(rawSsidBytes, (byte) 'a');
-        homeSp.homeNetworkIds.put(
+        homeNetworkIds.put(
                 StringFactory.newStringFromBytes(rawSsidBytes, StandardCharsets.UTF_8), 0x1234L);
+        homeSp.setHomeNetworkIds(homeNetworkIds);
         assertFalse(homeSp.validate());
     }
 
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
index c371c49..2a36764 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
@@ -30,6 +30,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -48,40 +49,43 @@
      */
     private static Policy createPolicy() {
         Policy policy = new Policy();
-        policy.minHomeDownlinkBandwidth = 123;
-        policy.minHomeUplinkBandwidth = 345;
-        policy.minRoamingDownlinkBandwidth = 567;
-        policy.minRoamingUplinkBandwidth = 789;
-        policy.excludedSsidList = new String[] {"ssid1", "ssid2"};
-        policy.requiredProtoPortMap = new HashMap<>();
-        policy.requiredProtoPortMap.put(12, "23,342,123");
-        policy.requiredProtoPortMap.put(23, "789,372,1235");
-        policy.maximumBssLoadValue = 12;
+        policy.setMinHomeDownlinkBandwidth(123);
+        policy.setMinHomeUplinkBandwidth(345);
+        policy.setMinRoamingDownlinkBandwidth(567);
+        policy.setMinRoamingUplinkBandwidth(789);
+        policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"});
+        Map<Integer, String> requiredProtoPortMap = new HashMap<>();
+        requiredProtoPortMap.put(12, "23,342,123");
+        requiredProtoPortMap.put(23, "789,372,1235");
+        policy.setRequiredProtoPortMap(requiredProtoPortMap);
+        policy.setMaximumBssLoadValue(12);
 
-        policy.preferredRoamingPartnerList = new ArrayList<>();
+        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
         Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
-        partner1.fqdn = "partner1.com";
-        partner1.fqdnExactMatch = true;
-        partner1.priority = 12;
-        partner1.countries = "us,jp";
+        partner1.setFqdn("partner1.com");
+        partner1.setFqdnExactMatch(true);
+        partner1.setPriority(12);
+        partner1.setCountries("us,jp");
         Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
-        partner2.fqdn = "partner2.com";
-        partner2.fqdnExactMatch = false;
-        partner2.priority = 42;
-        partner2.countries = "ca,fr";
-        policy.preferredRoamingPartnerList.add(partner1);
-        policy.preferredRoamingPartnerList.add(partner2);
+        partner2.setFqdn("partner2.com");
+        partner2.setFqdnExactMatch(false);
+        partner2.setPriority(42);
+        partner2.setCountries("ca,fr");
+        preferredRoamingPartnerList.add(partner1);
+        preferredRoamingPartnerList.add(partner2);
+        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
 
-        policy.policyUpdate = new UpdateParameter();
-        policy.policyUpdate.updateIntervalInMinutes = 1712;
-        policy.policyUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
-        policy.policyUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
-        policy.policyUpdate.serverUri = "policy.update.com";
-        policy.policyUpdate.username = "username";
-        policy.policyUpdate.base64EncodedPassword =
-                Base64.encodeToString("password".getBytes(), Base64.DEFAULT);
-        policy.policyUpdate.trustRootCertUrl = "trust.cert.com";
-        policy.policyUpdate.trustRootCertSha256Fingerprint = new byte[32];
+        UpdateParameter policyUpdate = new UpdateParameter();
+        policyUpdate.setUpdateIntervalInMinutes(1712);
+        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
+        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
+        policyUpdate.setServerUri("policy.update.com");
+        policyUpdate.setUsername("username");
+        policyUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
+        policyUpdate.setTrustRootCertUrl("trust.cert.com");
+        policyUpdate.setTrustRootCertSha256Fingerprint(new byte[32]);
+        policy.setPolicyUpdate(policyUpdate);
 
         return policy;
     }
@@ -128,7 +132,7 @@
     @Test
     public void verifyParcelWithoutProtoPortMap() throws Exception {
         Policy policy = createPolicy();
-        policy.requiredProtoPortMap = null;
+        policy.setRequiredProtoPortMap(null);
         verifyParcel(policy);
     }
 
@@ -140,7 +144,7 @@
     @Test
     public void verifyParcelWithoutPreferredRoamingPartnerList() throws Exception {
         Policy policy = createPolicy();
-        policy.preferredRoamingPartnerList = null;
+        policy.setPreferredRoamingPartnerList(null);
         verifyParcel(policy);
     }
 
@@ -152,7 +156,7 @@
     @Test
     public void verifyParcelWithoutPolicyUpdate() throws Exception {
         Policy policy = createPolicy();
-        policy.policyUpdate = null;
+        policy.setPolicyUpdate(null);
         verifyParcel(policy);
     }
 
@@ -212,7 +216,7 @@
     @Test
     public void validatePolicyWithoutPolicyUpdate() throws Exception {
         Policy policy = createPolicy();
-        policy.policyUpdate = null;
+        policy.setPolicyUpdate(null);
         assertFalse(policy.validate());
     }
 
@@ -224,7 +228,7 @@
     @Test
     public void validatePolicyWithInvalidPolicyUpdate() throws Exception {
         Policy policy = createPolicy();
-        policy.policyUpdate = new UpdateParameter();
+        policy.setPolicyUpdate(new UpdateParameter());
         assertFalse(policy.validate());
     }
 
@@ -237,10 +241,10 @@
     public void validatePolicyWithRoamingPartnerWithoutFQDN() throws Exception {
         Policy policy = createPolicy();
         Policy.RoamingPartner partner = new Policy.RoamingPartner();
-        partner.fqdnExactMatch = true;
-        partner.priority = 12;
-        partner.countries = "us,jp";
-        policy.preferredRoamingPartnerList.add(partner);
+        partner.setFqdnExactMatch(true);
+        partner.setPriority(12);
+        partner.setCountries("us,jp");
+        policy.getPreferredRoamingPartnerList().add(partner);
         assertFalse(policy.validate());
     }
 
@@ -254,10 +258,10 @@
     public void validatePolicyWithRoamingPartnerWithoutCountries() throws Exception {
         Policy policy = createPolicy();
         Policy.RoamingPartner partner = new Policy.RoamingPartner();
-        partner.fqdn = "test.com";
-        partner.fqdnExactMatch = true;
-        partner.priority = 12;
-        policy.preferredRoamingPartnerList.add(partner);
+        partner.setFqdn("test.com");
+        partner.setFqdnExactMatch(true);
+        partner.setPriority(12);
+        policy.getPreferredRoamingPartnerList().add(partner);
         assertFalse(policy.validate());
     }
 
@@ -271,7 +275,8 @@
     public void validatePolicyWithInvalidPortStringInProtoPortMap() throws Exception {
         Policy policy = createPolicy();
         byte[] rawPortBytes = new byte[MAX_PORT_STRING_BYTES + 1];
-        policy.requiredProtoPortMap.put(324, new String(rawPortBytes, StandardCharsets.UTF_8));
+        policy.getRequiredProtoPortMap().put(
+                324, new String(rawPortBytes, StandardCharsets.UTF_8));
         assertFalse(policy.validate());
     }
 
@@ -283,8 +288,9 @@
     @Test
     public void validatePolicyWithSsidExclusionListSizeExceededMax() throws Exception {
         Policy policy = createPolicy();
-        policy.excludedSsidList = new String[MAX_NUMBER_OF_EXCLUDED_SSIDS + 1];
-        Arrays.fill(policy.excludedSsidList, "ssid");
+        String[] excludedSsidList = new String[MAX_NUMBER_OF_EXCLUDED_SSIDS + 1];
+        Arrays.fill(excludedSsidList, "ssid");
+        policy.setExcludedSsidList(excludedSsidList);
         assertFalse(policy.validate());
     }
 
@@ -298,7 +304,9 @@
         Policy policy = createPolicy();
         byte[] rawSsidBytes = new byte[MAX_SSID_BYTES + 1];
         Arrays.fill(rawSsidBytes, (byte) 'a');
-        policy.excludedSsidList = new String[] {new String(rawSsidBytes, StandardCharsets.UTF_8)};
+        String[] excludedSsidList = new String[] {
+                new String(rawSsidBytes, StandardCharsets.UTF_8)};
+        policy.setExcludedSsidList(excludedSsidList);
         assertFalse(policy.validate());
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
index 6bf0db1b..551ed43 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
@@ -50,15 +50,15 @@
      */
     private static UpdateParameter createUpdateParameter() {
         UpdateParameter updateParam = new UpdateParameter();
-        updateParam.updateIntervalInMinutes = 1712;
-        updateParam.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
-        updateParam.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
-        updateParam.serverUri = "server.pdate.com";
-        updateParam.username = "username";
-        updateParam.base64EncodedPassword =
-                Base64.encodeToString("password".getBytes(), Base64.DEFAULT);
-        updateParam.trustRootCertUrl = "trust.cert.com";
-        updateParam.trustRootCertSha256Fingerprint = new byte[32];
+        updateParam.setUpdateIntervalInMinutes(1712);
+        updateParam.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
+        updateParam.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
+        updateParam.setServerUri("server.pdate.com");
+        updateParam.setUsername("username");
+        updateParam.setBase64EncodedPassword(
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
+        updateParam.setTrustRootCertUrl("trust.cert.com");
+        updateParam.setTrustRootCertSha256Fingerprint(new byte[32]);
         return updateParam;
     }
 
@@ -152,7 +152,7 @@
     @Test
     public void validateUpdateParameterWithUnknowMethod() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.updateMethod = "adsfasd";
+        updateParam.setUpdateMethod("adsfasd");
         assertFalse(updateParam.validate());
     }
 
@@ -164,7 +164,7 @@
     @Test
     public void validateUpdateParameterWithUnknowRestriction() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.restriction = "adsfasd";
+        updateParam.setRestriction("adsfasd");
         assertFalse(updateParam.validate());
     }
 
@@ -178,7 +178,7 @@
         UpdateParameter updateParam = createUpdateParameter();
         byte[] rawUsernameBytes = new byte[MAX_USERNAME_BYTES + 1];
         Arrays.fill(rawUsernameBytes, (byte) 'a');
-        updateParam.username = new String(rawUsernameBytes, StandardCharsets.UTF_8);
+        updateParam.setUsername(new String(rawUsernameBytes, StandardCharsets.UTF_8));
         assertFalse(updateParam.validate());
     }
 
@@ -190,7 +190,7 @@
     @Test
     public void validateUpdateParameterWithEmptyUsername() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.username = null;
+        updateParam.setUsername(null);
         assertFalse(updateParam.validate());
     }
 
@@ -204,7 +204,7 @@
         UpdateParameter updateParam = createUpdateParameter();
         byte[] rawPasswordBytes = new byte[MAX_PASSWORD_BYTES + 1];
         Arrays.fill(rawPasswordBytes, (byte) 'a');
-        updateParam.base64EncodedPassword = new String(rawPasswordBytes, StandardCharsets.UTF_8);
+        updateParam.setBase64EncodedPassword(new String(rawPasswordBytes, StandardCharsets.UTF_8));
         assertFalse(updateParam.validate());
     }
 
@@ -216,7 +216,7 @@
     @Test
     public void validateUpdateParameterWithEmptyPassword() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.base64EncodedPassword = null;
+        updateParam.setBase64EncodedPassword(null);
         assertFalse(updateParam.validate());
     }
 
@@ -229,7 +229,7 @@
     @Test
     public void validateUpdateParameterWithPasswordContainedInvalidPadding() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.base64EncodedPassword = updateParam.base64EncodedPassword + "=";
+        updateParam.setBase64EncodedPassword(updateParam.getBase64EncodedPassword() + "=");
         assertFalse(updateParam.validate());
     }
 
@@ -241,7 +241,7 @@
     @Test
     public void validateUpdateParameterWithoutTrustRootCertUrl() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.trustRootCertUrl = null;
+        updateParam.setTrustRootCertUrl(null);
         assertFalse(updateParam.validate());
     }
 
@@ -255,7 +255,7 @@
         UpdateParameter updateParam = createUpdateParameter();
         byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1];
         Arrays.fill(rawUrlBytes, (byte) 'a');
-        updateParam.trustRootCertUrl = new String(rawUrlBytes, StandardCharsets.UTF_8);
+        updateParam.setTrustRootCertUrl(new String(rawUrlBytes, StandardCharsets.UTF_8));
         assertFalse(updateParam.validate());
     }
 
@@ -268,7 +268,7 @@
     @Test
     public void validateUpdateParameterWithouttrustRootCertSha256Fingerprint() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.trustRootCertSha256Fingerprint = null;
+        updateParam.setTrustRootCertSha256Fingerprint(null);
         assertFalse(updateParam.validate());
     }
 
@@ -281,10 +281,10 @@
     @Test
     public void validateUpdateParameterWithInvalidtrustRootCertSha256Fingerprint() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.trustRootCertSha256Fingerprint = new byte[CERTIFICATE_SHA256_BYTES + 1];
+        updateParam.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_SHA256_BYTES + 1]);
         assertFalse(updateParam.validate());
 
-        updateParam.trustRootCertSha256Fingerprint = new byte[CERTIFICATE_SHA256_BYTES - 1];
+        updateParam.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_SHA256_BYTES - 1]);
         assertFalse(updateParam.validate());
     }
 
@@ -296,7 +296,7 @@
     @Test
     public void validateUpdateParameterWithoutServerUri() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.serverUri = null;
+        updateParam.setServerUri(null);
         assertFalse(updateParam.validate());
     }
 
@@ -310,7 +310,7 @@
         UpdateParameter updateParam = createUpdateParameter();
         byte[] rawUriBytes = new byte[MAX_URI_BYTES + 1];
         Arrays.fill(rawUriBytes, (byte) 'a');
-        updateParam.serverUri = new String(rawUriBytes, StandardCharsets.UTF_8);
+        updateParam.setServerUri(new String(rawUriBytes, StandardCharsets.UTF_8));
         assertFalse(updateParam.validate());
     }
 
@@ -323,14 +323,14 @@
     @Test
     public void validateUpdateParameterWithNoServerCheck() throws Exception {
         UpdateParameter updateParam = new UpdateParameter();
-        updateParam.updateIntervalInMinutes = UpdateParameter.UPDATE_CHECK_INTERVAL_NEVER;
-        updateParam.username = null;
-        updateParam.base64EncodedPassword = null;
-        updateParam.updateMethod = null;
-        updateParam.restriction = null;
-        updateParam.serverUri = null;
-        updateParam.trustRootCertUrl = null;
-        updateParam.trustRootCertSha256Fingerprint = null;
+        updateParam.setUpdateIntervalInMinutes(UpdateParameter.UPDATE_CHECK_INTERVAL_NEVER);
+        updateParam.setUsername(null);
+        updateParam.setBase64EncodedPassword(null);
+        updateParam.setUpdateMethod(null);
+        updateParam.setRestriction(null);
+        updateParam.setServerUri(null);
+        updateParam.setTrustRootCertUrl(null);
+        updateParam.setTrustRootCertSha256Fingerprint(null);
         assertTrue(updateParam.validate());
     }
 
@@ -342,7 +342,7 @@
     @Test
     public void validateUpdateParameterWithoutUpdateInterval() throws Exception {
         UpdateParameter updateParam = createUpdateParameter();
-        updateParam.updateIntervalInMinutes = Long.MIN_VALUE;
+        updateParam.setUpdateIntervalInMinutes(Long.MIN_VALUE);
         assertFalse(updateParam.validate());
     }
 }