Merge "Handle NPE from BluetoothRouteProvider"
diff --git a/Android.bp b/Android.bp
index ceb35bd..b0a1f93 100644
--- a/Android.bp
+++ b/Android.bp
@@ -314,6 +314,7 @@
         "tv_tuner_resource_manager_aidl_interface-java",
         "soundtrigger_middleware-aidl-java",
         "modules-utils-preconditions",
+        "modules-utils-statemachine",
         "modules-utils-synchronous-result-receiver",
         "modules-utils-os",
         "framework-permission-aidl-java",
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index d18154a..de84792 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -14,7 +14,6 @@
 
 gensrcs {
     name: "framework-javastream-protos",
-    depfile: true,
 
     tools: [
         "aprotoc",
@@ -22,10 +21,13 @@
         "soong_zip",
     ],
 
+    tool_files: [
+        ":libprotobuf-internal-protos",
+    ],
+
     cmd: "mkdir -p $(genDir)/$(in) " +
         "&& $(location aprotoc) " +
         "  --plugin=$(location protoc-gen-javastream) " +
-        "  --dependency_out=$(depfile) " +
         "  --javastream_out=$(genDir)/$(in) " +
         "  -Iexternal/protobuf/src " +
         "  -I . " +
@@ -47,17 +49,19 @@
 
 gensrcs {
     name: "framework-cppstream-protos",
-    depfile: true,
 
     tools: [
         "aprotoc",
         "protoc-gen-cppstream",
     ],
 
+    tool_files: [
+        ":libprotobuf-internal-protos",
+    ],
+
     cmd: "mkdir -p $(genDir) " +
         "&& $(location aprotoc) " +
         "  --plugin=$(location protoc-gen-cppstream) " +
-        "  --dependency_out=$(depfile) " +
         "  --cppstream_out=$(genDir) " +
         "  -Iexternal/protobuf/src " +
         "  -I . " +
diff --git a/boot/hiddenapi/hiddenapi-max-target-q.txt b/boot/hiddenapi/hiddenapi-max-target-q.txt
index 4832dd1..fdda4ea 100644
--- a/boot/hiddenapi/hiddenapi-max-target-q.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-q.txt
@@ -404,16 +404,11 @@
 Lcom/android/internal/R$string;->byteShort:I
 Lcom/android/internal/R$string;->cancel:I
 Lcom/android/internal/R$string;->enable_explore_by_touch_warning_title:I
-Lcom/android/internal/R$string;->gigabyteShort:I
-Lcom/android/internal/R$string;->kilobyteShort:I
-Lcom/android/internal/R$string;->megabyteShort:I
 Lcom/android/internal/R$string;->notification_title:I
 Lcom/android/internal/R$string;->no_matches:I
 Lcom/android/internal/R$string;->ok:I
-Lcom/android/internal/R$string;->petabyteShort:I
 Lcom/android/internal/R$string;->redo:I
 Lcom/android/internal/R$string;->share:I
-Lcom/android/internal/R$string;->terabyteShort:I
 Lcom/android/internal/R$string;->whichApplication:I
 Lcom/android/internal/R$style;->Animation_DropDownDown:I
 Lcom/android/internal/R$style;->Animation_DropDownUp:I
diff --git a/core/api/current.txt b/core/api/current.txt
index 2e0e6e57..dc19496 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -30355,6 +30355,7 @@
     method public <T extends android.os.Parcelable> void writeTypedArray(@Nullable T[], int);
     method public <T extends android.os.Parcelable> void writeTypedArrayMap(@Nullable android.util.ArrayMap<java.lang.String,T>, int);
     method public <T extends android.os.Parcelable> void writeTypedList(@Nullable java.util.List<T>);
+    method public <T extends android.os.Parcelable> void writeTypedList(@Nullable java.util.List<T>, int);
     method public <T extends android.os.Parcelable> void writeTypedObject(@Nullable T, int);
     method public <T extends android.os.Parcelable> void writeTypedSparseArray(@Nullable android.util.SparseArray<T>, int);
     method public void writeValue(@Nullable Object);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 8081c15..a643c29 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -381,27 +381,6 @@
     ],
 }
 
-java_library {
-    name: "modules-utils-statemachine",
-    srcs: [
-        "com/android/internal/util/IState.java",
-        "com/android/internal/util/State.java",
-        "com/android/internal/util/StateMachine.java",
-    ],
-    libs: [
-        "framework-annotations-lib",
-        "unsupportedappusage",
-    ],
-    sdk_version: "module_current",
-    min_sdk_version: "29",
-
-    visibility: ["//visibility:public"],
-    apex_available: [
-        "//apex_available:anyapex",
-        "//apex_available:platform",
-    ],
-}
-
 filegroup {
     name: "framework-ims-common-shared-srcs",
     srcs: [
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8bbfd8d..b601420 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -244,6 +244,7 @@
 import java.util.Objects;
 import java.util.TimeZone;
 import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 
 /**
@@ -345,11 +346,9 @@
      */
     @UnsupportedAppUsage
     final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
-    /**
-     * Maps from activity token to local record of the activities that are preparing to be launched.
-     */
-    final Map<IBinder, ActivityClientRecord> mLaunchingActivities =
-            Collections.synchronizedMap(new ArrayMap<IBinder, ActivityClientRecord>());
+    /** Maps from activity token to the pending override configuration. */
+    @GuardedBy("mPendingOverrideConfigs")
+    private final ArrayMap<IBinder, Configuration> mPendingOverrideConfigs = new ArrayMap<>();
     /** The activities to be truly destroyed (not include relaunch). */
     final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed =
             Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>());
@@ -359,6 +358,7 @@
     // Number of activities that are currently visible on-screen.
     @UnsupportedAppUsage
     int mNumVisibleActivities = 0;
+    private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
     @GuardedBy("mAppThread")
     private int mLastProcessState = PROCESS_STATE_UNKNOWN;
     @GuardedBy("mAppThread")
@@ -556,10 +556,6 @@
         boolean hideForNow;
         Configuration createdConfig;
         Configuration overrideConfig;
-        // Used to save the last reported configuration from server side so that activity
-        // configuration transactions can always use the latest configuration.
-        @GuardedBy("this")
-        private Configuration mPendingOverrideConfig;
         // Used for consolidating configs before sending on to Activity.
         private Configuration tmpConfig = new Configuration();
         // Callback used for updating activity override config.
@@ -3330,21 +3326,6 @@
     }
 
     @Override
-    public void addLaunchingActivity(IBinder token, ActivityClientRecord activity) {
-        mLaunchingActivities.put(token, activity);
-    }
-
-    @Override
-    public ActivityClientRecord getLaunchingActivity(IBinder token) {
-        return mLaunchingActivities.get(token);
-    }
-
-    @Override
-    public void removeLaunchingActivity(IBinder token) {
-        mLaunchingActivities.remove(token);
-    }
-
-    @Override
     public ActivityClientRecord getActivityClient(IBinder token) {
         return mActivities.get(token);
     }
@@ -3388,7 +3369,7 @@
             // Defer the top state for VM to avoid aggressive JIT compilation affecting activity
             // launch time.
             if (processState == ActivityManager.PROCESS_STATE_TOP
-                    && !mLaunchingActivities.isEmpty()) {
+                    && mNumLaunchingActivities.get() > 0) {
                 mPendingProcessState = processState;
                 mH.postDelayed(this::applyPendingProcessState, PENDING_TOP_PROCESS_STATE_TIMEOUT);
             } else {
@@ -3404,7 +3385,7 @@
         // Handle the pending configuration if the process state is changed from cached to
         // non-cached. Except the case where there is a launching activity because the
         // LaunchActivityItem will handle it.
-        if (wasCached && !isCachedProcessState() && mLaunchingActivities.isEmpty()) {
+        if (wasCached && !isCachedProcessState() && mNumLaunchingActivities.get() == 0) {
             final Configuration pendingConfig =
                     mConfigurationController.getPendingConfiguration(false /* clearPending */);
             if (pendingConfig == null) {
@@ -3442,6 +3423,11 @@
         }
     }
 
+    @Override
+    public void countLaunchingActivities(int num) {
+        mNumLaunchingActivities.getAndAdd(num);
+    }
+
     @UnsupportedAppUsage
     public final void sendActivityResult(
             IBinder token, String id, int requestCode,
@@ -6071,31 +6057,31 @@
     }
 
     /**
-     * Sets the supplied {@code overrideConfig} as pending for the {@code activityToken}. Calling
+     * Sets the supplied {@code overrideConfig} as pending for the {@code token}. Calling
      * this method prevents any calls to
      * {@link #handleActivityConfigurationChanged(ActivityClientRecord, Configuration, int)} from
      * processing any configurations older than {@code overrideConfig}.
      */
     @Override
-    public void updatePendingActivityConfiguration(ActivityClientRecord r,
-            Configuration overrideConfig) {
-        synchronized (r) {
-            if (r.mPendingOverrideConfig != null
-                    && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
+    public void updatePendingActivityConfiguration(IBinder token, Configuration overrideConfig) {
+        synchronized (mPendingOverrideConfigs) {
+            final Configuration pendingOverrideConfig = mPendingOverrideConfigs.get(token);
+            if (pendingOverrideConfig != null
+                    && !pendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
                 if (DEBUG_CONFIGURATION) {
-                    Slog.v(TAG, "Activity has newer configuration pending so drop this"
-                            + " transaction. overrideConfig=" + overrideConfig
-                            + " r.mPendingOverrideConfig=" + r.mPendingOverrideConfig);
+                    Slog.v(TAG, "Activity has newer configuration pending so this transaction will"
+                            + " be dropped. overrideConfig=" + overrideConfig
+                            + " pendingOverrideConfig=" + pendingOverrideConfig);
                 }
                 return;
             }
-            r.mPendingOverrideConfig = overrideConfig;
+            mPendingOverrideConfigs.put(token, overrideConfig);
         }
     }
 
     /**
      * Handle new activity configuration and/or move to a different display. This method is a noop
-     * if {@link #updatePendingActivityConfiguration(ActivityClientRecord, Configuration)} has been
+     * if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been
      * called with a newer config than {@code overrideConfig}.
      *
      * @param r Target activity record.
@@ -6106,16 +6092,17 @@
     @Override
     public void handleActivityConfigurationChanged(ActivityClientRecord r,
             @NonNull Configuration overrideConfig, int displayId) {
-        synchronized (r) {
-            if (overrideConfig.isOtherSeqNewer(r.mPendingOverrideConfig)) {
+        synchronized (mPendingOverrideConfigs) {
+            final Configuration pendingOverrideConfig = mPendingOverrideConfigs.get(r.token);
+            if (overrideConfig.isOtherSeqNewer(pendingOverrideConfig)) {
                 if (DEBUG_CONFIGURATION) {
                     Slog.v(TAG, "Activity has newer configuration pending so drop this"
                             + " transaction. overrideConfig=" + overrideConfig
-                            + " r.mPendingOverrideConfig=" + r.mPendingOverrideConfig);
+                            + " pendingOverrideConfig=" + pendingOverrideConfig);
                 }
                 return;
             }
-            r.mPendingOverrideConfig = null;
+            mPendingOverrideConfigs.remove(r.token);
         }
 
         if (displayId == INVALID_DISPLAY) {
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index c743f65..d365269 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -83,6 +83,9 @@
     /** Set current process state. */
     public abstract void updateProcessState(int processState, boolean fromIpc);
 
+    /** Count how many activities are launching. */
+    public abstract void countLaunchingActivities(int num);
+
     // Execute phase related logic and handlers. Methods here execute actual lifecycle transactions
     // and deliver callbacks.
 
@@ -139,7 +142,7 @@
     public abstract void performRestartActivity(@NonNull ActivityClientRecord r, boolean start);
 
     /** Set pending activity configuration in case it will be updated by other transaction item. */
-    public abstract void updatePendingActivityConfiguration(@NonNull ActivityClientRecord r,
+    public abstract void updatePendingActivityConfiguration(@NonNull IBinder token,
             Configuration overrideConfig);
 
     /** Deliver activity (override) configuration change. */
@@ -189,26 +192,6 @@
             FixedRotationAdjustments fixedRotationAdjustments);
 
     /**
-     * Add {@link ActivityClientRecord} that is preparing to be launched.
-     * @param token Activity token.
-     * @param activity An initialized instance of {@link ActivityClientRecord} to use during launch.
-     */
-    public abstract void addLaunchingActivity(IBinder token, ActivityClientRecord activity);
-
-    /**
-     * Get {@link ActivityClientRecord} that is preparing to be launched.
-     * @param token Activity token.
-     * @return An initialized instance of {@link ActivityClientRecord} to use during launch.
-     */
-    public abstract ActivityClientRecord getLaunchingActivity(IBinder token);
-
-    /**
-     * Remove {@link ActivityClientRecord} from the launching activity list.
-     * @param token Activity token.
-     */
-    public abstract void removeLaunchingActivity(IBinder token);
-
-    /**
      * Get {@link android.app.ActivityThread.ActivityClientRecord} instance that corresponds to the
      * provided token.
      */
diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
index 032b57e..5a3ad31 100644
--- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
@@ -40,11 +40,9 @@
 
     @Override
     public void preExecute(android.app.ClientTransactionHandler client, IBinder token) {
-        final ActivityClientRecord r = getActivityClientRecord(client, token,
-                true /* includeLaunching */);
         // Notify the client of an upcoming change in the token configuration. This ensures that
         // batches of config change items only process the newest configuration.
-        client.updatePendingActivityConfiguration(r, mConfiguration);
+        client.updatePendingActivityConfiguration(token, mConfiguration);
     }
 
     @Override
diff --git a/core/java/android/app/servertransaction/ActivityTransactionItem.java b/core/java/android/app/servertransaction/ActivityTransactionItem.java
index 186f25d..6a6d76d 100644
--- a/core/java/android/app/servertransaction/ActivityTransactionItem.java
+++ b/core/java/android/app/servertransaction/ActivityTransactionItem.java
@@ -53,43 +53,23 @@
     public abstract void execute(@NonNull ClientTransactionHandler client,
             @NonNull ActivityClientRecord r, PendingTransactionActions pendingActions);
 
-    @NonNull ActivityClientRecord getActivityClientRecord(
-            @NonNull ClientTransactionHandler client, IBinder token) {
-        return getActivityClientRecord(client, token, false /* includeLaunching */);
-    }
-
     /**
      * Gets the {@link ActivityClientRecord} instance that corresponds to the provided token.
      * @param client Target client handler.
      * @param token Target activity token.
-     * @param includeLaunching Indicate to find the {@link ActivityClientRecord} in launching
-     *                         activity list.
-     *                         <p>Note that there is no {@link android.app.Activity} instance in
-     *                         {@link ActivityClientRecord} from the launching activity list.
      * @return The {@link ActivityClientRecord} instance that corresponds to the provided token.
      */
     @NonNull ActivityClientRecord getActivityClientRecord(
-            @NonNull ClientTransactionHandler client, IBinder token, boolean includeLaunching) {
-        ActivityClientRecord r = null;
-        // Check launching Activity first to prevent race condition that activity instance has not
-        // yet set to ActivityClientRecord.
-        if (includeLaunching) {
-            r = client.getLaunchingActivity(token);
-        }
-        // Then if we don't want to find launching Activity or the ActivityClientRecord doesn't
-        // exist in launching Activity list. The ActivityClientRecord should have been initialized
-        // and put in the Activity list.
-        if (r == null) {
-            r = client.getActivityClient(token);
-            if (r != null && client.getActivity(token) == null) {
-                throw new IllegalArgumentException("Activity must not be null to execute "
-                        + "transaction item");
-            }
-        }
+            @NonNull ClientTransactionHandler client, IBinder token) {
+        final ActivityClientRecord r = client.getActivityClient(token);
         if (r == null) {
             throw new IllegalArgumentException("Activity client record must not be null to execute "
                     + "transaction item");
         }
+        if (client.getActivity(token) == null) {
+            throw new IllegalArgumentException("Activity must not be null to execute "
+                    + "transaction item");
+        }
         return r;
     }
 }
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 34e4fcd..e281a02 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -82,12 +82,7 @@
 
     @Override
     public void preExecute(ClientTransactionHandler client, IBinder token) {
-        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
-                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
-                mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
-                client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
-                mLaunchedFromBubble);
-        client.addLaunchingActivity(token, r);
+        client.countLaunchingActivities(1);
         client.updateProcessState(mProcState, false);
         client.updatePendingConfiguration(mCurConfig);
         if (mActivityClientController != null) {
@@ -99,7 +94,11 @@
     public void execute(ClientTransactionHandler client, IBinder token,
             PendingTransactionActions pendingActions) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
-        ActivityClientRecord r = client.getLaunchingActivity(token);
+        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
+                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
+                mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
+                client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
+                mLaunchedFromBubble);
         client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
@@ -107,7 +106,7 @@
     @Override
     public void postExecute(ClientTransactionHandler client, IBinder token,
             PendingTransactionActions pendingActions) {
-        client.removeLaunchingActivity(token);
+        client.countLaunchingActivities(-1);
     }
 
 
diff --git a/core/java/android/app/servertransaction/MoveToDisplayItem.java b/core/java/android/app/servertransaction/MoveToDisplayItem.java
index 4b8a347..2893ff2 100644
--- a/core/java/android/app/servertransaction/MoveToDisplayItem.java
+++ b/core/java/android/app/servertransaction/MoveToDisplayItem.java
@@ -40,11 +40,9 @@
 
     @Override
     public void preExecute(ClientTransactionHandler client, IBinder token) {
-        final ActivityClientRecord r = getActivityClientRecord(client, token,
-                true /* includeLaunching */);
         // Notify the client of an upcoming change in the token configuration. This ensures that
         // batches of config change items only process the newest configuration.
-        client.updatePendingActivityConfiguration(r, mConfiguration);
+        client.updatePendingActivityConfiguration(token, mConfiguration);
     }
 
     @Override
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index e5dab05..0418a4b 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -31,6 +31,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.Serializable;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Set;
 import java.util.function.BiFunction;
@@ -102,7 +103,7 @@
     /*
      * If mParcelledData is non-null, then mMap will be null and the
      * data are stored as a Parcel containing a Bundle.  When the data
-     * are unparcelled, mParcelledData willbe set to null.
+     * are unparcelled, mParcelledData will be set to null.
      */
     @UnsupportedAppUsage
     volatile Parcel mParcelledData = null;
@@ -112,6 +113,19 @@
      */
     private boolean mParcelledByNative;
 
+    /*
+     * Flag indicating if mParcelledData is only referenced in this bundle.
+     * mParcelledData could be referenced by other bundles if mMap contains lazy values,
+     * and bundle data is copied to another bundle using putAll or the copy constructors.
+     */
+    boolean mOwnsLazyValues = true;
+
+    /*
+     * As mParcelledData is set to null when it is unparcelled, we keep a weak reference to
+     * it to aid in recycling it. Do not use this reference otherwise.
+     */
+    private WeakReference<Parcel> mWeakParcelledData = null;
+
     /**
      * The ClassLoader used when unparcelling data from mParcelledData.
      */
@@ -200,6 +214,9 @@
             mClassLoader = from.mClassLoader;
 
             if (from.mMap != null) {
+                mOwnsLazyValues = false;
+                from.mOwnsLazyValues = false;
+
                 if (!deep) {
                     mMap = new ArrayMap<>(from.mMap);
                 } else {
@@ -434,6 +451,9 @@
             mMap = map;
             if (recycleParcel) {
                 recycleParcel(parcelledData);
+                mWeakParcelledData = null;
+            } else {
+                mWeakParcelledData = new WeakReference<>(parcelledData);
             }
             mParcelledByNative = false;
             mParcelledData = null;
@@ -575,6 +595,10 @@
      */
     public void clear() {
         unparcel();
+        if (mOwnsLazyValues && mWeakParcelledData != null) {
+            recycleParcel(mWeakParcelledData.get());
+            mWeakParcelledData = null;
+        }
         mMap.clear();
     }
 
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index cf28c16..7e355d9 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -301,6 +301,8 @@
     public void putAll(Bundle bundle) {
         unparcel();
         bundle.unparcel();
+        mOwnsLazyValues = false;
+        bundle.mOwnsLazyValues = false;
         mMap.putAll(bundle.mMap);
 
         // FD state is now known if and only if both bundles already knew
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 5240522..6ed9982 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1998,7 +1998,20 @@
     }
 
     /**
-     * @hide
+     * Flatten a List containing a particular object type into the parcel, at
+     * the current dataPosition() and growing dataCapacity() if needed.  The
+     * type of the objects in the list must be one that implements Parcelable.
+     * Unlike the generic writeList() method, however, only the raw data of the
+     * objects is written and not their type, so you must use the corresponding
+     * readTypedList() to unmarshall them.
+     *
+     * @param val The list of objects to be written.
+     * @param parcelableFlags Contextual flags as per
+     * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}.
+     *
+     * @see #createTypedArrayList
+     * @see #readTypedList
+     * @see Parcelable
      */
     public <T extends Parcelable> void writeTypedList(@Nullable List<T> val, int parcelableFlags) {
         if (val == null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a2ff69e..d779b49 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1035,7 +1035,6 @@
             if (mView == null) {
                 mView = view;
 
-                mAttachInfo.mDisplayState = mDisplay.getState();
                 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
@@ -1229,6 +1228,9 @@
                 }
 
                 registerListeners();
+                // We should update mAttachInfo.mDisplayState after registerDisplayListener
+                // because displayState might be changed before registerDisplayListener.
+                mAttachInfo.mDisplayState = mDisplay.getState();
                 if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) {
                     mUseBLASTAdapter = true;
                 }
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 44c7f54..28b98d6 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -62,6 +62,8 @@
     private static IBinder mApplicationObject;
 
     private static volatile boolean mCrashing = false;
+    private static final String SYSPROP_CRASH_COUNT = "sys.system_server.crash_java";
+    private static int mCrashCount;
 
     private static volatile ApplicationWtfHandler sDefaultApplicationWtfHandler;
 
@@ -105,6 +107,8 @@
             // first clause in either of these two cases, only for system_server.
             if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) {
                 Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
+                mCrashCount = SystemProperties.getInt(SYSPROP_CRASH_COUNT, 0) + 1;
+                SystemProperties.set(SYSPROP_CRASH_COUNT, String.valueOf(mCrashCount));
             } else {
                 logUncaught(t.getName(), ActivityThread.currentProcessName(), Process.myPid(), e);
             }
diff --git a/core/java/com/android/internal/util/IState.java b/core/java/com/android/internal/util/IState.java
deleted file mode 100644
index 41b3d5e..0000000
--- a/core/java/com/android/internal/util/IState.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Copyright (C) 2011 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.internal.util;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Message;
-
-/**
- * {@hide}
- *
- * The interface for implementing states in a {@link StateMachine}
- */
-public interface IState {
-
-    /**
-     * Returned by processMessage to indicate the message was processed.
-     */
-    static final boolean HANDLED = true;
-
-    /**
-     * Returned by processMessage to indicate the message was NOT processed.
-     */
-    static final boolean NOT_HANDLED = false;
-
-    /**
-     * Called when a state is entered.
-     */
-    void enter();
-
-    /**
-     * Called when a state is exited.
-     */
-    void exit();
-
-    /**
-     * Called when a message is to be processed by the
-     * state machine.
-     *
-     * This routine is never reentered thus no synchronization
-     * is needed as only one processMessage method will ever be
-     * executing within a state machine at any given time. This
-     * does mean that processing by this routine must be completed
-     * as expeditiously as possible as no subsequent messages will
-     * be processed until this routine returns.
-     *
-     * @param msg to process
-     * @return HANDLED if processing has completed and NOT_HANDLED
-     *         if the message wasn't processed.
-     */
-    boolean processMessage(Message msg);
-
-    /**
-     * Name of State for debugging purposes.
-     *
-     * @return name of state.
-     */
-    @UnsupportedAppUsage
-    String getName();
-}
diff --git a/core/java/com/android/internal/util/State.java b/core/java/com/android/internal/util/State.java
deleted file mode 100644
index d5c0f60..0000000
--- a/core/java/com/android/internal/util/State.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Copyright (C) 2009 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.internal.util;
-
-import android.annotation.SuppressLint;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Message;
-
-/**
- * {@hide}
- *
- * The class for implementing states in a StateMachine
- */
-@SuppressLint("AndroidFrameworkRequiresPermission")
-public class State implements IState {
-
-    /**
-     * Constructor
-     */
-    @UnsupportedAppUsage
-    protected State() {
-    }
-
-    /* (non-Javadoc)
-     * @see com.android.internal.util.IState#enter()
-     */
-    @UnsupportedAppUsage
-    @Override
-    public void enter() {
-    }
-
-    /* (non-Javadoc)
-     * @see com.android.internal.util.IState#exit()
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @Override
-    public void exit() {
-    }
-
-    /* (non-Javadoc)
-     * @see com.android.internal.util.IState#processMessage(android.os.Message)
-     */
-    @UnsupportedAppUsage
-    @Override
-    public boolean processMessage(Message msg) {
-        return false;
-    }
-
-    /**
-     * Name of State for debugging purposes.
-     *
-     * This default implementation returns the class name, returning
-     * the instance name would better in cases where a State class
-     * is used for multiple states. But normally there is one class per
-     * state and the class name is sufficient and easy to get. You may
-     * want to provide a setName or some other mechanism for setting
-     * another name if the class name is not appropriate.
-     *
-     * @see com.android.internal.util.IState#processMessage(android.os.Message)
-     */
-    @UnsupportedAppUsage
-    @Override
-    public String getName() {
-        String name = getClass().getName();
-        int lastDollar = name.lastIndexOf('$');
-        return name.substring(lastDollar + 1);
-    }
-}
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
deleted file mode 100644
index cb8d9d1..0000000
--- a/core/java/com/android/internal/util/StateMachine.java
+++ /dev/null
@@ -1,2185 +0,0 @@
-/**
- * Copyright (C) 2009 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.internal.util;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Vector;
-
-/**
- * {@hide}
- *
- * <p>The state machine defined here is a hierarchical state machine which processes messages
- * and can have states arranged hierarchically.</p>
- *
- * <p>A state is a <code>State</code> object and must implement
- * <code>processMessage</code> and optionally <code>enter/exit/getName</code>.
- * The enter/exit methods are equivalent to the construction and destruction
- * in Object Oriented programming and are used to perform initialization and
- * cleanup of the state respectively. The <code>getName</code> method returns the
- * name of the state; the default implementation returns the class name. It may be
- * desirable to have <code>getName</code> return the state instance name instead,
- * in particular if a particular state class has multiple instances.</p>
- *
- * <p>When a state machine is created, <code>addState</code> is used to build the
- * hierarchy and <code>setInitialState</code> is used to identify which of these
- * is the initial state. After construction the programmer calls <code>start</code>
- * which initializes and starts the state machine. The first action the StateMachine
- * is to the invoke <code>enter</code> for all of the initial state's hierarchy,
- * starting at its eldest parent. The calls to enter will be done in the context
- * of the StateMachine's Handler, not in the context of the call to start, and they
- * will be invoked before any messages are processed. For example, given the simple
- * state machine below, mP1.enter will be invoked and then mS1.enter. Finally,
- * messages sent to the state machine will be processed by the current state;
- * in our simple state machine below that would initially be mS1.processMessage.</p>
-<pre>
-        mP1
-       /   \
-      mS2   mS1 ----&gt; initial state
-</pre>
- * <p>After the state machine is created and started, messages are sent to a state
- * machine using <code>sendMessage</code> and the messages are created using
- * <code>obtainMessage</code>. When the state machine receives a message the
- * current state's <code>processMessage</code> is invoked. In the above example
- * mS1.processMessage will be invoked first. The state may use <code>transitionTo</code>
- * to change the current state to a new state.</p>
- *
- * <p>Each state in the state machine may have a zero or one parent states. If
- * a child state is unable to handle a message it may have the message processed
- * by its parent by returning false or NOT_HANDLED. If a message is not handled by
- * a child state or any of its ancestors, <code>unhandledMessage</code> will be invoked
- * to give one last chance for the state machine to process the message.</p>
- *
- * <p>When all processing is completed a state machine may choose to call
- * <code>transitionToHaltingState</code>. When the current <code>processingMessage</code>
- * returns the state machine will transfer to an internal <code>HaltingState</code>
- * and invoke <code>halting</code>. Any message subsequently received by the state
- * machine will cause <code>haltedProcessMessage</code> to be invoked.</p>
- *
- * <p>If it is desirable to completely stop the state machine call <code>quit</code> or
- * <code>quitNow</code>. These will call <code>exit</code> of the current state and its parents,
- * call <code>onQuitting</code> and then exit Thread/Loopers.</p>
- *
- * <p>In addition to <code>processMessage</code> each <code>State</code> has
- * an <code>enter</code> method and <code>exit</code> method which may be overridden.</p>
- *
- * <p>Since the states are arranged in a hierarchy transitioning to a new state
- * causes current states to be exited and new states to be entered. To determine
- * the list of states to be entered/exited the common parent closest to
- * the current state is found. We then exit from the current state and its
- * parent's up to but not including the common parent state and then enter all
- * of the new states below the common parent down to the destination state.
- * If there is no common parent all states are exited and then the new states
- * are entered.</p>
- *
- * <p>Two other methods that states can use are <code>deferMessage</code> and
- * <code>sendMessageAtFrontOfQueue</code>. The <code>sendMessageAtFrontOfQueue</code> sends
- * a message but places it on the front of the queue rather than the back. The
- * <code>deferMessage</code> causes the message to be saved on a list until a
- * transition is made to a new state. At which time all of the deferred messages
- * will be put on the front of the state machine queue with the oldest message
- * at the front. These will then be processed by the new current state before
- * any other messages that are on the queue or might be added later. Both of
- * these are protected and may only be invoked from within a state machine.</p>
- *
- * <p>To illustrate some of these properties we'll use state machine with an 8
- * state hierarchy:</p>
-<pre>
-          mP0
-         /   \
-        mP1   mS0
-       /   \
-      mS2   mS1
-     /  \    \
-    mS3  mS4  mS5  ---&gt; initial state
-</pre>
- * <p>After starting mS5 the list of active states is mP0, mP1, mS1 and mS5.
- * So the order of calling processMessage when a message is received is mS5,
- * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this
- * message by returning false or NOT_HANDLED.</p>
- *
- * <p>Now assume mS5.processMessage receives a message it can handle, and during
- * the handling determines the machine should change states. It could call
- * transitionTo(mS4) and return true or HANDLED. Immediately after returning from
- * processMessage the state machine runtime will find the common parent,
- * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then
- * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So
- * when the next message is received mS4.processMessage will be invoked.</p>
- *
- * <p>Now for some concrete examples, here is the canonical HelloWorld as a state machine.
- * It responds with "Hello World" being printed to the log for every message.</p>
-<pre>
-class HelloWorld extends StateMachine {
-    HelloWorld(String name) {
-        super(name);
-        addState(mState1);
-        setInitialState(mState1);
-    }
-
-    public static HelloWorld makeHelloWorld() {
-        HelloWorld hw = new HelloWorld("hw");
-        hw.start();
-        return hw;
-    }
-
-    class State1 extends State {
-        &#64;Override public boolean processMessage(Message message) {
-            log("Hello World");
-            return HANDLED;
-        }
-    }
-    State1 mState1 = new State1();
-}
-
-void testHelloWorld() {
-    HelloWorld hw = makeHelloWorld();
-    hw.sendMessage(hw.obtainMessage());
-}
-</pre>
- * <p>A more interesting state machine is one with four states
- * with two independent parent states.</p>
-<pre>
-        mP1      mP2
-       /   \
-      mS2   mS1
-</pre>
- * <p>Here is a description of this state machine using pseudo code.</p>
- <pre>
-state mP1 {
-     enter { log("mP1.enter"); }
-     exit { log("mP1.exit");  }
-     on msg {
-         CMD_2 {
-             send(CMD_3);
-             defer(msg);
-             transitionTo(mS2);
-             return HANDLED;
-         }
-         return NOT_HANDLED;
-     }
-}
-
-INITIAL
-state mS1 parent mP1 {
-     enter { log("mS1.enter"); }
-     exit  { log("mS1.exit");  }
-     on msg {
-         CMD_1 {
-             transitionTo(mS1);
-             return HANDLED;
-         }
-         return NOT_HANDLED;
-     }
-}
-
-state mS2 parent mP1 {
-     enter { log("mS2.enter"); }
-     exit  { log("mS2.exit");  }
-     on msg {
-         CMD_2 {
-             send(CMD_4);
-             return HANDLED;
-         }
-         CMD_3 {
-             defer(msg);
-             transitionTo(mP2);
-             return HANDLED;
-         }
-         return NOT_HANDLED;
-     }
-}
-
-state mP2 {
-     enter {
-         log("mP2.enter");
-         send(CMD_5);
-     }
-     exit { log("mP2.exit"); }
-     on msg {
-         CMD_3, CMD_4 { return HANDLED; }
-         CMD_5 {
-             transitionTo(HaltingState);
-             return HANDLED;
-         }
-         return NOT_HANDLED;
-     }
-}
-</pre>
- * <p>The implementation is below and also in StateMachineTest:</p>
-<pre>
-class Hsm1 extends StateMachine {
-    public static final int CMD_1 = 1;
-    public static final int CMD_2 = 2;
-    public static final int CMD_3 = 3;
-    public static final int CMD_4 = 4;
-    public static final int CMD_5 = 5;
-
-    public static Hsm1 makeHsm1() {
-        log("makeHsm1 E");
-        Hsm1 sm = new Hsm1("hsm1");
-        sm.start();
-        log("makeHsm1 X");
-        return sm;
-    }
-
-    Hsm1(String name) {
-        super(name);
-        log("ctor E");
-
-        // Add states, use indentation to show hierarchy
-        addState(mP1);
-            addState(mS1, mP1);
-            addState(mS2, mP1);
-        addState(mP2);
-
-        // Set the initial state
-        setInitialState(mS1);
-        log("ctor X");
-    }
-
-    class P1 extends State {
-        &#64;Override public void enter() {
-            log("mP1.enter");
-        }
-        &#64;Override public boolean processMessage(Message message) {
-            boolean retVal;
-            log("mP1.processMessage what=" + message.what);
-            switch(message.what) {
-            case CMD_2:
-                // CMD_2 will arrive in mS2 before CMD_3
-                sendMessage(obtainMessage(CMD_3));
-                deferMessage(message);
-                transitionTo(mS2);
-                retVal = HANDLED;
-                break;
-            default:
-                // Any message we don't understand in this state invokes unhandledMessage
-                retVal = NOT_HANDLED;
-                break;
-            }
-            return retVal;
-        }
-        &#64;Override public void exit() {
-            log("mP1.exit");
-        }
-    }
-
-    class S1 extends State {
-        &#64;Override public void enter() {
-            log("mS1.enter");
-        }
-        &#64;Override public boolean processMessage(Message message) {
-            log("S1.processMessage what=" + message.what);
-            if (message.what == CMD_1) {
-                // Transition to ourself to show that enter/exit is called
-                transitionTo(mS1);
-                return HANDLED;
-            } else {
-                // Let parent process all other messages
-                return NOT_HANDLED;
-            }
-        }
-        &#64;Override public void exit() {
-            log("mS1.exit");
-        }
-    }
-
-    class S2 extends State {
-        &#64;Override public void enter() {
-            log("mS2.enter");
-        }
-        &#64;Override public boolean processMessage(Message message) {
-            boolean retVal;
-            log("mS2.processMessage what=" + message.what);
-            switch(message.what) {
-            case(CMD_2):
-                sendMessage(obtainMessage(CMD_4));
-                retVal = HANDLED;
-                break;
-            case(CMD_3):
-                deferMessage(message);
-                transitionTo(mP2);
-                retVal = HANDLED;
-                break;
-            default:
-                retVal = NOT_HANDLED;
-                break;
-            }
-            return retVal;
-        }
-        &#64;Override public void exit() {
-            log("mS2.exit");
-        }
-    }
-
-    class P2 extends State {
-        &#64;Override public void enter() {
-            log("mP2.enter");
-            sendMessage(obtainMessage(CMD_5));
-        }
-        &#64;Override public boolean processMessage(Message message) {
-            log("P2.processMessage what=" + message.what);
-            switch(message.what) {
-            case(CMD_3):
-                break;
-            case(CMD_4):
-                break;
-            case(CMD_5):
-                transitionToHaltingState();
-                break;
-            }
-            return HANDLED;
-        }
-        &#64;Override public void exit() {
-            log("mP2.exit");
-        }
-    }
-
-    &#64;Override
-    void onHalting() {
-        log("halting");
-        synchronized (this) {
-            this.notifyAll();
-        }
-    }
-
-    P1 mP1 = new P1();
-    S1 mS1 = new S1();
-    S2 mS2 = new S2();
-    P2 mP2 = new P2();
-}
-</pre>
- * <p>If this is executed by sending two messages CMD_1 and CMD_2
- * (Note the synchronize is only needed because we use hsm.wait())</p>
-<pre>
-Hsm1 hsm = makeHsm1();
-synchronize(hsm) {
-     hsm.sendMessage(obtainMessage(hsm.CMD_1));
-     hsm.sendMessage(obtainMessage(hsm.CMD_2));
-     try {
-          // wait for the messages to be handled
-          hsm.wait();
-     } catch (InterruptedException e) {
-          loge("exception while waiting " + e.getMessage());
-     }
-}
-</pre>
- * <p>The output is:</p>
-<pre>
-D/hsm1    ( 1999): makeHsm1 E
-D/hsm1    ( 1999): ctor E
-D/hsm1    ( 1999): ctor X
-D/hsm1    ( 1999): mP1.enter
-D/hsm1    ( 1999): mS1.enter
-D/hsm1    ( 1999): makeHsm1 X
-D/hsm1    ( 1999): mS1.processMessage what=1
-D/hsm1    ( 1999): mS1.exit
-D/hsm1    ( 1999): mS1.enter
-D/hsm1    ( 1999): mS1.processMessage what=2
-D/hsm1    ( 1999): mP1.processMessage what=2
-D/hsm1    ( 1999): mS1.exit
-D/hsm1    ( 1999): mS2.enter
-D/hsm1    ( 1999): mS2.processMessage what=2
-D/hsm1    ( 1999): mS2.processMessage what=3
-D/hsm1    ( 1999): mS2.exit
-D/hsm1    ( 1999): mP1.exit
-D/hsm1    ( 1999): mP2.enter
-D/hsm1    ( 1999): mP2.processMessage what=3
-D/hsm1    ( 1999): mP2.processMessage what=4
-D/hsm1    ( 1999): mP2.processMessage what=5
-D/hsm1    ( 1999): mP2.exit
-D/hsm1    ( 1999): halting
-</pre>
- */
-public class StateMachine {
-    // Name of the state machine and used as logging tag
-    private String mName;
-
-    /** Message.what value when quitting */
-    private static final int SM_QUIT_CMD = -1;
-
-    /** Message.what value when initializing */
-    private static final int SM_INIT_CMD = -2;
-
-    /**
-     * Convenience constant that maybe returned by processMessage
-     * to indicate the message was processed and is not to be
-     * processed by parent states
-     */
-    public static final boolean HANDLED = true;
-
-    /**
-     * Convenience constant that maybe returned by processMessage
-     * to indicate the message was NOT processed and is to be
-     * processed by parent states
-     */
-    public static final boolean NOT_HANDLED = false;
-
-    /**
-     * StateMachine logging record.
-     * {@hide}
-     */
-    public static class LogRec {
-        private StateMachine mSm;
-        private long mTime;
-        private int mWhat;
-        private String mInfo;
-        private IState mState;
-        private IState mOrgState;
-        private IState mDstState;
-
-        /**
-         * Constructor
-         *
-         * @param msg
-         * @param state the state which handled the message
-         * @param orgState is the first state the received the message but
-         * did not processes the message.
-         * @param transToState is the state that was transitioned to after the message was
-         * processed.
-         */
-        LogRec(StateMachine sm, Message msg, String info, IState state, IState orgState,
-                IState transToState) {
-            update(sm, msg, info, state, orgState, transToState);
-        }
-
-        /**
-         * Update the information in the record.
-         * @param state that handled the message
-         * @param orgState is the first state the received the message
-         * @param dstState is the state that was the transition target when logging
-         */
-        public void update(StateMachine sm, Message msg, String info, IState state, IState orgState,
-                IState dstState) {
-            mSm = sm;
-            mTime = System.currentTimeMillis();
-            mWhat = (msg != null) ? msg.what : 0;
-            mInfo = info;
-            mState = state;
-            mOrgState = orgState;
-            mDstState = dstState;
-        }
-
-        /**
-         * @return time stamp
-         */
-        public long getTime() {
-            return mTime;
-        }
-
-        /**
-         * @return msg.what
-         */
-        public long getWhat() {
-            return mWhat;
-        }
-
-        /**
-         * @return the command that was executing
-         */
-        public String getInfo() {
-            return mInfo;
-        }
-
-        /**
-         * @return the state that handled this message
-         */
-        public IState getState() {
-            return mState;
-        }
-
-        /**
-         * @return the state destination state if a transition is occurring or null if none.
-         */
-        public IState getDestState() {
-            return mDstState;
-        }
-
-        /**
-         * @return the original state that received the message.
-         */
-        public IState getOriginalState() {
-            return mOrgState;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            sb.append("time=");
-            Calendar c = Calendar.getInstance();
-            c.setTimeInMillis(mTime);
-            sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
-            sb.append(" processed=");
-            sb.append(mState == null ? "<null>" : mState.getName());
-            sb.append(" org=");
-            sb.append(mOrgState == null ? "<null>" : mOrgState.getName());
-            sb.append(" dest=");
-            sb.append(mDstState == null ? "<null>" : mDstState.getName());
-            sb.append(" what=");
-            String what = mSm != null ? mSm.getWhatToString(mWhat) : "";
-            if (TextUtils.isEmpty(what)) {
-                sb.append(mWhat);
-                sb.append("(0x");
-                sb.append(Integer.toHexString(mWhat));
-                sb.append(")");
-            } else {
-                sb.append(what);
-            }
-            if (!TextUtils.isEmpty(mInfo)) {
-                sb.append(" ");
-                sb.append(mInfo);
-            }
-            return sb.toString();
-        }
-    }
-
-    /**
-     * A list of log records including messages recently processed by the state machine.
-     *
-     * The class maintains a list of log records including messages
-     * recently processed. The list is finite and may be set in the
-     * constructor or by calling setSize. The public interface also
-     * includes size which returns the number of recent records,
-     * count which is the number of records processed since the
-     * the last setSize, get which returns a record and
-     * add which adds a record.
-     */
-    private static class LogRecords {
-
-        private static final int DEFAULT_SIZE = 20;
-
-        private Vector<LogRec> mLogRecVector = new Vector<LogRec>();
-        private int mMaxSize = DEFAULT_SIZE;
-        private int mOldestIndex = 0;
-        private int mCount = 0;
-        private boolean mLogOnlyTransitions = false;
-
-        /**
-         * private constructor use add
-         */
-        private LogRecords() {
-        }
-
-        /**
-         * Set size of messages to maintain and clears all current records.
-         *
-         * @param maxSize number of records to maintain at anyone time.
-        */
-        synchronized void setSize(int maxSize) {
-            // TODO: once b/28217358 is fixed, add unit tests  to verify that these variables are
-            // cleared after calling this method, and that subsequent calls to get() function as
-            // expected.
-            mMaxSize = maxSize;
-            mOldestIndex = 0;
-            mCount = 0;
-            mLogRecVector.clear();
-        }
-
-        synchronized void setLogOnlyTransitions(boolean enable) {
-            mLogOnlyTransitions = enable;
-        }
-
-        synchronized boolean logOnlyTransitions() {
-            return mLogOnlyTransitions;
-        }
-
-        /**
-         * @return the number of recent records.
-         */
-        synchronized int size() {
-            return mLogRecVector.size();
-        }
-
-        /**
-         * @return the total number of records processed since size was set.
-         */
-        synchronized int count() {
-            return mCount;
-        }
-
-        /**
-         * Clear the list of records.
-         */
-        synchronized void cleanup() {
-            mLogRecVector.clear();
-        }
-
-        /**
-         * @return the information on a particular record. 0 is the oldest
-         * record and size()-1 is the newest record. If the index is to
-         * large null is returned.
-         */
-        synchronized LogRec get(int index) {
-            int nextIndex = mOldestIndex + index;
-            if (nextIndex >= mMaxSize) {
-                nextIndex -= mMaxSize;
-            }
-            if (nextIndex >= size()) {
-                return null;
-            } else {
-                return mLogRecVector.get(nextIndex);
-            }
-        }
-
-        /**
-         * Add a processed message.
-         *
-         * @param msg
-         * @param messageInfo to be stored
-         * @param state that handled the message
-         * @param orgState is the first state the received the message but
-         * did not processes the message.
-         * @param transToState is the state that was transitioned to after the message was
-         * processed.
-         *
-         */
-        synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state,
-                IState orgState, IState transToState) {
-            mCount += 1;
-            if (mLogRecVector.size() < mMaxSize) {
-                mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState));
-            } else {
-                LogRec pmi = mLogRecVector.get(mOldestIndex);
-                mOldestIndex += 1;
-                if (mOldestIndex >= mMaxSize) {
-                    mOldestIndex = 0;
-                }
-                pmi.update(sm, msg, messageInfo, state, orgState, transToState);
-            }
-        }
-    }
-
-    private static class SmHandler extends Handler {
-
-        /** true if StateMachine has quit */
-        private boolean mHasQuit = false;
-
-        /** The debug flag */
-        private boolean mDbg = false;
-
-        /** The SmHandler object, identifies that message is internal */
-        private static final Object mSmHandlerObj = new Object();
-
-        /** The current message */
-        private Message mMsg;
-
-        /** A list of log records including messages this state machine has processed */
-        private LogRecords mLogRecords = new LogRecords();
-
-        /** true if construction of the state machine has not been completed */
-        private boolean mIsConstructionCompleted;
-
-        /** Stack used to manage the current hierarchy of states */
-        private StateInfo mStateStack[];
-
-        /** Top of mStateStack */
-        private int mStateStackTopIndex = -1;
-
-        /** A temporary stack used to manage the state stack */
-        private StateInfo mTempStateStack[];
-
-        /** The top of the mTempStateStack */
-        private int mTempStateStackCount;
-
-        /** State used when state machine is halted */
-        private HaltingState mHaltingState = new HaltingState();
-
-        /** State used when state machine is quitting */
-        private QuittingState mQuittingState = new QuittingState();
-
-        /** Reference to the StateMachine */
-        private StateMachine mSm;
-
-        /**
-         * Information about a state.
-         * Used to maintain the hierarchy.
-         */
-        private class StateInfo {
-            /** The state */
-            State state;
-
-            /** The parent of this state, null if there is no parent */
-            StateInfo parentStateInfo;
-
-            /** True when the state has been entered and on the stack */
-            boolean active;
-
-            /**
-             * Convert StateInfo to string
-             */
-            @Override
-            public String toString() {
-                return "state=" + state.getName() + ",active=" + active + ",parent="
-                        + ((parentStateInfo == null) ? "null" : parentStateInfo.state.getName());
-            }
-        }
-
-        /** The map of all of the states in the state machine */
-        private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
-
-        /** The initial state that will process the first message */
-        private State mInitialState;
-
-        /** The destination state when transitionTo has been invoked */
-        private State mDestState;
-
-        /**
-         * Indicates if a transition is in progress
-         *
-         * This will be true for all calls of State.exit and all calls of State.enter except for the
-         * last enter call for the current destination state.
-         */
-        private boolean mTransitionInProgress = false;
-
-        /** The list of deferred messages */
-        private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
-
-        /**
-         * State entered when transitionToHaltingState is called.
-         */
-        private class HaltingState extends State {
-            @Override
-            public boolean processMessage(Message msg) {
-                mSm.haltedProcessMessage(msg);
-                return true;
-            }
-        }
-
-        /**
-         * State entered when a valid quit message is handled.
-         */
-        private class QuittingState extends State {
-            @Override
-            public boolean processMessage(Message msg) {
-                return NOT_HANDLED;
-            }
-        }
-
-        /**
-         * Handle messages sent to the state machine by calling
-         * the current state's processMessage. It also handles
-         * the enter/exit calls and placing any deferred messages
-         * back onto the queue when transitioning to a new state.
-         */
-        @Override
-        public final void handleMessage(Message msg) {
-            if (!mHasQuit) {
-                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
-                    mSm.onPreHandleMessage(msg);
-                }
-
-                if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
-
-                /** Save the current message */
-                mMsg = msg;
-
-                /** State that processed the message */
-                State msgProcessedState = null;
-                if (mIsConstructionCompleted || (mMsg.what == SM_QUIT_CMD)) {
-                    /** Normal path */
-                    msgProcessedState = processMsg(msg);
-                } else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
-                        && (mMsg.obj == mSmHandlerObj)) {
-                    /** Initial one time path. */
-                    mIsConstructionCompleted = true;
-                    invokeEnterMethods(0);
-                } else {
-                    throw new RuntimeException("StateMachine.handleMessage: "
-                            + "The start method not called, received msg: " + msg);
-                }
-                performTransitions(msgProcessedState, msg);
-
-                // We need to check if mSm == null here as we could be quitting.
-                if (mDbg && mSm != null) mSm.log("handleMessage: X");
-
-                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
-                    mSm.onPostHandleMessage(msg);
-                }
-            }
-        }
-
-        /**
-         * Do any transitions
-         * @param msgProcessedState is the state that processed the message
-         */
-        private void performTransitions(State msgProcessedState, Message msg) {
-            /**
-             * If transitionTo has been called, exit and then enter
-             * the appropriate states. We loop on this to allow
-             * enter and exit methods to use transitionTo.
-             */
-            State orgState = mStateStack[mStateStackTopIndex].state;
-
-            /**
-             * Record whether message needs to be logged before we transition and
-             * and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
-             * always set msg.obj to the handler.
-             */
-            boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
-
-            if (mLogRecords.logOnlyTransitions()) {
-                /** Record only if there is a transition */
-                if (mDestState != null) {
-                    mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
-                            orgState, mDestState);
-                }
-            } else if (recordLogMsg) {
-                /** Record message */
-                mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
-                        mDestState);
-            }
-
-            State destState = mDestState;
-            if (destState != null) {
-                /**
-                 * Process the transitions including transitions in the enter/exit methods
-                 */
-                while (true) {
-                    if (mDbg) mSm.log("handleMessage: new destination call exit/enter");
-
-                    /**
-                     * Determine the states to exit and enter and return the
-                     * common ancestor state of the enter/exit states. Then
-                     * invoke the exit methods then the enter methods.
-                     */
-                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
-                    // flag is cleared in invokeEnterMethods before entering the target state
-                    mTransitionInProgress = true;
-                    invokeExitMethods(commonStateInfo);
-                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
-                    invokeEnterMethods(stateStackEnteringIndex);
-
-                    /**
-                     * Since we have transitioned to a new state we need to have
-                     * any deferred messages moved to the front of the message queue
-                     * so they will be processed before any other messages in the
-                     * message queue.
-                     */
-                    moveDeferredMessageAtFrontOfQueue();
-
-                    if (destState != mDestState) {
-                        // A new mDestState so continue looping
-                        destState = mDestState;
-                    } else {
-                        // No change in mDestState so we're done
-                        break;
-                    }
-                }
-                mDestState = null;
-            }
-
-            /**
-             * After processing all transitions check and
-             * see if the last transition was to quit or halt.
-             */
-            if (destState != null) {
-                if (destState == mQuittingState) {
-                    /**
-                     * Call onQuitting to let subclasses cleanup.
-                     */
-                    mSm.onQuitting();
-                    cleanupAfterQuitting();
-                } else if (destState == mHaltingState) {
-                    /**
-                     * Call onHalting() if we've transitioned to the halting
-                     * state. All subsequent messages will be processed in
-                     * in the halting state which invokes haltedProcessMessage(msg);
-                     */
-                    mSm.onHalting();
-                }
-            }
-        }
-
-        /**
-         * Cleanup all the static variables and the looper after the SM has been quit.
-         */
-        private final void cleanupAfterQuitting() {
-            if (mSm.mSmThread != null) {
-                // If we made the thread then quit looper which stops the thread.
-                getLooper().quit();
-                mSm.mSmThread = null;
-            }
-
-            mSm.mSmHandler = null;
-            mSm = null;
-            mMsg = null;
-            mLogRecords.cleanup();
-            mStateStack = null;
-            mTempStateStack = null;
-            mStateInfo.clear();
-            mInitialState = null;
-            mDestState = null;
-            mDeferredMessages.clear();
-            mHasQuit = true;
-        }
-
-        /**
-         * Complete the construction of the state machine.
-         */
-        private final void completeConstruction() {
-            if (mDbg) mSm.log("completeConstruction: E");
-
-            /**
-             * Determine the maximum depth of the state hierarchy
-             * so we can allocate the state stacks.
-             */
-            int maxDepth = 0;
-            for (StateInfo si : mStateInfo.values()) {
-                int depth = 0;
-                for (StateInfo i = si; i != null; depth++) {
-                    i = i.parentStateInfo;
-                }
-                if (maxDepth < depth) {
-                    maxDepth = depth;
-                }
-            }
-            if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);
-
-            mStateStack = new StateInfo[maxDepth];
-            mTempStateStack = new StateInfo[maxDepth];
-            setupInitialStateStack();
-
-            /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
-            sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
-
-            if (mDbg) mSm.log("completeConstruction: X");
-        }
-
-        /**
-         * Process the message. If the current state doesn't handle
-         * it, call the states parent and so on. If it is never handled then
-         * call the state machines unhandledMessage method.
-         * @return the state that processed the message
-         */
-        private final State processMsg(Message msg) {
-            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
-            if (mDbg) {
-                mSm.log("processMsg: " + curStateInfo.state.getName());
-            }
-
-            if (isQuit(msg)) {
-                transitionTo(mQuittingState);
-            } else {
-                while (!curStateInfo.state.processMessage(msg)) {
-                    /**
-                     * Not processed
-                     */
-                    curStateInfo = curStateInfo.parentStateInfo;
-                    if (curStateInfo == null) {
-                        /**
-                         * No parents left so it's not handled
-                         */
-                        mSm.unhandledMessage(msg);
-                        break;
-                    }
-                    if (mDbg) {
-                        mSm.log("processMsg: " + curStateInfo.state.getName());
-                    }
-                }
-            }
-            return (curStateInfo != null) ? curStateInfo.state : null;
-        }
-
-        /**
-         * Call the exit method for each state from the top of stack
-         * up to the common ancestor state.
-         */
-        private final void invokeExitMethods(StateInfo commonStateInfo) {
-            while ((mStateStackTopIndex >= 0)
-                    && (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
-                State curState = mStateStack[mStateStackTopIndex].state;
-                if (mDbg) mSm.log("invokeExitMethods: " + curState.getName());
-                curState.exit();
-                mStateStack[mStateStackTopIndex].active = false;
-                mStateStackTopIndex -= 1;
-            }
-        }
-
-        /**
-         * Invoke the enter method starting at the entering index to top of state stack
-         */
-        private final void invokeEnterMethods(int stateStackEnteringIndex) {
-            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
-                if (stateStackEnteringIndex == mStateStackTopIndex) {
-                    // Last enter state for transition
-                    mTransitionInProgress = false;
-                }
-                if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
-                mStateStack[i].state.enter();
-                mStateStack[i].active = true;
-            }
-            mTransitionInProgress = false; // ensure flag set to false if no methods called
-        }
-
-        /**
-         * Move the deferred message to the front of the message queue.
-         */
-        private final void moveDeferredMessageAtFrontOfQueue() {
-            /**
-             * The oldest messages on the deferred list must be at
-             * the front of the queue so start at the back, which
-             * as the most resent message and end with the oldest
-             * messages at the front of the queue.
-             */
-            for (int i = mDeferredMessages.size() - 1; i >= 0; i--) {
-                Message curMsg = mDeferredMessages.get(i);
-                if (mDbg) mSm.log("moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);
-                sendMessageAtFrontOfQueue(curMsg);
-            }
-            mDeferredMessages.clear();
-        }
-
-        /**
-         * Move the contents of the temporary stack to the state stack
-         * reversing the order of the items on the temporary stack as
-         * they are moved.
-         *
-         * @return index into mStateStack where entering needs to start
-         */
-        private final int moveTempStateStackToStateStack() {
-            int startingIndex = mStateStackTopIndex + 1;
-            int i = mTempStateStackCount - 1;
-            int j = startingIndex;
-            while (i >= 0) {
-                if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
-                mStateStack[j] = mTempStateStack[i];
-                j += 1;
-                i -= 1;
-            }
-
-            mStateStackTopIndex = j - 1;
-            if (mDbg) {
-                mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
-                        + ",startingIndex=" + startingIndex + ",Top="
-                        + mStateStack[mStateStackTopIndex].state.getName());
-            }
-            return startingIndex;
-        }
-
-        /**
-         * Setup the mTempStateStack with the states we are going to enter.
-         *
-         * This is found by searching up the destState's ancestors for a
-         * state that is already active i.e. StateInfo.active == true.
-         * The destStae and all of its inactive parents will be on the
-         * TempStateStack as the list of states to enter.
-         *
-         * @return StateInfo of the common ancestor for the destState and
-         * current state or null if there is no common parent.
-         */
-        private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
-            /**
-             * Search up the parent list of the destination state for an active
-             * state. Use a do while() loop as the destState must always be entered
-             * even if it is active. This can happen if we are exiting/entering
-             * the current state.
-             */
-            mTempStateStackCount = 0;
-            StateInfo curStateInfo = mStateInfo.get(destState);
-            do {
-                mTempStateStack[mTempStateStackCount++] = curStateInfo;
-                curStateInfo = curStateInfo.parentStateInfo;
-            } while ((curStateInfo != null) && !curStateInfo.active);
-
-            if (mDbg) {
-                mSm.log("setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
-                        + mTempStateStackCount + ",curStateInfo: " + curStateInfo);
-            }
-            return curStateInfo;
-        }
-
-        /**
-         * Initialize StateStack to mInitialState.
-         */
-        private final void setupInitialStateStack() {
-            if (mDbg) {
-                mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
-            }
-
-            StateInfo curStateInfo = mStateInfo.get(mInitialState);
-            for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
-                mTempStateStack[mTempStateStackCount] = curStateInfo;
-                curStateInfo = curStateInfo.parentStateInfo;
-            }
-
-            // Empty the StateStack
-            mStateStackTopIndex = -1;
-
-            moveTempStateStackToStateStack();
-        }
-
-        /**
-         * @return current message
-         */
-        private final Message getCurrentMessage() {
-            return mMsg;
-        }
-
-        /**
-         * @return current state
-         */
-        private final IState getCurrentState() {
-            return mStateStack[mStateStackTopIndex].state;
-        }
-
-        /**
-         * Add a new state to the state machine. Bottom up addition
-         * of states is allowed but the same state may only exist
-         * in one hierarchy.
-         *
-         * @param state the state to add
-         * @param parent the parent of state
-         * @return stateInfo for this state
-         */
-        private final StateInfo addState(State state, State parent) {
-            if (mDbg) {
-                mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
-                        + ((parent == null) ? "" : parent.getName()));
-            }
-            StateInfo parentStateInfo = null;
-            if (parent != null) {
-                parentStateInfo = mStateInfo.get(parent);
-                if (parentStateInfo == null) {
-                    // Recursively add our parent as it's not been added yet.
-                    parentStateInfo = addState(parent, null);
-                }
-            }
-            StateInfo stateInfo = mStateInfo.get(state);
-            if (stateInfo == null) {
-                stateInfo = new StateInfo();
-                mStateInfo.put(state, stateInfo);
-            }
-
-            // Validate that we aren't adding the same state in two different hierarchies.
-            if ((stateInfo.parentStateInfo != null)
-                    && (stateInfo.parentStateInfo != parentStateInfo)) {
-                throw new RuntimeException("state already added");
-            }
-            stateInfo.state = state;
-            stateInfo.parentStateInfo = parentStateInfo;
-            stateInfo.active = false;
-            if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
-            return stateInfo;
-        }
-
-        /**
-         * Remove a state from the state machine. Will not remove the state if it is currently
-         * active or if it has any children in the hierarchy.
-         * @param state the state to remove
-         */
-        private void removeState(State state) {
-            StateInfo stateInfo = mStateInfo.get(state);
-            if (stateInfo == null || stateInfo.active) {
-                return;
-            }
-            boolean isParent = mStateInfo.values().stream()
-                    .filter(si -> si.parentStateInfo == stateInfo)
-                    .findAny()
-                    .isPresent();
-            if (isParent) {
-                return;
-            }
-            mStateInfo.remove(state);
-        }
-
-        /**
-         * Constructor
-         *
-         * @param looper for dispatching messages
-         * @param sm the hierarchical state machine
-         */
-        private SmHandler(Looper looper, StateMachine sm) {
-            super(looper);
-            mSm = sm;
-
-            addState(mHaltingState, null);
-            addState(mQuittingState, null);
-        }
-
-        /** @see StateMachine#setInitialState(State) */
-        private final void setInitialState(State initialState) {
-            if (mDbg) mSm.log("setInitialState: initialState=" + initialState.getName());
-            mInitialState = initialState;
-        }
-
-        /** @see StateMachine#transitionTo(IState) */
-        private final void transitionTo(IState destState) {
-            if (mTransitionInProgress) {
-                Log.wtf(mSm.mName, "transitionTo called while transition already in progress to " +
-                        mDestState + ", new target state=" + destState);
-            }
-            mDestState = (State) destState;
-            if (mDbg) mSm.log("transitionTo: destState=" + mDestState.getName());
-        }
-
-        /** @see StateMachine#deferMessage(Message) */
-        private final void deferMessage(Message msg) {
-            if (mDbg) mSm.log("deferMessage: msg=" + msg.what);
-
-            /* Copy the "msg" to "newMsg" as "msg" will be recycled */
-            Message newMsg = obtainMessage();
-            newMsg.copyFrom(msg);
-
-            mDeferredMessages.add(newMsg);
-        }
-
-        /** @see StateMachine#quit() */
-        private final void quit() {
-            if (mDbg) mSm.log("quit:");
-            sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
-        }
-
-        /** @see StateMachine#quitNow() */
-        private final void quitNow() {
-            if (mDbg) mSm.log("quitNow:");
-            sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
-        }
-
-        /** Validate that the message was sent by quit or quitNow. */
-        private final boolean isQuit(Message msg) {
-            return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj);
-        }
-
-        /** @see StateMachine#isDbg() */
-        private final boolean isDbg() {
-            return mDbg;
-        }
-
-        /** @see StateMachine#setDbg(boolean) */
-        private final void setDbg(boolean dbg) {
-            mDbg = dbg;
-        }
-
-    }
-
-    private SmHandler mSmHandler;
-    private HandlerThread mSmThread;
-
-    /**
-     * Initialize.
-     *
-     * @param looper for this state machine
-     * @param name of the state machine
-     */
-    private void initStateMachine(String name, Looper looper) {
-        mName = name;
-        mSmHandler = new SmHandler(looper, this);
-    }
-
-    /**
-     * Constructor creates a StateMachine with its own thread.
-     *
-     * @param name of the state machine
-     */
-    @UnsupportedAppUsage
-    protected StateMachine(String name) {
-        mSmThread = new HandlerThread(name);
-        mSmThread.start();
-        Looper looper = mSmThread.getLooper();
-
-        initStateMachine(name, looper);
-    }
-
-    /**
-     * Constructor creates a StateMachine using the looper.
-     *
-     * @param name of the state machine
-     */
-    @UnsupportedAppUsage
-    protected StateMachine(String name, Looper looper) {
-        initStateMachine(name, looper);
-    }
-
-    /**
-     * Constructor creates a StateMachine using the handler.
-     *
-     * @param name of the state machine
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    protected StateMachine(String name, Handler handler) {
-        initStateMachine(name, handler.getLooper());
-    }
-
-    /**
-     * Notifies subclass that the StateMachine handler is about to process the Message msg
-     * @param msg The message that is being handled
-     */
-    protected void onPreHandleMessage(Message msg) {
-    }
-
-    /**
-     * Notifies subclass that the StateMachine handler has finished processing the Message msg and
-     * has possibly transitioned to a new state.
-     * @param msg The message that is being handled
-     */
-    protected void onPostHandleMessage(Message msg) {
-    }
-
-    /**
-     * Add a new state to the state machine
-     * @param state the state to add
-     * @param parent the parent of state
-     */
-    public final void addState(State state, State parent) {
-        mSmHandler.addState(state, parent);
-    }
-
-    /**
-     * Add a new state to the state machine, parent will be null
-     * @param state to add
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public final void addState(State state) {
-        mSmHandler.addState(state, null);
-    }
-
-    /**
-     * Removes a state from the state machine, unless it is currently active or if it has children.
-     * @param state state to remove
-     */
-    public final void removeState(State state) {
-        mSmHandler.removeState(state);
-    }
-
-    /**
-     * Set the initial state. This must be invoked before
-     * and messages are sent to the state machine.
-     *
-     * @param initialState is the state which will receive the first message.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public final void setInitialState(State initialState) {
-        mSmHandler.setInitialState(initialState);
-    }
-
-    /**
-     * @return current message
-     */
-    public final Message getCurrentMessage() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return null;
-        return smh.getCurrentMessage();
-    }
-
-    /**
-     * @return current state
-     */
-    public final IState getCurrentState() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return null;
-        return smh.getCurrentState();
-    }
-
-    /**
-     * transition to destination state. Upon returning
-     * from processMessage the current state's exit will
-     * be executed and upon the next message arriving
-     * destState.enter will be invoked.
-     *
-     * this function can also be called inside the enter function of the
-     * previous transition target, but the behavior is undefined when it is
-     * called mid-way through a previous transition (for example, calling this
-     * in the enter() routine of a intermediate node when the current transition
-     * target is one of the nodes descendants).
-     *
-     * @param destState will be the state that receives the next message.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public final void transitionTo(IState destState) {
-        mSmHandler.transitionTo(destState);
-    }
-
-    /**
-     * transition to halt state. Upon returning
-     * from processMessage we will exit all current
-     * states, execute the onHalting() method and then
-     * for all subsequent messages haltedProcessMessage
-     * will be called.
-     */
-    public final void transitionToHaltingState() {
-        mSmHandler.transitionTo(mSmHandler.mHaltingState);
-    }
-
-    /**
-     * Defer this message until next state transition.
-     * Upon transitioning all deferred messages will be
-     * placed on the queue and reprocessed in the original
-     * order. (i.e. The next state the oldest messages will
-     * be processed first)
-     *
-     * @param msg is deferred until the next transition.
-     */
-    public final void deferMessage(Message msg) {
-        mSmHandler.deferMessage(msg);
-    }
-
-    /**
-     * Called when message wasn't handled
-     *
-     * @param msg that couldn't be handled.
-     */
-    protected void unhandledMessage(Message msg) {
-        if (mSmHandler.mDbg) loge(" - unhandledMessage: msg.what=" + msg.what);
-    }
-
-    /**
-     * Called for any message that is received after
-     * transitionToHalting is called.
-     */
-    protected void haltedProcessMessage(Message msg) {
-    }
-
-    /**
-     * This will be called once after handling a message that called
-     * transitionToHalting. All subsequent messages will invoke
-     * {@link StateMachine#haltedProcessMessage(Message)}
-     */
-    protected void onHalting() {
-    }
-
-    /**
-     * This will be called once after a quit message that was NOT handled by
-     * the derived StateMachine. The StateMachine will stop and any subsequent messages will be
-     * ignored. In addition, if this StateMachine created the thread, the thread will
-     * be stopped after this method returns.
-     */
-    protected void onQuitting() {
-    }
-
-    /**
-     * @return the name
-     */
-    public final String getName() {
-        return mName;
-    }
-
-    /**
-     * Set number of log records to maintain and clears all current records.
-     *
-     * @param maxSize number of messages to maintain at anyone time.
-     */
-    public final void setLogRecSize(int maxSize) {
-        mSmHandler.mLogRecords.setSize(maxSize);
-    }
-
-    /**
-     * Set to log only messages that cause a state transition
-     *
-     * @param enable {@code true} to enable, {@code false} to disable
-     */
-    public final void setLogOnlyTransitions(boolean enable) {
-        mSmHandler.mLogRecords.setLogOnlyTransitions(enable);
-    }
-
-    /**
-     * @return the number of log records currently readable
-     */
-    public final int getLogRecSize() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return 0;
-        return smh.mLogRecords.size();
-    }
-
-    /**
-     * @return the number of log records we can store
-     */
-    @VisibleForTesting
-    public final int getLogRecMaxSize() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return 0;
-        return smh.mLogRecords.mMaxSize;
-    }
-
-    /**
-     * @return the total number of records processed
-     */
-    public final int getLogRecCount() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return 0;
-        return smh.mLogRecords.count();
-    }
-
-    /**
-     * @return a log record, or null if index is out of range
-     */
-    public final LogRec getLogRec(int index) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return null;
-        return smh.mLogRecords.get(index);
-    }
-
-    /**
-     * @return a copy of LogRecs as a collection
-     */
-    public final Collection<LogRec> copyLogRecs() {
-        Vector<LogRec> vlr = new Vector<LogRec>();
-        SmHandler smh = mSmHandler;
-        if (smh != null) {
-            for (LogRec lr : smh.mLogRecords.mLogRecVector) {
-                vlr.add(lr);
-            }
-        }
-        return vlr;
-    }
-
-    /**
-     * Add the string to LogRecords.
-     *
-     * @param string
-     */
-    public void addLogRec(String string) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-        smh.mLogRecords.add(this, smh.getCurrentMessage(), string, smh.getCurrentState(),
-                smh.mStateStack[smh.mStateStackTopIndex].state, smh.mDestState);
-    }
-
-    /**
-     * @return true if msg should be saved in the log, default is true.
-     */
-    protected boolean recordLogRec(Message msg) {
-        return true;
-    }
-
-    /**
-     * Return a string to be logged by LogRec, default
-     * is an empty string. Override if additional information is desired.
-     *
-     * @param msg that was processed
-     * @return information to be logged as a String
-     */
-    protected String getLogRecString(Message msg) {
-        return "";
-    }
-
-    /**
-     * @return the string for msg.what
-     */
-    protected String getWhatToString(int what) {
-        return null;
-    }
-
-    /**
-     * @return Handler, maybe null if state machine has quit.
-     */
-    public final Handler getHandler() {
-        return mSmHandler;
-    }
-
-    /**
-     * Get a message and set Message.target state machine handler.
-     *
-     * Note: The handler can be null if the state machine has quit,
-     * which means target will be null and may cause a AndroidRuntimeException
-     * in MessageQueue#enqueMessage if sent directly or if sent using
-     * StateMachine#sendMessage the message will just be ignored.
-     *
-     * @return  A Message object from the global pool
-     */
-    public final Message obtainMessage() {
-        return Message.obtain(mSmHandler);
-    }
-
-    /**
-     * Get a message and set Message.target state machine handler, what.
-     *
-     * Note: The handler can be null if the state machine has quit,
-     * which means target will be null and may cause a AndroidRuntimeException
-     * in MessageQueue#enqueMessage if sent directly or if sent using
-     * StateMachine#sendMessage the message will just be ignored.
-     *
-     * @param what is the assigned to Message.what.
-     * @return  A Message object from the global pool
-     */
-    public final Message obtainMessage(int what) {
-        return Message.obtain(mSmHandler, what);
-    }
-
-    /**
-     * Get a message and set Message.target state machine handler,
-     * what and obj.
-     *
-     * Note: The handler can be null if the state machine has quit,
-     * which means target will be null and may cause a AndroidRuntimeException
-     * in MessageQueue#enqueMessage if sent directly or if sent using
-     * StateMachine#sendMessage the message will just be ignored.
-     *
-     * @param what is the assigned to Message.what.
-     * @param obj is assigned to Message.obj.
-     * @return  A Message object from the global pool
-     */
-    public final Message obtainMessage(int what, Object obj) {
-        return Message.obtain(mSmHandler, what, obj);
-    }
-
-    /**
-     * Get a message and set Message.target state machine handler,
-     * what, arg1 and arg2
-     *
-     * Note: The handler can be null if the state machine has quit,
-     * which means target will be null and may cause a AndroidRuntimeException
-     * in MessageQueue#enqueMessage if sent directly or if sent using
-     * StateMachine#sendMessage the message will just be ignored.
-     *
-     * @param what  is assigned to Message.what
-     * @param arg1  is assigned to Message.arg1
-     * @return  A Message object from the global pool
-     */
-    public final Message obtainMessage(int what, int arg1) {
-        // use this obtain so we don't match the obtain(h, what, Object) method
-        return Message.obtain(mSmHandler, what, arg1, 0);
-    }
-
-    /**
-     * Get a message and set Message.target state machine handler,
-     * what, arg1 and arg2
-     *
-     * Note: The handler can be null if the state machine has quit,
-     * which means target will be null and may cause a AndroidRuntimeException
-     * in MessageQueue#enqueMessage if sent directly or if sent using
-     * StateMachine#sendMessage the message will just be ignored.
-     *
-     * @param what  is assigned to Message.what
-     * @param arg1  is assigned to Message.arg1
-     * @param arg2  is assigned to Message.arg2
-     * @return  A Message object from the global pool
-     */
-    @UnsupportedAppUsage
-    public final Message obtainMessage(int what, int arg1, int arg2) {
-        return Message.obtain(mSmHandler, what, arg1, arg2);
-    }
-
-    /**
-     * Get a message and set Message.target state machine handler,
-     * what, arg1, arg2 and obj
-     *
-     * Note: The handler can be null if the state machine has quit,
-     * which means target will be null and may cause a AndroidRuntimeException
-     * in MessageQueue#enqueMessage if sent directly or if sent using
-     * StateMachine#sendMessage the message will just be ignored.
-     *
-     * @param what  is assigned to Message.what
-     * @param arg1  is assigned to Message.arg1
-     * @param arg2  is assigned to Message.arg2
-     * @param obj is assigned to Message.obj
-     * @return  A Message object from the global pool
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public final Message obtainMessage(int what, int arg1, int arg2, Object obj) {
-        return Message.obtain(mSmHandler, what, arg1, arg2, obj);
-    }
-
-    /**
-     * Enqueue a message to this state machine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    @UnsupportedAppUsage
-    public void sendMessage(int what) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessage(obtainMessage(what));
-    }
-
-    /**
-     * Enqueue a message to this state machine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    @UnsupportedAppUsage
-    public void sendMessage(int what, Object obj) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessage(obtainMessage(what, obj));
-    }
-
-    /**
-     * Enqueue a message to this state machine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void sendMessage(int what, int arg1) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessage(obtainMessage(what, arg1));
-    }
-
-    /**
-     * Enqueue a message to this state machine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessage(int what, int arg1, int arg2) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessage(obtainMessage(what, arg1, arg2));
-    }
-
-    /**
-     * Enqueue a message to this state machine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void sendMessage(int what, int arg1, int arg2, Object obj) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessage(obtainMessage(what, arg1, arg2, obj));
-    }
-
-    /**
-     * Enqueue a message to this state machine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    @UnsupportedAppUsage
-    public void sendMessage(Message msg) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessage(msg);
-    }
-
-    /**
-     * Enqueue a message to this state machine after a delay.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessageDelayed(int what, long delayMillis) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageDelayed(obtainMessage(what), delayMillis);
-    }
-
-    /**
-     * Enqueue a message to this state machine after a delay.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessageDelayed(int what, Object obj, long delayMillis) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
-    }
-
-    /**
-     * Enqueue a message to this state machine after a delay.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessageDelayed(int what, int arg1, long delayMillis) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageDelayed(obtainMessage(what, arg1), delayMillis);
-    }
-
-    /**
-     * Enqueue a message to this state machine after a delay.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessageDelayed(int what, int arg1, int arg2, long delayMillis) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageDelayed(obtainMessage(what, arg1, arg2), delayMillis);
-    }
-
-    /**
-     * Enqueue a message to this state machine after a delay.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessageDelayed(int what, int arg1, int arg2, Object obj,
-            long delayMillis) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageDelayed(obtainMessage(what, arg1, arg2, obj), delayMillis);
-    }
-
-    /**
-     * Enqueue a message to this state machine after a delay.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    public void sendMessageDelayed(Message msg, long delayMillis) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageDelayed(msg, delayMillis);
-    }
-
-    /**
-     * Enqueue a message to the front of the queue for this state machine.
-     * Protected, may only be called by instances of StateMachine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    protected final void sendMessageAtFrontOfQueue(int what) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageAtFrontOfQueue(obtainMessage(what));
-    }
-
-    /**
-     * Enqueue a message to the front of the queue for this state machine.
-     * Protected, may only be called by instances of StateMachine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
-    }
-
-    /**
-     * Enqueue a message to the front of the queue for this state machine.
-     * Protected, may only be called by instances of StateMachine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    protected final void sendMessageAtFrontOfQueue(int what, int arg1) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1));
-    }
-
-
-    /**
-     * Enqueue a message to the front of the queue for this state machine.
-     * Protected, may only be called by instances of StateMachine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2));
-    }
-
-    /**
-     * Enqueue a message to the front of the queue for this state machine.
-     * Protected, may only be called by instances of StateMachine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2, Object obj) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2, obj));
-    }
-
-    /**
-     * Enqueue a message to the front of the queue for this state machine.
-     * Protected, may only be called by instances of StateMachine.
-     *
-     * Message is ignored if state machine has quit.
-     */
-    protected final void sendMessageAtFrontOfQueue(Message msg) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.sendMessageAtFrontOfQueue(msg);
-    }
-
-    /**
-     * Removes a message from the message queue.
-     * Protected, may only be called by instances of StateMachine.
-     */
-    protected final void removeMessages(int what) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.removeMessages(what);
-    }
-
-    /**
-     * Removes a message from the deferred messages queue.
-     */
-    protected final void removeDeferredMessages(int what) {
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
-        while (iterator.hasNext()) {
-            Message msg = iterator.next();
-            if (msg.what == what) iterator.remove();
-        }
-    }
-
-    /**
-     * Check if there are any pending messages with code 'what' in deferred messages queue.
-     */
-    protected final boolean hasDeferredMessages(int what) {
-        SmHandler smh = mSmHandler;
-        if (smh == null) return false;
-
-        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
-        while (iterator.hasNext()) {
-            Message msg = iterator.next();
-            if (msg.what == what) return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Check if there are any pending posts of messages with code 'what' in
-     * the message queue. This does NOT check messages in deferred message queue.
-     */
-    protected final boolean hasMessages(int what) {
-        SmHandler smh = mSmHandler;
-        if (smh == null) return false;
-
-        return smh.hasMessages(what);
-    }
-
-    /**
-     * Validate that the message was sent by
-     * {@link StateMachine#quit} or {@link StateMachine#quitNow}.
-     * */
-    protected final boolean isQuit(Message msg) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return msg.what == SM_QUIT_CMD;
-
-        return smh.isQuit(msg);
-    }
-
-    /**
-     * Quit the state machine after all currently queued up messages are processed.
-     */
-    public final void quit() {
-        // mSmHandler can be null if the state machine is already stopped.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.quit();
-    }
-
-    /**
-     * Quit the state machine immediately all currently queued messages will be discarded.
-     */
-    public final void quitNow() {
-        // mSmHandler can be null if the state machine is already stopped.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.quitNow();
-    }
-
-    /**
-     * @return if debugging is enabled
-     */
-    public boolean isDbg() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return false;
-
-        return smh.isDbg();
-    }
-
-    /**
-     * Set debug enable/disabled.
-     *
-     * @param dbg is true to enable debugging.
-     */
-    public void setDbg(boolean dbg) {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        smh.setDbg(dbg);
-    }
-
-    /**
-     * Start the state machine.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void start() {
-        // mSmHandler can be null if the state machine has quit.
-        SmHandler smh = mSmHandler;
-        if (smh == null) return;
-
-        /** Send the complete construction message */
-        smh.completeConstruction();
-    }
-
-    /**
-     * Dump the current state.
-     *
-     * @param fd
-     * @param pw
-     * @param args
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(getName() + ":");
-        pw.println(" total records=" + getLogRecCount());
-        for (int i = 0; i < getLogRecSize(); i++) {
-            pw.println(" rec[" + i + "]: " + getLogRec(i));
-            pw.flush();
-        }
-        final IState curState = getCurrentState();
-        pw.println("curState=" + (curState == null ? "<QUIT>" : curState.getName()));
-    }
-
-    @Override
-    public String toString() {
-        String name = "(null)";
-        String state = "(null)";
-        try {
-            name = mName.toString();
-            state = mSmHandler.getCurrentState().getName().toString();
-        } catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
-            // Will use default(s) initialized above.
-        }
-        return "name=" + name + " state=" + state;
-    }
-
-    /**
-     * Log with debug and add to the LogRecords.
-     *
-     * @param s is string log
-     */
-    protected void logAndAddLogRec(String s) {
-        addLogRec(s);
-        log(s);
-    }
-
-    /**
-     * Log with debug
-     *
-     * @param s is string log
-     */
-    protected void log(String s) {
-        Log.d(mName, s);
-    }
-
-    /**
-     * Log with debug attribute
-     *
-     * @param s is string log
-     */
-    protected void logd(String s) {
-        Log.d(mName, s);
-    }
-
-    /**
-     * Log with verbose attribute
-     *
-     * @param s is string log
-     */
-    protected void logv(String s) {
-        Log.v(mName, s);
-    }
-
-    /**
-     * Log with info attribute
-     *
-     * @param s is string log
-     */
-    protected void logi(String s) {
-        Log.i(mName, s);
-    }
-
-    /**
-     * Log with warning attribute
-     *
-     * @param s is string log
-     */
-    protected void logw(String s) {
-        Log.w(mName, s);
-    }
-
-    /**
-     * Log with error attribute
-     *
-     * @param s is string log
-     */
-    protected void loge(String s) {
-        Log.e(mName, s);
-    }
-
-    /**
-     * Log with error attribute
-     *
-     * @param s is string log
-     * @param e is a Throwable which logs additional information.
-     */
-    protected void loge(String s, Throwable e) {
-        Log.e(mName, s, e);
-    }
-}
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index db0cc27..74fb543 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -20,23 +20,11 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Suffix added to a number to signify size in bytes. -->
     <string name="byteShort">B</string>
-    <!-- Suffix added to a number to signify size in kilobytes (1000 bytes).
-        If you retain the Latin script for the localization, please use the lowercase
-        'k', as it signifies 1000 bytes as opposed to 1024 bytes. -->
-    <string name="kilobyteShort">kB</string>
-    <!-- Suffix added to a number to signify size in megabytes. -->
-    <string name="megabyteShort">MB</string>
-    <!-- Suffix added to a number to signify size in gigabytes. -->
-    <string name="gigabyteShort">GB</string>
-    <!-- Suffix added to a number to signify size in terabytes. -->
-    <string name="terabyteShort">TB</string>
-    <!-- Suffix added to a number to signify size in petabytes. -->
-    <string name="petabyteShort">PB</string>
-    <!-- Format string used to add a suffix like "kB" or "MB" to a number
-         to display a size in kilobytes, megabytes, or other size units.
-         Some languages (like French) will want to add a space between
-         the placeholders. -->
-    <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g> <xliff:g id="unit" example="MB">%2$s</xliff:g></string>
+    <!-- Format string used to add a suffix like "B" to a number
+         to display a size in bytes.
+         Some languages may want to remove the space between the placeholders
+         or replace it with a non-breaking space. -->
+    <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g> <xliff:g id="unit" example="B">%2$s</xliff:g></string>
 
     <!-- Used in Contacts for a field that has no label and in Note Pad
          for a note with no name. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4ad95b6..0063956 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -737,7 +737,6 @@
   <java-symbol type="string" name="fileSizeSuffix" />
   <java-symbol type="string" name="force_close" />
   <java-symbol type="string" name="gadget_host_error_inflating" />
-  <java-symbol type="string" name="gigabyteShort" />
   <java-symbol type="string" name="gpsNotifMessage" />
   <java-symbol type="string" name="gpsNotifTicker" />
   <java-symbol type="string" name="gpsNotifTitle" />
@@ -793,7 +792,6 @@
   <java-symbol type="string" name="keyboardview_keycode_enter" />
   <java-symbol type="string" name="keyboardview_keycode_mode_change" />
   <java-symbol type="string" name="keyboardview_keycode_shift" />
-  <java-symbol type="string" name="kilobyteShort" />
   <java-symbol type="string" name="last_month" />
   <java-symbol type="string" name="launchBrowserDefault" />
   <java-symbol type="string" name="lock_to_app_unlock_pin" />
@@ -810,7 +808,6 @@
   <java-symbol type="string" name="lockscreen_emergency_call" />
   <java-symbol type="string" name="lockscreen_return_to_call" />
   <java-symbol type="string" name="low_memory" />
-  <java-symbol type="string" name="megabyteShort" />
   <java-symbol type="string" name="midnight" />
   <java-symbol type="string" name="mismatchPin" />
   <java-symbol type="string" name="mmiComplete" />
@@ -840,7 +837,6 @@
   <java-symbol type="string" name="passwordIncorrect" />
   <java-symbol type="string" name="perms_description_app" />
   <java-symbol type="string" name="perms_new_perm_prefix" />
-  <java-symbol type="string" name="petabyteShort" />
   <java-symbol type="string" name="peerTtyModeFull" />
   <java-symbol type="string" name="peerTtyModeHco" />
   <java-symbol type="string" name="peerTtyModeVco" />
@@ -1016,7 +1012,6 @@
   <java-symbol type="string" name="sync_really_delete" />
   <java-symbol type="string" name="sync_too_many_deletes_desc" />
   <java-symbol type="string" name="sync_undo_deletes" />
-  <java-symbol type="string" name="terabyteShort" />
   <java-symbol type="string" name="text_copied" />
   <java-symbol type="string" name="time_of_day" />
   <java-symbol type="string" name="time_picker_decrement_hour_button" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 5db6a3e..bfb2fd5 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -273,13 +273,14 @@
             newerConfig.orientation = orientation == ORIENTATION_LANDSCAPE
                     ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
             newerConfig.seq = seq + 2;
-            final ActivityClientRecord r = getActivityClientRecord(activity);
-            activityThread.updatePendingActivityConfiguration(r, newerConfig);
+            activityThread.updatePendingActivityConfiguration(activity.getActivityToken(),
+                    newerConfig);
 
             final Configuration olderConfig = new Configuration();
             olderConfig.orientation = orientation;
             olderConfig.seq = seq + 1;
 
+            final ActivityClientRecord r = getActivityClientRecord(activity);
             activityThread.handleActivityConfigurationChanged(r, olderConfig, INVALID_DISPLAY);
             assertEquals(numOfConfig, activity.mNumOfConfigChanges);
             assertEquals(olderConfig.orientation, activity.mConfig.orientation);
@@ -504,7 +505,8 @@
                     ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
 
             final ActivityClientRecord r = getActivityClientRecord(activity);
-            activityThread.updatePendingActivityConfiguration(r, newActivityConfig);
+            activityThread.updatePendingActivityConfiguration(activity.getActivityToken(),
+                    newActivityConfig);
             activityThread.handleActivityConfigurationChanged(r, newActivityConfig,
                     INVALID_DISPLAY);
 
diff --git a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
deleted file mode 100644
index b85cb9c..0000000
--- a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
+++ /dev/null
@@ -1,2022 +0,0 @@
-/**
- * Copyright (C) 2009 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.internal.util;
-
-import android.os.Debug;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import com.android.internal.util.StateMachine.LogRec;
-
-import junit.framework.TestCase;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * Test for StateMachine.
- */
-public class StateMachineTest extends TestCase {
-    private static final String ENTER = "enter";
-    private static final String EXIT = "exit";
-    private static final String ON_QUITTING = "ON_QUITTING";
-
-    private static final int TEST_CMD_1 = 1;
-    private static final int TEST_CMD_2 = 2;
-    private static final int TEST_CMD_3 = 3;
-    private static final int TEST_CMD_4 = 4;
-    private static final int TEST_CMD_5 = 5;
-    private static final int TEST_CMD_6 = 6;
-
-    private static final boolean DBG = true;
-    private static final boolean WAIT_FOR_DEBUGGER = false;
-    private static final String TAG = "StateMachineTest";
-
-    private void sleep(int millis) {
-        try {
-            Thread.sleep(millis);
-        } catch(InterruptedException e) {
-        }
-    }
-
-    private void dumpLogRecs(StateMachine sm) {
-        int size = sm.getLogRecSize();
-        tlog("size=" + size + " count=" + sm.getLogRecCount());
-        for (int i = 0; i < size; i++) {
-            LogRec lr = sm.getLogRec(i);
-            tlog(lr.toString());
-        }
-    }
-
-    private void dumpLogRecs(Collection<LogRec> clr) {
-        int size = clr.size();
-        tlog("size=" + size);
-        for (LogRec lr : clr) {
-            tlog(lr.toString());
-        }
-    }
-
-    /**
-     * Tests {@link StateMachine#toString()}.
-     */
-    class StateMachineToStringTest extends StateMachine {
-        StateMachineToStringTest(String name) {
-            super(name);
-        }
-    }
-
-    class ExampleState extends State {
-        String mName;
-
-        ExampleState(String name) {
-            mName = name;
-        }
-
-        @Override
-        public String getName() {
-            return mName;
-        }
-    }
-
-    @SmallTest
-    public void testToStringSucceedsEvenIfMachineHasNoStates() throws Exception {
-        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
-        assertTrue(stateMachine.toString().contains("TestStateMachine"));
-    }
-
-    @SmallTest
-    public void testToStringSucceedsEvenIfStateHasNoName() throws Exception {
-        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
-        State exampleState = new ExampleState(null);
-        stateMachine.addState(exampleState);
-        stateMachine.setInitialState(exampleState);
-        stateMachine.start();
-        assertTrue(stateMachine.toString().contains("TestStateMachine"));
-        assertTrue(stateMachine.toString().contains("(null)"));
-    }
-
-    @SmallTest
-    public void testToStringIncludesMachineAndStateNames() throws Exception {
-        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
-        State exampleState = new ExampleState("exampleState");
-        stateMachine.addState(exampleState);
-        stateMachine.setInitialState(exampleState);
-        stateMachine.start();
-        assertTrue(stateMachine.toString().contains("TestStateMachine"));
-        assertTrue(stateMachine.toString().contains("exampleState"));
-    }
-
-    @SmallTest
-    public void testToStringDoesNotContainMultipleLines() throws Exception {
-        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
-        State exampleState = new ExampleState("exampleState");
-        stateMachine.addState(exampleState);
-        stateMachine.setInitialState(exampleState);
-        stateMachine.start();
-        assertFalse(stateMachine.toString().contains("\n"));
-    }
-
-    /**
-     * Tests {@link StateMachine#quit()}.
-     */
-    class StateMachineQuitTest extends StateMachine {
-        Collection<LogRec> mLogRecs;
-
-        StateMachineQuitTest(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-
-        @Override
-        public void onQuitting() {
-            tlog("onQuitting");
-            addLogRec(ON_QUITTING);
-            mLogRecs = mThisSm.copyLogRecs();
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        class S1 extends State {
-            @Override
-            public void exit() {
-                tlog("S1.exit");
-                addLogRec(EXIT);
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                switch(message.what) {
-                    // Sleep and assume the other messages will be queued up.
-                    case TEST_CMD_1: {
-                        tlog("TEST_CMD_1");
-                        sleep(500);
-                        quit();
-                        break;
-                    }
-                    default: {
-                        tlog("default what=" + message.what);
-                        break;
-                    }
-                }
-                return HANDLED;
-            }
-        }
-
-        private StateMachineQuitTest mThisSm;
-        private S1 mS1 = new S1();
-    }
-
-    @SmallTest
-    public void testStateMachineQuit() throws Exception {
-        if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
-
-        StateMachineQuitTest smQuitTest = new StateMachineQuitTest("smQuitTest");
-        smQuitTest.start();
-        if (smQuitTest.isDbg()) tlog("testStateMachineQuit E");
-
-        synchronized (smQuitTest) {
-
-            // Send 6 message we'll quit on the first but all 6 should be processed before quitting.
-            for (int i = 1; i <= 6; i++) {
-                smQuitTest.sendMessage(smQuitTest.obtainMessage(i));
-            }
-
-            try {
-                // wait for the messages to be handled
-                smQuitTest.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachineQuit: exception while waiting " + e.getMessage());
-            }
-        }
-
-        dumpLogRecs(smQuitTest.mLogRecs);
-        assertEquals(8, smQuitTest.mLogRecs.size());
-
-        LogRec lr;
-        Iterator<LogRec> itr = smQuitTest.mLogRecs.iterator();
-        for (int i = 1; i <= 6; i++) {
-            lr = itr.next();
-            assertEquals(i, lr.getWhat());
-            assertEquals(smQuitTest.mS1, lr.getState());
-            assertEquals(smQuitTest.mS1, lr.getOriginalState());
-        }
-        lr = itr.next();
-        assertEquals(EXIT, lr.getInfo());
-        assertEquals(smQuitTest.mS1, lr.getState());
-
-        lr = itr.next();
-        assertEquals(ON_QUITTING, lr.getInfo());
-
-        if (smQuitTest.isDbg()) tlog("testStateMachineQuit X");
-    }
-
-    /**
-     * Tests {@link StateMachine#quitNow()}
-     */
-    class StateMachineQuitNowTest extends StateMachine {
-        public Collection<LogRec> mLogRecs = null;
-
-        StateMachineQuitNowTest(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-
-        @Override
-        public void onQuitting() {
-            tlog("onQuitting");
-            addLogRec(ON_QUITTING);
-            // Get a copy of the log records since we're quitting and they will disappear
-            mLogRecs = mThisSm.copyLogRecs();
-
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        class S1 extends State {
-            @Override
-            public void exit() {
-                tlog("S1.exit");
-                addLogRec(EXIT);
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                switch(message.what) {
-                    // Sleep and assume the other messages will be queued up.
-                    case TEST_CMD_1: {
-                        tlog("TEST_CMD_1");
-                        sleep(500);
-                        quitNow();
-                        break;
-                    }
-                    default: {
-                        tlog("default what=" + message.what);
-                        break;
-                    }
-                }
-                return HANDLED;
-            }
-        }
-
-        private StateMachineQuitNowTest mThisSm;
-        private S1 mS1 = new S1();
-    }
-
-    @SmallTest
-    public void testStateMachineQuitNow() throws Exception {
-        if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
-
-        StateMachineQuitNowTest smQuitNowTest = new StateMachineQuitNowTest("smQuitNowTest");
-        smQuitNowTest.start();
-        if (smQuitNowTest.isDbg()) tlog("testStateMachineQuitNow E");
-
-        synchronized (smQuitNowTest) {
-
-            // Send 6 message we'll QuitNow on the first even though
-            // we send 6 only one will be processed.
-            for (int i = 1; i <= 6; i++) {
-                smQuitNowTest.sendMessage(smQuitNowTest.obtainMessage(i));
-            }
-
-            try {
-                // wait for the messages to be handled
-                smQuitNowTest.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachineQuitNow: exception while waiting " + e.getMessage());
-            }
-        }
-
-        tlog("testStateMachineQuiteNow: logRecs=" + smQuitNowTest.mLogRecs);
-        assertEquals(3, smQuitNowTest.mLogRecs.size());
-
-        Iterator<LogRec> itr = smQuitNowTest.mLogRecs.iterator();
-        LogRec lr = itr.next();
-        assertEquals(1, lr.getWhat());
-        assertEquals(smQuitNowTest.mS1, lr.getState());
-        assertEquals(smQuitNowTest.mS1, lr.getOriginalState());
-
-        lr = itr.next();
-        assertEquals(EXIT, lr.getInfo());
-        assertEquals(smQuitNowTest.mS1, lr.getState());
-
-        lr = itr.next();
-        assertEquals(ON_QUITTING, lr.getInfo());
-
-        if (smQuitNowTest.isDbg()) tlog("testStateMachineQuitNow X");
-    }
-
-    /**
-     * Tests {@link StateMachine#quitNow()} immediately after {@link StateMachine#start()}.
-     */
-    class StateMachineQuitNowAfterStartTest extends StateMachine {
-        Collection<LogRec> mLogRecs;
-
-        StateMachineQuitNowAfterStartTest(String name, Looper looper) {
-            super(name, looper);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-
-        @Override
-        public void onQuitting() {
-            tlog("onQuitting");
-            addLogRec(ON_QUITTING);
-            mLogRecs = mThisSm.copyLogRecs();
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        class S1 extends State {
-            @Override
-            public void enter() {
-                tlog("S1.enter");
-                addLogRec(ENTER);
-            }
-            @Override
-            public void exit() {
-                tlog("S1.exit");
-                addLogRec(EXIT);
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                switch(message.what) {
-                    // Sleep and assume the other messages will be queued up.
-                    case TEST_CMD_1: {
-                        tlog("TEST_CMD_1");
-                        sleep(500);
-                        break;
-                    }
-                    default: {
-                        tlog("default what=" + message.what);
-                        break;
-                    }
-                }
-                return HANDLED;
-            }
-        }
-
-        private StateMachineQuitNowAfterStartTest mThisSm;
-        private S1 mS1 = new S1();
-    }
-
-    /**
-     * When quitNow() is called immediately after start(), the QUIT_CMD gets processed
-     * before the INIT_CMD. This test ensures that the StateMachine can gracefully handle
-     * this sequencing of messages (QUIT before INIT).
-     */
-    @SmallTest
-    public void testStateMachineQuitNowAfterStart() throws Exception {
-        if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
-
-        TestLooper testLooper = new TestLooper();
-        StateMachineQuitNowAfterStartTest smQuitNowAfterStartTest =
-                new StateMachineQuitNowAfterStartTest(
-                        "smQuitNowAfterStartTest", testLooper.getLooper());
-        smQuitNowAfterStartTest.start();
-        smQuitNowAfterStartTest.quitNow();
-        if (smQuitNowAfterStartTest.isDbg()) tlog("testStateMachineQuitNowAfterStart E");
-
-        testLooper.dispatchAll();
-        dumpLogRecs(smQuitNowAfterStartTest.mLogRecs);
-        assertEquals(2, smQuitNowAfterStartTest.mLogRecs.size());
-
-        LogRec lr;
-        Iterator<LogRec> itr = smQuitNowAfterStartTest.mLogRecs.iterator();
-        lr = itr.next();
-        assertEquals(EXIT, lr.getInfo());
-        assertEquals(smQuitNowAfterStartTest.mS1, lr.getState());
-
-        lr = itr.next();
-        assertEquals(ON_QUITTING, lr.getInfo());
-
-        if (smQuitNowAfterStartTest.isDbg()) tlog("testStateMachineQuitNowAfterStart X");
-    }
-
-    /**
-     * Test enter/exit can use transitionTo
-     */
-    class StateMachineEnterExitTransitionToTest extends StateMachine {
-
-        StateMachineEnterExitTransitionToTest(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-            addState(mS2);
-            addState(mS3);
-            addState(mS4);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-
-        class S1 extends State {
-            @Override
-            public void enter() {
-                // Test transitions in enter on the initial state work
-                addLogRec(ENTER);
-                transitionTo(mS2);
-                tlog("S1.enter");
-            }
-            @Override
-            public void exit() {
-                addLogRec(EXIT);
-                tlog("S1.exit");
-            }
-        }
-
-        class S2 extends State {
-            @Override
-            public void enter() {
-                addLogRec(ENTER);
-                tlog("S2.enter");
-            }
-            @Override
-            public void exit() {
-                // Test transition in exit work
-                transitionTo(mS4);
-
-                assertEquals(TEST_CMD_1, getCurrentMessage().what);
-                addLogRec(EXIT);
-
-                tlog("S2.exit");
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                // Start a transition to S3 but it will be
-                // changed to a transition to S4 in exit
-                transitionTo(mS3);
-                tlog("S2.processMessage");
-                return HANDLED;
-            }
-        }
-
-        class S3 extends State {
-            @Override
-            public void enter() {
-                addLogRec(ENTER);
-                tlog("S3.enter");
-            }
-            @Override
-            public void exit() {
-                addLogRec(EXIT);
-                tlog("S3.exit");
-            }
-        }
-
-        class S4 extends State {
-            @Override
-            public void enter() {
-                addLogRec(ENTER);
-                // Test that we can do halting in an enter/exit
-                transitionToHaltingState();
-                tlog("S4.enter");
-            }
-            @Override
-            public void exit() {
-                addLogRec(EXIT);
-                tlog("S4.exit");
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachineEnterExitTransitionToTest mThisSm;
-        private S1 mS1 = new S1();
-        private S2 mS2 = new S2();
-        private S3 mS3 = new S3();
-        private S4 mS4 = new S4();
-    }
-
-    @SmallTest
-    public void testStateMachineEnterExitTransitionToTest() throws Exception {
-        //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
-
-        StateMachineEnterExitTransitionToTest smEnterExitTransitionToTest =
-                new StateMachineEnterExitTransitionToTest("smEnterExitTransitionToTest");
-        smEnterExitTransitionToTest.start();
-        if (smEnterExitTransitionToTest.isDbg()) {
-            tlog("testStateMachineEnterExitTransitionToTest E");
-        }
-
-        synchronized (smEnterExitTransitionToTest) {
-            smEnterExitTransitionToTest.sendMessage(TEST_CMD_1);
-
-            try {
-                // wait for the messages to be handled
-                smEnterExitTransitionToTest.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachineEnterExitTransitionToTest: exception while waiting "
-                    + e.getMessage());
-            }
-        }
-
-        dumpLogRecs(smEnterExitTransitionToTest);
-
-        assertEquals(9, smEnterExitTransitionToTest.getLogRecCount());
-        LogRec lr;
-
-        lr = smEnterExitTransitionToTest.getLogRec(0);
-        assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS1, lr.getState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(1);
-        assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS1, lr.getState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(2);
-        assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(3);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
-        assertEquals(smEnterExitTransitionToTest.mS2, lr.getOriginalState());
-        assertEquals(smEnterExitTransitionToTest.mS3, lr.getDestState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(4);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
-        assertEquals(smEnterExitTransitionToTest.mS2, lr.getOriginalState());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
-        assertEquals(EXIT, lr.getInfo());
-
-        lr = smEnterExitTransitionToTest.getLogRec(5);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS3, lr.getState());
-        assertEquals(smEnterExitTransitionToTest.mS3, lr.getOriginalState());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(6);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS3, lr.getState());
-        assertEquals(smEnterExitTransitionToTest.mS3, lr.getOriginalState());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(7);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getState());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getOriginalState());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
-
-        lr = smEnterExitTransitionToTest.getLogRec(8);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getState());
-        assertEquals(smEnterExitTransitionToTest.mS4, lr.getOriginalState());
-
-        if (smEnterExitTransitionToTest.isDbg()) {
-            tlog("testStateMachineEnterExitTransitionToTest X");
-        }
-    }
-
-    /**
-     * Tests that ProcessedMessage works as a circular buffer.
-     */
-    class StateMachine0 extends StateMachine {
-        StateMachine0(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-            setLogRecSize(3);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-
-        class S1 extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_6) {
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine0 mThisSm;
-        private S1 mS1 = new S1();
-    }
-
-    @SmallTest
-    public void testStateMachine0() throws Exception {
-        //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
-
-        StateMachine0 sm0 = new StateMachine0("sm0");
-        sm0.start();
-        if (sm0.isDbg()) tlog("testStateMachine0 E");
-
-        synchronized (sm0) {
-            // Send 6 messages
-            for (int i = 1; i <= 6; i++) {
-                sm0.sendMessage(sm0.obtainMessage(i));
-            }
-
-            try {
-                // wait for the messages to be handled
-                sm0.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine0: exception while waiting " + e.getMessage());
-            }
-        }
-
-        assertEquals(6, sm0.getLogRecCount());
-        assertEquals(3, sm0.getLogRecSize());
-
-        dumpLogRecs(sm0);
-
-        LogRec lr;
-        lr = sm0.getLogRec(0);
-        assertEquals(TEST_CMD_4, lr.getWhat());
-        assertEquals(sm0.mS1, lr.getState());
-        assertEquals(sm0.mS1, lr.getOriginalState());
-
-        lr = sm0.getLogRec(1);
-        assertEquals(TEST_CMD_5, lr.getWhat());
-        assertEquals(sm0.mS1, lr.getState());
-        assertEquals(sm0.mS1, lr.getOriginalState());
-
-        lr = sm0.getLogRec(2);
-        assertEquals(TEST_CMD_6, lr.getWhat());
-        assertEquals(sm0.mS1, lr.getState());
-        assertEquals(sm0.mS1, lr.getOriginalState());
-
-        if (sm0.isDbg()) tlog("testStateMachine0 X");
-    }
-
-    /**
-     * This tests enter/exit and transitions to the same state.
-     * The state machine has one state, it receives two messages
-     * in state mS1. With the first message it transitions to
-     * itself which causes it to be exited and reentered.
-     */
-    class StateMachine1 extends StateMachine {
-        StateMachine1(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-            if (DBG) tlog("StateMachine1: ctor X");
-        }
-
-        class S1 extends State {
-            @Override
-            public void enter() {
-                mEnterCount++;
-            }
-            @Override
-            public void exit() {
-                mExitCount++;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_1) {
-                    assertEquals(1, mEnterCount);
-                    assertEquals(0, mExitCount);
-                    transitionTo(mS1);
-                } else if (message.what == TEST_CMD_2) {
-                    assertEquals(2, mEnterCount);
-                    assertEquals(1, mExitCount);
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine1 mThisSm;
-        private S1 mS1 = new S1();
-
-        private int mEnterCount;
-        private int mExitCount;
-    }
-
-    @MediumTest
-    public void testStateMachine1() throws Exception {
-        StateMachine1 sm1 = new StateMachine1("sm1");
-        sm1.start();
-        if (sm1.isDbg()) tlog("testStateMachine1 E");
-
-        synchronized (sm1) {
-            // Send two messages
-            sm1.sendMessage(TEST_CMD_1);
-            sm1.sendMessage(TEST_CMD_2);
-
-            try {
-                // wait for the messages to be handled
-                sm1.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine1: exception while waiting " + e.getMessage());
-            }
-        }
-
-        assertEquals(2, sm1.mEnterCount);
-        assertEquals(2, sm1.mExitCount);
-
-        assertEquals(2, sm1.getLogRecSize());
-
-        LogRec lr;
-        lr = sm1.getLogRec(0);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(sm1.mS1, lr.getState());
-        assertEquals(sm1.mS1, lr.getOriginalState());
-
-        lr = sm1.getLogRec(1);
-        assertEquals(TEST_CMD_2, lr.getWhat());
-        assertEquals(sm1.mS1, lr.getState());
-        assertEquals(sm1.mS1, lr.getOriginalState());
-
-        assertEquals(2, sm1.mEnterCount);
-        assertEquals(2, sm1.mExitCount);
-
-        if (sm1.isDbg()) tlog("testStateMachine1 X");
-    }
-
-    /**
-     * Test deferring messages and states with no parents. The state machine
-     * has two states, it receives two messages in state mS1 deferring them
-     * until what == TEST_CMD_2 and then transitions to state mS2. State
-     * mS2 then receives both of the deferred messages first TEST_CMD_1 and
-     * then TEST_CMD_2.
-     */
-    class StateMachine2 extends StateMachine {
-        StateMachine2(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup the hierarchy
-            addState(mS1);
-            addState(mS2);
-
-            // Set the initial state
-            setInitialState(mS1);
-            if (DBG) tlog("StateMachine2: ctor X");
-        }
-
-        class S1 extends State {
-            @Override
-            public void enter() {
-                mDidEnter = true;
-            }
-            @Override
-            public void exit() {
-                mDidExit = true;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                deferMessage(message);
-                if (message.what == TEST_CMD_2) {
-                    transitionTo(mS2);
-                }
-                return HANDLED;
-            }
-        }
-
-        class S2 extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_2) {
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine2 mThisSm;
-        private S1 mS1 = new S1();
-        private S2 mS2 = new S2();
-
-        private boolean mDidEnter = false;
-        private boolean mDidExit = false;
-    }
-
-    @MediumTest
-    public void testStateMachine2() throws Exception {
-        StateMachine2 sm2 = new StateMachine2("sm2");
-        sm2.start();
-        if (sm2.isDbg()) tlog("testStateMachine2 E");
-
-        synchronized (sm2) {
-            // Send two messages
-            sm2.sendMessage(TEST_CMD_1);
-            sm2.sendMessage(TEST_CMD_2);
-
-            try {
-                // wait for the messages to be handled
-                sm2.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine2: exception while waiting " + e.getMessage());
-            }
-        }
-
-        assertEquals(4, sm2.getLogRecSize());
-
-        LogRec lr;
-        lr = sm2.getLogRec(0);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(sm2.mS1, lr.getState());
-
-        lr = sm2.getLogRec(1);
-        assertEquals(TEST_CMD_2, lr.getWhat());
-        assertEquals(sm2.mS1, lr.getState());
-
-        lr = sm2.getLogRec(2);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(sm2.mS2, lr.getState());
-
-        lr = sm2.getLogRec(3);
-        assertEquals(TEST_CMD_2, lr.getWhat());
-        assertEquals(sm2.mS2, lr.getState());
-
-        assertTrue(sm2.mDidEnter);
-        assertTrue(sm2.mDidExit);
-
-        if (sm2.isDbg()) tlog("testStateMachine2 X");
-    }
-
-    /**
-     * Test that unhandled messages in a child are handled by the parent.
-     * When TEST_CMD_2 is received.
-     */
-    class StateMachine3 extends StateMachine {
-        StateMachine3(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup the simplest hierarchy of two states
-            // mParentState and mChildState.
-            // (Use indentation to help visualize hierarchy)
-            addState(mParentState);
-                addState(mChildState, mParentState);
-
-            // Set the initial state will be the child
-            setInitialState(mChildState);
-            if (DBG) tlog("StateMachine3: ctor X");
-        }
-
-        class ParentState extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_2) {
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        class ChildState extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                return NOT_HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine3 mThisSm;
-        private ParentState mParentState = new ParentState();
-        private ChildState mChildState = new ChildState();
-    }
-
-    @MediumTest
-    public void testStateMachine3() throws Exception {
-        StateMachine3 sm3 = new StateMachine3("sm3");
-        sm3.start();
-        if (sm3.isDbg()) tlog("testStateMachine3 E");
-
-        synchronized (sm3) {
-            // Send two messages
-            sm3.sendMessage(TEST_CMD_1);
-            sm3.sendMessage(TEST_CMD_2);
-
-            try {
-                // wait for the messages to be handled
-                sm3.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine3: exception while waiting " + e.getMessage());
-            }
-        }
-
-        assertEquals(2, sm3.getLogRecSize());
-
-        LogRec lr;
-        lr = sm3.getLogRec(0);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(sm3.mParentState, lr.getState());
-        assertEquals(sm3.mChildState, lr.getOriginalState());
-
-        lr = sm3.getLogRec(1);
-        assertEquals(TEST_CMD_2, lr.getWhat());
-        assertEquals(sm3.mParentState, lr.getState());
-        assertEquals(sm3.mChildState, lr.getOriginalState());
-
-        if (sm3.isDbg()) tlog("testStateMachine3 X");
-    }
-
-    /**
-     * Test a hierarchy of 3 states a parent and two children
-     * with transition from child 1 to child 2 and child 2
-     * lets the parent handle the messages.
-     */
-    class StateMachine4 extends StateMachine {
-        StateMachine4(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup a hierarchy of three states
-            // mParentState, mChildState1 & mChildState2
-            // (Use indentation to help visualize hierarchy)
-            addState(mParentState);
-                addState(mChildState1, mParentState);
-                addState(mChildState2, mParentState);
-
-            // Set the initial state will be child 1
-            setInitialState(mChildState1);
-            if (DBG) tlog("StateMachine4: ctor X");
-        }
-
-        class ParentState extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_2) {
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        class ChildState1 extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                transitionTo(mChildState2);
-                return HANDLED;
-            }
-        }
-
-        class ChildState2 extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                return NOT_HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine4 mThisSm;
-        private ParentState mParentState = new ParentState();
-        private ChildState1 mChildState1 = new ChildState1();
-        private ChildState2 mChildState2 = new ChildState2();
-    }
-
-    @MediumTest
-    public void testStateMachine4() throws Exception {
-        StateMachine4 sm4 = new StateMachine4("sm4");
-        sm4.start();
-        if (sm4.isDbg()) tlog("testStateMachine4 E");
-
-        synchronized (sm4) {
-            // Send two messages
-            sm4.sendMessage(TEST_CMD_1);
-            sm4.sendMessage(TEST_CMD_2);
-
-            try {
-                // wait for the messages to be handled
-                sm4.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine4: exception while waiting " + e.getMessage());
-            }
-        }
-
-
-        assertEquals(2, sm4.getLogRecSize());
-
-        LogRec lr;
-        lr = sm4.getLogRec(0);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(sm4.mChildState1, lr.getState());
-        assertEquals(sm4.mChildState1, lr.getOriginalState());
-
-        lr = sm4.getLogRec(1);
-        assertEquals(TEST_CMD_2, lr.getWhat());
-        assertEquals(sm4.mParentState, lr.getState());
-        assertEquals(sm4.mChildState2, lr.getOriginalState());
-
-        if (sm4.isDbg()) tlog("testStateMachine4 X");
-    }
-
-    /**
-     * Test transition from one child to another of a "complex"
-     * hierarchy with two parents and multiple children.
-     */
-    class StateMachine5 extends StateMachine {
-        StateMachine5(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup a hierarchy with two parents and some children.
-            // (Use indentation to help visualize hierarchy)
-            addState(mParentState1);
-                addState(mChildState1, mParentState1);
-                addState(mChildState2, mParentState1);
-
-            addState(mParentState2);
-                addState(mChildState3, mParentState2);
-                addState(mChildState4, mParentState2);
-                    addState(mChildState5, mChildState4);
-
-            // Set the initial state will be the child
-            setInitialState(mChildState1);
-            if (DBG) tlog("StateMachine5: ctor X");
-        }
-
-        class ParentState1 extends State {
-            @Override
-            public void enter() {
-                mParentState1EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mParentState1ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                return HANDLED;
-            }
-        }
-
-        class ChildState1 extends State {
-            @Override
-            public void enter() {
-                mChildState1EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mChildState1ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                assertEquals(1, mParentState1EnterCount);
-                assertEquals(0, mParentState1ExitCount);
-                assertEquals(1, mChildState1EnterCount);
-                assertEquals(0, mChildState1ExitCount);
-                assertEquals(0, mChildState2EnterCount);
-                assertEquals(0, mChildState2ExitCount);
-                assertEquals(0, mParentState2EnterCount);
-                assertEquals(0, mParentState2ExitCount);
-                assertEquals(0, mChildState3EnterCount);
-                assertEquals(0, mChildState3ExitCount);
-                assertEquals(0, mChildState4EnterCount);
-                assertEquals(0, mChildState4ExitCount);
-                assertEquals(0, mChildState5EnterCount);
-                assertEquals(0, mChildState5ExitCount);
-
-                transitionTo(mChildState2);
-                return HANDLED;
-            }
-        }
-
-        class ChildState2 extends State {
-            @Override
-            public void enter() {
-                mChildState2EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mChildState2ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                assertEquals(1, mParentState1EnterCount);
-                assertEquals(0, mParentState1ExitCount);
-                assertEquals(1, mChildState1EnterCount);
-                assertEquals(1, mChildState1ExitCount);
-                assertEquals(1, mChildState2EnterCount);
-                assertEquals(0, mChildState2ExitCount);
-                assertEquals(0, mParentState2EnterCount);
-                assertEquals(0, mParentState2ExitCount);
-                assertEquals(0, mChildState3EnterCount);
-                assertEquals(0, mChildState3ExitCount);
-                assertEquals(0, mChildState4EnterCount);
-                assertEquals(0, mChildState4ExitCount);
-                assertEquals(0, mChildState5EnterCount);
-                assertEquals(0, mChildState5ExitCount);
-
-                transitionTo(mChildState5);
-                return HANDLED;
-            }
-        }
-
-        class ParentState2 extends State {
-            @Override
-            public void enter() {
-                mParentState2EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mParentState2ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                assertEquals(1, mParentState1EnterCount);
-                assertEquals(1, mParentState1ExitCount);
-                assertEquals(1, mChildState1EnterCount);
-                assertEquals(1, mChildState1ExitCount);
-                assertEquals(1, mChildState2EnterCount);
-                assertEquals(1, mChildState2ExitCount);
-                assertEquals(2, mParentState2EnterCount);
-                assertEquals(1, mParentState2ExitCount);
-                assertEquals(1, mChildState3EnterCount);
-                assertEquals(1, mChildState3ExitCount);
-                assertEquals(2, mChildState4EnterCount);
-                assertEquals(2, mChildState4ExitCount);
-                assertEquals(1, mChildState5EnterCount);
-                assertEquals(1, mChildState5ExitCount);
-
-                transitionToHaltingState();
-                return HANDLED;
-            }
-        }
-
-        class ChildState3 extends State {
-            @Override
-            public void enter() {
-                mChildState3EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mChildState3ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                assertEquals(1, mParentState1EnterCount);
-                assertEquals(1, mParentState1ExitCount);
-                assertEquals(1, mChildState1EnterCount);
-                assertEquals(1, mChildState1ExitCount);
-                assertEquals(1, mChildState2EnterCount);
-                assertEquals(1, mChildState2ExitCount);
-                assertEquals(1, mParentState2EnterCount);
-                assertEquals(0, mParentState2ExitCount);
-                assertEquals(1, mChildState3EnterCount);
-                assertEquals(0, mChildState3ExitCount);
-                assertEquals(1, mChildState4EnterCount);
-                assertEquals(1, mChildState4ExitCount);
-                assertEquals(1, mChildState5EnterCount);
-                assertEquals(1, mChildState5ExitCount);
-
-                transitionTo(mChildState4);
-                return HANDLED;
-            }
-        }
-
-        class ChildState4 extends State {
-            @Override
-            public void enter() {
-                mChildState4EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mChildState4ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                assertEquals(1, mParentState1EnterCount);
-                assertEquals(1, mParentState1ExitCount);
-                assertEquals(1, mChildState1EnterCount);
-                assertEquals(1, mChildState1ExitCount);
-                assertEquals(1, mChildState2EnterCount);
-                assertEquals(1, mChildState2ExitCount);
-                assertEquals(1, mParentState2EnterCount);
-                assertEquals(0, mParentState2ExitCount);
-                assertEquals(1, mChildState3EnterCount);
-                assertEquals(1, mChildState3ExitCount);
-                assertEquals(2, mChildState4EnterCount);
-                assertEquals(1, mChildState4ExitCount);
-                assertEquals(1, mChildState5EnterCount);
-                assertEquals(1, mChildState5ExitCount);
-
-                transitionTo(mParentState2);
-                return HANDLED;
-            }
-        }
-
-        class ChildState5 extends State {
-            @Override
-            public void enter() {
-                mChildState5EnterCount += 1;
-            }
-            @Override
-            public void exit() {
-                mChildState5ExitCount += 1;
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                assertEquals(1, mParentState1EnterCount);
-                assertEquals(1, mParentState1ExitCount);
-                assertEquals(1, mChildState1EnterCount);
-                assertEquals(1, mChildState1ExitCount);
-                assertEquals(1, mChildState2EnterCount);
-                assertEquals(1, mChildState2ExitCount);
-                assertEquals(1, mParentState2EnterCount);
-                assertEquals(0, mParentState2ExitCount);
-                assertEquals(0, mChildState3EnterCount);
-                assertEquals(0, mChildState3ExitCount);
-                assertEquals(1, mChildState4EnterCount);
-                assertEquals(0, mChildState4ExitCount);
-                assertEquals(1, mChildState5EnterCount);
-                assertEquals(0, mChildState5ExitCount);
-
-                transitionTo(mChildState3);
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine5 mThisSm;
-        private ParentState1 mParentState1 = new ParentState1();
-        private ChildState1 mChildState1 = new ChildState1();
-        private ChildState2 mChildState2 = new ChildState2();
-        private ParentState2 mParentState2 = new ParentState2();
-        private ChildState3 mChildState3 = new ChildState3();
-        private ChildState4 mChildState4 = new ChildState4();
-        private ChildState5 mChildState5 = new ChildState5();
-
-        private int mParentState1EnterCount = 0;
-        private int mParentState1ExitCount = 0;
-        private int mChildState1EnterCount = 0;
-        private int mChildState1ExitCount = 0;
-        private int mChildState2EnterCount = 0;
-        private int mChildState2ExitCount = 0;
-        private int mParentState2EnterCount = 0;
-        private int mParentState2ExitCount = 0;
-        private int mChildState3EnterCount = 0;
-        private int mChildState3ExitCount = 0;
-        private int mChildState4EnterCount = 0;
-        private int mChildState4ExitCount = 0;
-        private int mChildState5EnterCount = 0;
-        private int mChildState5ExitCount = 0;
-    }
-
-    @MediumTest
-    public void testStateMachine5() throws Exception {
-        StateMachine5 sm5 = new StateMachine5("sm5");
-        sm5.start();
-        if (sm5.isDbg()) tlog("testStateMachine5 E");
-
-        synchronized (sm5) {
-            // Send 6 messages
-            sm5.sendMessage(TEST_CMD_1);
-            sm5.sendMessage(TEST_CMD_2);
-            sm5.sendMessage(TEST_CMD_3);
-            sm5.sendMessage(TEST_CMD_4);
-            sm5.sendMessage(TEST_CMD_5);
-            sm5.sendMessage(TEST_CMD_6);
-
-            try {
-                // wait for the messages to be handled
-                sm5.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine5: exception while waiting " + e.getMessage());
-            }
-        }
-
-
-        assertEquals(6, sm5.getLogRecSize());
-
-        assertEquals(1, sm5.mParentState1EnterCount);
-        assertEquals(1, sm5.mParentState1ExitCount);
-        assertEquals(1, sm5.mChildState1EnterCount);
-        assertEquals(1, sm5.mChildState1ExitCount);
-        assertEquals(1, sm5.mChildState2EnterCount);
-        assertEquals(1, sm5.mChildState2ExitCount);
-        assertEquals(2, sm5.mParentState2EnterCount);
-        assertEquals(2, sm5.mParentState2ExitCount);
-        assertEquals(1, sm5.mChildState3EnterCount);
-        assertEquals(1, sm5.mChildState3ExitCount);
-        assertEquals(2, sm5.mChildState4EnterCount);
-        assertEquals(2, sm5.mChildState4ExitCount);
-        assertEquals(1, sm5.mChildState5EnterCount);
-        assertEquals(1, sm5.mChildState5ExitCount);
-
-        LogRec lr;
-        lr = sm5.getLogRec(0);
-        assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(sm5.mChildState1, lr.getState());
-        assertEquals(sm5.mChildState1, lr.getOriginalState());
-
-        lr = sm5.getLogRec(1);
-        assertEquals(TEST_CMD_2, lr.getWhat());
-        assertEquals(sm5.mChildState2, lr.getState());
-        assertEquals(sm5.mChildState2, lr.getOriginalState());
-
-        lr = sm5.getLogRec(2);
-        assertEquals(TEST_CMD_3, lr.getWhat());
-        assertEquals(sm5.mChildState5, lr.getState());
-        assertEquals(sm5.mChildState5, lr.getOriginalState());
-
-        lr = sm5.getLogRec(3);
-        assertEquals(TEST_CMD_4, lr.getWhat());
-        assertEquals(sm5.mChildState3, lr.getState());
-        assertEquals(sm5.mChildState3, lr.getOriginalState());
-
-        lr = sm5.getLogRec(4);
-        assertEquals(TEST_CMD_5, lr.getWhat());
-        assertEquals(sm5.mChildState4, lr.getState());
-        assertEquals(sm5.mChildState4, lr.getOriginalState());
-
-        lr = sm5.getLogRec(5);
-        assertEquals(TEST_CMD_6, lr.getWhat());
-        assertEquals(sm5.mParentState2, lr.getState());
-        assertEquals(sm5.mParentState2, lr.getOriginalState());
-
-        if (sm5.isDbg()) tlog("testStateMachine5 X");
-    }
-
-    /**
-     * Test that the initial state enter is invoked immediately
-     * after construction and before any other messages arrive and that
-     * sendMessageDelayed works.
-     */
-    class StateMachine6 extends StateMachine {
-        StateMachine6(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-            if (DBG) tlog("StateMachine6: ctor X");
-        }
-
-        class S1 extends State {
-            @Override
-            public void enter() {
-                sendMessage(TEST_CMD_1);
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_1) {
-                    mArrivalTimeMsg1 = SystemClock.elapsedRealtime();
-                } else if (message.what == TEST_CMD_2) {
-                    mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine6 mThisSm;
-        private S1 mS1 = new S1();
-
-        private long mArrivalTimeMsg1;
-        private long mArrivalTimeMsg2;
-    }
-
-    @MediumTest
-    public void testStateMachine6() throws Exception {
-        final int DELAY_TIME = 250;
-        final int DELAY_FUDGE = 20;
-
-        StateMachine6 sm6 = new StateMachine6("sm6");
-        sm6.start();
-        if (sm6.isDbg()) tlog("testStateMachine6 E");
-
-        synchronized (sm6) {
-            // Send a message
-            sm6.sendMessageDelayed(TEST_CMD_2, DELAY_TIME);
-
-            try {
-                // wait for the messages to be handled
-                sm6.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine6: exception while waiting " + e.getMessage());
-            }
-        }
-
-        /**
-         * TEST_CMD_1 was sent in enter and must always have been processed
-         * immediately after construction and hence the arrival time difference
-         * should always >= to the DELAY_TIME
-         */
-        long arrivalTimeDiff = sm6.mArrivalTimeMsg2 - sm6.mArrivalTimeMsg1;
-        long expectedDelay = DELAY_TIME - DELAY_FUDGE;
-        if (sm6.isDbg()) tlog("testStateMachine6: expect " + arrivalTimeDiff
-                                    + " >= " + expectedDelay);
-        assertTrue(arrivalTimeDiff >= expectedDelay);
-
-        if (sm6.isDbg()) tlog("testStateMachine6 X");
-    }
-
-    /**
-     * Test that enter is invoked immediately after exit. This validates
-     * that enter can be used to send a watch dog message for its state.
-     */
-    class StateMachine7 extends StateMachine {
-        private final int SM7_DELAY_TIME = 250;
-
-        StateMachine7(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-            addState(mS2);
-
-            // Set the initial state
-            setInitialState(mS1);
-            if (DBG) tlog("StateMachine7: ctor X");
-        }
-
-        class S1 extends State {
-            @Override
-            public void exit() {
-                sendMessage(TEST_CMD_2);
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                transitionTo(mS2);
-                return HANDLED;
-            }
-        }
-
-        class S2 extends State {
-            @Override
-            public void enter() {
-                // Send a delayed message as a watch dog
-                sendMessageDelayed(TEST_CMD_3, SM7_DELAY_TIME);
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_2) {
-                    mMsgCount += 1;
-                    mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
-                } else if (message.what == TEST_CMD_3) {
-                    mMsgCount += 1;
-                    mArrivalTimeMsg3 = SystemClock.elapsedRealtime();
-                }
-
-                if (mMsgCount == 2) {
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachine7 mThisSm;
-        private S1 mS1 = new S1();
-        private S2 mS2 = new S2();
-
-        private int mMsgCount = 0;
-        private long mArrivalTimeMsg2;
-        private long mArrivalTimeMsg3;
-    }
-
-    @MediumTest
-    public void testStateMachine7() throws Exception {
-        final int SM7_DELAY_FUDGE = 20;
-
-        StateMachine7 sm7 = new StateMachine7("sm7");
-        sm7.start();
-        if (sm7.isDbg()) tlog("testStateMachine7 E");
-
-        synchronized (sm7) {
-            // Send a message
-            sm7.sendMessage(TEST_CMD_1);
-
-            try {
-                // wait for the messages to be handled
-                sm7.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachine7: exception while waiting " + e.getMessage());
-            }
-        }
-
-        /**
-         * TEST_CMD_3 was sent in S2.enter with a delay and must always have been
-         * processed immediately after S1.exit. Since S1.exit sent TEST_CMD_2
-         * without a delay the arrival time difference should always >= to SM7_DELAY_TIME.
-         */
-        long arrivalTimeDiff = sm7.mArrivalTimeMsg3 - sm7.mArrivalTimeMsg2;
-        long expectedDelay = sm7.SM7_DELAY_TIME - SM7_DELAY_FUDGE;
-        if (sm7.isDbg()) tlog("testStateMachine7: expect " + arrivalTimeDiff
-                                    + " >= " + expectedDelay);
-        assertTrue(arrivalTimeDiff >= expectedDelay);
-
-        if (sm7.isDbg()) tlog("testStateMachine7 X");
-    }
-
-    /**
-     * Test unhandledMessage.
-     */
-    class StateMachineUnhandledMessage extends StateMachine {
-        StateMachineUnhandledMessage(String name) {
-            super(name);
-            mThisSm = this;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-        @Override
-        public void unhandledMessage(Message message) {
-            mUnhandledMessageCount += 1;
-        }
-
-        class S1 extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_2) {
-                    transitionToHaltingState();
-                }
-                return NOT_HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            synchronized (mThisSm) {
-                mThisSm.notifyAll();
-            }
-        }
-
-        private StateMachineUnhandledMessage mThisSm;
-        private int mUnhandledMessageCount;
-        private S1 mS1 = new S1();
-    }
-
-    @SmallTest
-    public void testStateMachineUnhandledMessage() throws Exception {
-
-        StateMachineUnhandledMessage sm = new StateMachineUnhandledMessage("smUnhandledMessage");
-        sm.start();
-        if (sm.isDbg()) tlog("testStateMachineUnhandledMessage E");
-
-        synchronized (sm) {
-            // Send 2 messages
-            for (int i = 1; i <= 2; i++) {
-                sm.sendMessage(i);
-            }
-
-            try {
-                // wait for the messages to be handled
-                sm.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachineUnhandledMessage: exception while waiting "
-                        + e.getMessage());
-            }
-        }
-
-        assertEquals(2, sm.getLogRecSize());
-        assertEquals(2, sm.mUnhandledMessageCount);
-
-        if (sm.isDbg()) tlog("testStateMachineUnhandledMessage X");
-    }
-
-    /**
-     * Test state machines sharing the same thread/looper. Multiple instances
-     * of the same state machine will be created. They will all share the
-     * same thread and thus each can update <code>sharedCounter</code> which
-     * will be used to notify testStateMachineSharedThread that the test is
-     * complete.
-     */
-    class StateMachineSharedThread extends StateMachine {
-        StateMachineSharedThread(String name, Looper looper, int maxCount) {
-            super(name, looper);
-            mMaxCount = maxCount;
-            setDbg(DBG);
-
-            // Setup state machine with 1 state
-            addState(mS1);
-
-            // Set the initial state
-            setInitialState(mS1);
-        }
-
-        class S1 extends State {
-            @Override
-            public boolean processMessage(Message message) {
-                if (message.what == TEST_CMD_4) {
-                    transitionToHaltingState();
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            // Update the shared counter, which is OK since all state
-            // machines are using the same thread.
-            sharedCounter += 1;
-            if (sharedCounter == mMaxCount) {
-                synchronized (waitObject) {
-                    waitObject.notifyAll();
-                }
-            }
-        }
-
-        private int mMaxCount;
-        private S1 mS1 = new S1();
-    }
-    private static int sharedCounter = 0;
-    private static Object waitObject = new Object();
-
-    @MediumTest
-    public void testStateMachineSharedThread() throws Exception {
-        if (DBG) tlog("testStateMachineSharedThread E");
-
-        // Create and start the handler thread
-        HandlerThread smThread = new HandlerThread("testStateMachineSharedThread");
-        smThread.start();
-
-        // Create the state machines
-        StateMachineSharedThread sms[] = new StateMachineSharedThread[10];
-        for (int i = 0; i < sms.length; i++) {
-            sms[i] = new StateMachineSharedThread("smSharedThread",
-                        smThread.getLooper(), sms.length);
-            sms[i].start();
-        }
-
-        synchronized (waitObject) {
-            // Send messages to each of the state machines
-            for (StateMachineSharedThread sm : sms) {
-                for (int i = 1; i <= 4; i++) {
-                    sm.sendMessage(i);
-                }
-            }
-
-            // Wait for the last state machine to notify its done
-            try {
-                waitObject.wait();
-            } catch (InterruptedException e) {
-                tloge("testStateMachineSharedThread: exception while waiting "
-                        + e.getMessage());
-            }
-        }
-
-        for (StateMachineSharedThread sm : sms) {
-            assertEquals(4, sm.getLogRecCount());
-            for (int i = 0; i < sm.getLogRecSize(); i++) {
-                LogRec lr = sm.getLogRec(i);
-                assertEquals(i+1, lr.getWhat());
-                assertEquals(sm.mS1, lr.getState());
-                assertEquals(sm.mS1, lr.getOriginalState());
-            }
-        }
-
-        if (DBG) tlog("testStateMachineSharedThread X");
-    }
-
-    static class Hsm1 extends StateMachine {
-        private static final String HSM1_TAG = "hsm1";
-
-        public static final int CMD_1 = 1;
-        public static final int CMD_2 = 2;
-        public static final int CMD_3 = 3;
-        public static final int CMD_4 = 4;
-        public static final int CMD_5 = 5;
-
-        public static Hsm1 makeHsm1() {
-            Log.d(HSM1_TAG, "makeHsm1 E");
-            Hsm1 sm = new Hsm1(HSM1_TAG);
-            sm.start();
-            Log.d(HSM1_TAG, "makeHsm1 X");
-            return sm;
-        }
-
-        Hsm1(String name) {
-            super(name);
-            tlog("ctor E");
-
-            // Add states, use indentation to show hierarchy
-            addState(mP1);
-                addState(mS1, mP1);
-                addState(mS2, mP1);
-            addState(mP2);
-
-            // Set the initial state
-            setInitialState(mS1);
-            tlog("ctor X");
-        }
-
-        class P1 extends State {
-            @Override
-            public void enter() {
-                tlog("P1.enter");
-            }
-            @Override
-            public void exit() {
-                tlog("P1.exit");
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                boolean retVal;
-                tlog("P1.processMessage what=" + message.what);
-                switch(message.what) {
-                case CMD_2:
-                    // CMD_2 will arrive in mS2 before CMD_3
-                    sendMessage(CMD_3);
-                    deferMessage(message);
-                    transitionTo(mS2);
-                    retVal = true;
-                    break;
-                default:
-                    // Any message we don't understand in this state invokes unhandledMessage
-                    retVal = false;
-                    break;
-                }
-                return retVal;
-            }
-        }
-
-        class S1 extends State {
-            @Override
-            public void enter() {
-                tlog("S1.enter");
-            }
-            @Override
-            public void exit() {
-                tlog("S1.exit");
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                tlog("S1.processMessage what=" + message.what);
-                if (message.what == CMD_1) {
-                    // Transition to ourself to show that enter/exit is called
-                    transitionTo(mS1);
-                    return HANDLED;
-                } else {
-                    // Let parent process all other messages
-                    return NOT_HANDLED;
-                }
-            }
-        }
-
-        class S2 extends State {
-            @Override
-            public void enter() {
-                tlog("S2.enter");
-            }
-            @Override
-            public void exit() {
-                tlog("S2.exit");
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                boolean retVal;
-                tlog("S2.processMessage what=" + message.what);
-                switch(message.what) {
-                case(CMD_2):
-                    sendMessage(CMD_4);
-                    retVal = true;
-                    break;
-                case(CMD_3):
-                    deferMessage(message);
-                    transitionTo(mP2);
-                    retVal = true;
-                    break;
-                default:
-                    retVal = false;
-                    break;
-                }
-                return retVal;
-            }
-        }
-
-        class P2 extends State {
-            @Override
-            public void enter() {
-                tlog("P2.enter");
-                sendMessage(CMD_5);
-            }
-            @Override
-            public void exit() {
-                tlog("P2.exit");
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                tlog("P2.processMessage what=" + message.what);
-                switch(message.what) {
-                case(CMD_3):
-                    break;
-                case(CMD_4):
-                    break;
-                case(CMD_5):
-                    transitionToHaltingState();
-                    break;
-                }
-                return HANDLED;
-            }
-        }
-
-        @Override
-        protected void onHalting() {
-            tlog("halting");
-            synchronized (this) {
-                this.notifyAll();
-            }
-        }
-
-        P1 mP1 = new P1();
-        S1 mS1 = new S1();
-        S2 mS2 = new S2();
-        P2 mP2 = new P2();
-    }
-
-    @MediumTest
-    public void testHsm1() throws Exception {
-        if (DBG) tlog("testHsm1 E");
-
-        Hsm1 sm = Hsm1.makeHsm1();
-
-        // Send messages
-        sm.sendMessage(Hsm1.CMD_1);
-        sm.sendMessage(Hsm1.CMD_2);
-
-        synchronized (sm) {
-            // Wait for the last state machine to notify its done
-            try {
-                sm.wait();
-            } catch (InterruptedException e) {
-                tloge("testHsm1: exception while waiting " + e.getMessage());
-            }
-        }
-
-        dumpLogRecs(sm);
-
-        assertEquals(7, sm.getLogRecCount());
-
-        LogRec lr = sm.getLogRec(0);
-        assertEquals(Hsm1.CMD_1, lr.getWhat());
-        assertEquals(sm.mS1, lr.getState());
-        assertEquals(sm.mS1, lr.getOriginalState());
-
-        lr = sm.getLogRec(1);
-        assertEquals(Hsm1.CMD_2, lr.getWhat());
-        assertEquals(sm.mP1, lr.getState());
-        assertEquals(sm.mS1, lr.getOriginalState());
-
-        lr = sm.getLogRec(2);
-        assertEquals(Hsm1.CMD_2, lr.getWhat());
-        assertEquals(sm.mS2, lr.getState());
-        assertEquals(sm.mS2, lr.getOriginalState());
-
-        lr = sm.getLogRec(3);
-        assertEquals(Hsm1.CMD_3, lr.getWhat());
-        assertEquals(sm.mS2, lr.getState());
-        assertEquals(sm.mS2, lr.getOriginalState());
-
-        lr = sm.getLogRec(4);
-        assertEquals(Hsm1.CMD_3, lr.getWhat());
-        assertEquals(sm.mP2, lr.getState());
-        assertEquals(sm.mP2, lr.getOriginalState());
-
-        lr = sm.getLogRec(5);
-        assertEquals(Hsm1.CMD_4, lr.getWhat());
-        assertEquals(sm.mP2, lr.getState());
-        assertEquals(sm.mP2, lr.getOriginalState());
-
-        lr = sm.getLogRec(6);
-        assertEquals(Hsm1.CMD_5, lr.getWhat());
-        assertEquals(sm.mP2, lr.getState());
-        assertEquals(sm.mP2, lr.getOriginalState());
-
-        if (DBG) tlog("testStateMachineSharedThread X");
-    }
-
-    private static void tlog(String s) {
-        Log.d(TAG, s);
-    }
-
-    private static void tloge(String s) {
-        Log.e(TAG, s);
-    }
-
-    public void testDumpDoesNotThrowNpeAfterQuit() {
-        final Hsm1 sm = Hsm1.makeHsm1();
-        sm.quitNow();
-        final StringWriter stringWriter = new StringWriter();
-        final PrintWriter printWriter = new PrintWriter(stringWriter);
-        sm.dump(null, printWriter, new String[0]);
-    }
-}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index e608a74..fdc6e81 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -464,6 +464,8 @@
         <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
              P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
         <permission name="android.permission.MANAGE_WIFI_NETWORK_SELECTION" />
+        <!-- Permission needed for CTS test - ConcurrencyTest#testP2pSetWfdInfo -->
+        <permission name="android.permission.CONFIGURE_WIFI_DISPLAY" />
         <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest -->
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
         <!-- Permission required for CTS test - MusicRecognitionManagerTest -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index c4d4261..b44ccfb 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -524,6 +524,8 @@
     <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
          P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
     <uses-permission android:name="android.permission.MANAGE_WIFI_NETWORK_SELECTION" />
+    <!-- Permission needed for CTS test - ConcurrencyTest#testP2pSetWfdInfo -->
+    <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
 
     <!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
     <uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
diff --git a/services/core/java/com/android/server/integrity/OWNERS b/services/core/java/com/android/server/integrity/OWNERS
index 55a4e40..33561fd 100644
--- a/services/core/java/com/android/server/integrity/OWNERS
+++ b/services/core/java/com/android/server/integrity/OWNERS
@@ -2,4 +2,4 @@
 khelmy@google.com
 mdchurchill@google.com
 sturla@google.com
-songpan@google.com
+
diff --git a/services/core/java/com/android/server/power/stats/OWNERS b/services/core/java/com/android/server/power/stats/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
index b0f207c..b5d97ab 100644
--- a/telephony/java/android/telephony/AccessNetworkUtils.java
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -4,8 +4,8 @@
 import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
 import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
 
-import android.telephony.AccessNetworkConstants.EutranBand;
 import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
+import android.telephony.AccessNetworkConstants.EutranBand;
 import android.telephony.AccessNetworkConstants.GeranBand;
 import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.NgranArfcnFrequency;
@@ -13,6 +13,7 @@
 import android.telephony.AccessNetworkConstants.UtranBand;
 import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency;
 import android.telephony.ServiceState.DuplexMode;
+import android.util.Log;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -231,110 +232,6 @@
     }
 
     /**
-     * Gets the NR Operating band for a given downlink NRARFCN.
-     *
-     * <p>See 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 and
-     * Table 5.2-2 NR operating bands in FR2
-     *
-     * @param nrarfcn The downlink NRARFCN
-     * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
-     */
-    public static int getOperatingBandForNrarfcn(int nrarfcn) {
-        if (nrarfcn >= 2110 && nrarfcn <= 2170) {
-            return NgranBands.BAND_1;
-        } else if (nrarfcn >= 1930 && nrarfcn <= 1990) {
-            return NgranBands.BAND_2;
-        } else if (nrarfcn >= 1805 && nrarfcn <= 1880) {
-            return NgranBands.BAND_3;
-        } else if (nrarfcn >= 869 && nrarfcn <= 894) {
-            return NgranBands.BAND_5;
-        } else if (nrarfcn >= 2620 && nrarfcn <= 2690) {
-            return NgranBands.BAND_7;
-        } else if (nrarfcn >= 925 && nrarfcn <= 960) {
-            return NgranBands.BAND_8;
-        } else if (nrarfcn >= 729 && nrarfcn <= 746) {
-            return NgranBands.BAND_12;
-        } else if (nrarfcn >= 758 && nrarfcn <= 768) {
-            return NgranBands.BAND_14;
-        } else if (nrarfcn >= 860 && nrarfcn <= 875) {
-            return NgranBands.BAND_18;
-        } else if (nrarfcn >= 791 && nrarfcn <= 821) {
-            return NgranBands.BAND_20;
-        } else if (nrarfcn >= 1930 && nrarfcn <= 1995) {
-            return NgranBands.BAND_25;
-        } else if (nrarfcn >= 859 && nrarfcn <= 894) {
-            return NgranBands.BAND_26;
-        } else if (nrarfcn >= 758 && nrarfcn <= 803) {
-            return NgranBands.BAND_28;
-        } else if (nrarfcn >= 717 && nrarfcn <= 728) {
-            return NgranBands.BAND_29;
-        } else if (nrarfcn >= 2350 && nrarfcn <= 2360) {
-            return NgranBands.BAND_30;
-        } else if (nrarfcn >= 2010 && nrarfcn <= 2025) {
-            return NgranBands.BAND_34;
-        } else if (nrarfcn >= 2570 && nrarfcn <= 2620) {
-            return NgranBands.BAND_38;
-        } else if (nrarfcn >= 1880 && nrarfcn <= 1920) {
-            return NgranBands.BAND_39;
-        } else if (nrarfcn >= 2300 && nrarfcn <= 2400) {
-            return NgranBands.BAND_40;
-        } else if (nrarfcn >= 2496 && nrarfcn <= 2690) {
-            return NgranBands.BAND_41;
-        } else if (nrarfcn >= 5150 && nrarfcn <= 5925) {
-            return NgranBands.BAND_46;
-        } else if (nrarfcn >= 3550 && nrarfcn <= 3700) {
-            return NgranBands.BAND_48;
-        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
-            return NgranBands.BAND_50;
-        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
-            return NgranBands.BAND_51;
-        } else if (nrarfcn >= 2483 && nrarfcn <= 2495) {
-            return NgranBands.BAND_53;
-        } else if (nrarfcn >= 2110 && nrarfcn <= 2200) {
-            return NgranBands.BAND_65; // BAND_66 has the same channels
-        } else if (nrarfcn >= 1995 && nrarfcn <= 2020) {
-            return NgranBands.BAND_70;
-        } else if (nrarfcn >= 617 && nrarfcn <= 652) {
-            return NgranBands.BAND_71;
-        } else if (nrarfcn >= 1475 && nrarfcn <= 1518) {
-            return NgranBands.BAND_74;
-        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
-            return NgranBands.BAND_75;
-        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
-            return NgranBands.BAND_76;
-        } else if (nrarfcn >= 3300 && nrarfcn <= 4200) {
-            return NgranBands.BAND_77;
-        } else if (nrarfcn >= 3300 && nrarfcn <= 3800) {
-            return NgranBands.BAND_78;
-        } else if (nrarfcn >= 4400 && nrarfcn <= 5000) {
-            return NgranBands.BAND_79;
-        } else if (nrarfcn >= 2496 && nrarfcn <= 2690) {
-            return NgranBands.BAND_90;
-        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
-            return NgranBands.BAND_91;
-        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
-            return NgranBands.BAND_92;
-        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
-            return NgranBands.BAND_93;
-        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
-            return NgranBands.BAND_94;
-        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
-            return NgranBands.BAND_94;
-        } else if (nrarfcn >= 5925 && nrarfcn <= 7125) {
-            return NgranBands.BAND_96;
-        } else if (nrarfcn >= 26500 && nrarfcn <= 29500) {
-            return NgranBands.BAND_257;
-        } else if (nrarfcn >= 24250 && nrarfcn <= 27500) {
-            return NgranBands.BAND_258;
-        } else if (nrarfcn >= 37000 && nrarfcn <= 40000) {
-            return NgranBands.BAND_260;
-        } else if (nrarfcn >= 27500 && nrarfcn <= 28350) {
-            return NgranBands.BAND_261;
-        }
-        return INVALID_BAND;
-    }
-
-    /**
      * Gets the GERAN Operating band for a given ARFCN.
      *
      * <p>See 3GPP TS 45.005 clause 2 for calculation.