Merge " Create integrity directory and OWNERS"
diff --git a/Android.bp b/Android.bp
index 8520d40..7241417 100644
--- a/Android.bp
+++ b/Android.bp
@@ -163,7 +163,7 @@
 }
 
 filegroup {
-    name: "framework-srcs",
+    name: "framework-non-updatable-sources",
     srcs: [
         // Java/AIDL sources under frameworks/base
         ":framework-core-sources",
@@ -211,6 +211,14 @@
     ],
 }
 
+filegroup {
+    name: "framework-all-sources",
+    srcs: [
+        ":framework-non-updatable-sources",
+        ":updatable-media-srcs",
+    ],
+}
+
 java_defaults {
     name: "framework-aidl-export-defaults",
     aidl: {
@@ -283,15 +291,12 @@
     defaults: ["framework-aidl-export-defaults"],
     installable: true,
 
-    srcs: [
-        ":framework-srcs",
-        "core/java/**/*.logtags",
-    ],
-
     aidl: {
         generate_get_transaction_name: true,
     },
 
+    srcs: ["core/java/**/*.logtags"],
+
     exclude_srcs: [
         // See comment on framework-atb-backward-compatibility module below
         "core/java/android/content/pm/AndroidTestBaseUpdater.java",
@@ -356,6 +361,7 @@
 java_library {
     name: "framework",
     defaults: ["framework-defaults"],
+    srcs: [":framework-non-updatable-sources"],
     javac_shard_size: 150,
     required: [
         "framework-platform-compat-config",
@@ -365,8 +371,16 @@
 }
 
 java_library {
+    name: "framework-all",
+    defaults: ["framework-defaults"],
+    srcs: [":framework-all-sources"],
+    installable: false,
+}
+
+java_library {
     name: "framework-annotation-proc",
     defaults: ["framework-defaults"],
+    srcs: [":framework-all-sources"],
     installable: false,
     plugins: [
         "unsupportedappusage-annotation-processor",
@@ -878,10 +892,21 @@
     // replacement (with $1, $2 backreferences to the regex groups)
     "'$$1https://docs.oracle.com/javase/8/docs/$$2\">' "
 
+packages_to_document = [
+    "android",
+    "java",
+    "javax",
+    "org.apache.http",
+    "org.json",
+    "org.w3c.dom",
+    "org.xml.sax",
+    "org.xmlpull",
+]
+
 stubs_defaults {
     name: "framework-doc-stubs-default",
     srcs: [
-        ":framework-srcs",
+        ":framework-non-updatable-sources",
         "core/java/**/*.logtags",
         "test-base/src/**/*.java",
         ":opt-telephony-srcs",
@@ -945,7 +970,7 @@
 stubs_defaults {
     name: "metalava-api-stubs-default",
     srcs: [
-        ":framework-srcs",
+        ":framework-non-updatable-sources",
         "core/java/**/*.logtags",
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
@@ -967,6 +992,7 @@
         "api-versions-jars-dir",
     ],
     sdk_version: "core_platform",
+    filter_packages: packages_to_document,
 }
 
 droidstubs {
@@ -1465,7 +1491,7 @@
 // annotations to private apis
 aidl_mapping {
     name: "framework-aidl-mappings",
-    srcs: [":framework-srcs"],
+    srcs: [":framework-all-sources"],
     output: "framework-aidl-mappings.txt",
 }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 326ac94..dd0df39 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8108,7 +8108,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean disableDataConnectivity();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
@@ -8147,6 +8147,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
     method public boolean isDataConnectivityPossible();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
@@ -8154,7 +8155,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
-    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean needsOtaServiceProvisioning();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
@@ -9419,14 +9420,18 @@
     method public void acknowledgeSmsReport(int, int, int);
     method public String getSmsFormat();
     method public void onReady();
-    method public final void onSendSmsResult(int, int, int, int) throws java.lang.RuntimeException;
+    method @Deprecated public final void onSendSmsResult(int, int, int, int) throws java.lang.RuntimeException;
+    method public final void onSendSmsResultError(int, int, int, int, int) throws java.lang.RuntimeException;
+    method public final void onSendSmsResultSuccess(int, int) throws java.lang.RuntimeException;
     method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
-    method public final void onSmsStatusReportReceived(int, int, String, byte[]) throws java.lang.RuntimeException;
+    method @Deprecated public final void onSmsStatusReportReceived(int, int, String, byte[]) throws java.lang.RuntimeException;
+    method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
     method public void sendSms(int, int, String, String, boolean, byte[]);
     field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
     field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
     field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
     field public static final int DELIVER_STATUS_OK = 1; // 0x1
+    field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
     field public static final int SEND_STATUS_ERROR = 2; // 0x2
     field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
     field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 52b7d4b..bf71998 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -319,6 +319,9 @@
             217 [(log_from_module) = "permissioncontroller"];
         PermissionAppsFragmentViewed permission_apps_fragment_viewed =
             218  [(log_from_module) = "permissioncontroller"];
+
+        AppCompatibilityChangeReported app_compatibility_change_reported =
+            228 [(allow_from_any_uid) = true];
     }
 
     // Pulled events will start at field 10000.
@@ -6779,3 +6782,39 @@
     }
     optional Category category = 6;
 }
+
+/**
+ * Logs when a compatibility change is affecting an app.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/android/app/AppCompatCallbacks.java and
+ *   frameworks/base/services/core/java/com/android/server/compat/PlatformCompat.java
+ */
+message AppCompatibilityChangeReported {
+    // The UID of the app being affected by the compatibilty change.
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // The ID of the change affecting the app.
+    optional int64 change_id = 2;
+
+    enum State {
+        UNKNOWN_STATE = 0;
+        ENABLED = 1;
+        DISABLED = 2;
+        LOGGED = 3;
+    }
+
+    // The state of the change - if logged from gating whether it was enabled or disabled, or just
+    // logged otherwise.
+    optional State state = 3;
+
+    enum Source {
+        UNKNOWN_SOURCE = 0;
+        APP_PROCESS = 1;
+        SYSTEM_SERVER = 2;
+    }
+
+    // Where it was logged from.
+    optional Source source = 4;
+
+}
diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java
index 17697db..08c97eb 100644
--- a/core/java/android/app/AppCompatCallbacks.java
+++ b/core/java/android/app/AppCompatCallbacks.java
@@ -19,6 +19,9 @@
 import android.compat.Compatibility;
 import android.os.Process;
 import android.util.Log;
+import android.util.StatsLog;
+
+import com.android.internal.compat.ChangeReporter;
 
 import java.util.Arrays;
 
@@ -28,10 +31,10 @@
  * @hide
  */
 public final class AppCompatCallbacks extends Compatibility.Callbacks {
-
     private static final String TAG = "Compatibility";
 
     private final long[] mDisabledChanges;
+    private final ChangeReporter mChangeReporter;
 
     /**
      * Install this class into the current process.
@@ -45,20 +48,29 @@
     private AppCompatCallbacks(long[] disabledChanges) {
         mDisabledChanges = Arrays.copyOf(disabledChanges, disabledChanges.length);
         Arrays.sort(mDisabledChanges);
+        mChangeReporter = new ChangeReporter();
     }
 
     protected void reportChange(long changeId) {
-        Log.d(TAG, "Compat change reported: " + changeId + "; UID " + Process.myUid());
-        // TODO log via StatsLog
+        reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     protected boolean isChangeEnabled(long changeId) {
         if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) {
             // Not present in the disabled array
-            reportChange(changeId);
+            reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
             return true;
         }
+        reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
         return false;
     }
 
+    private void reportChange(long changeId, int state) {
+        int uid = Process.myUid();
+        //TODO(b/138374585): Implement rate limiting for the logs.
+        Log.d(TAG, ChangeReporter.createLogString(uid, changeId, state));
+        mChangeReporter.reportChange(uid, changeId,
+                state, /* source */StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__APP_PROCESS);
+    }
+
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 74c89d6..f852976 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -182,6 +182,12 @@
      */
     public static final int NETWORK_STACK_UID = 1073;
 
+    /**
+     * Defines the UID/GID for fs-verity certificate ownership in keystore.
+     * @hide
+     */
+    public static final int FSVERITY_CERT_UID = 1075;
+
     /** {@hide} */
     public static final int NOBODY_UID = 9999;
 
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 4538410..7bf1c4b 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -184,6 +184,8 @@
      * Set the value for the given {@code key} to {@code val}.
      *
      * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
+     * @throws RuntimeException if the property cannot be set, for example, if it was blocked by
+     * SELinux. libc will log the underlying reason.
      * @hide
      */
     @UnsupportedAppUsage
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index b347a78..39792ce5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -638,4 +638,14 @@
      * native InputManager before proceeding with tests.
      */
     void syncInputTransactions();
+
+    /**
+     * Returns whether SurfaceFlinger layer tracing is enabled.
+     */
+    boolean isLayerTracing();
+
+    /**
+     * Enables/disables SurfaceFlinger layer tracing.
+     */
+    void setLayerTracing(boolean enabled);
 }
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
new file mode 100644
index 0000000..1ce071b
--- /dev/null
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.compat;
+
+import android.util.StatsLog;
+
+/**
+ * A helper class to report changes to stats log.
+ *
+ * @hide
+ */
+public final class ChangeReporter {
+
+    /**
+     * Transforms StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE enum to a string.
+     *
+     * @param state to transform
+     * @return a string representing the state
+     */
+    private static String stateToString(int state) {
+        switch (state) {
+            case StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED:
+                return "LOGGED";
+            case StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED:
+                return "ENABLED";
+            case StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED:
+                return "DISABLED";
+            default:
+                return "UNKNOWN";
+        }
+    }
+
+    /**
+     * Constructs and returns a string to be logged to logcat when a change is reported.
+     *
+     * @param uid      affected by the change
+     * @param changeId the reported change id
+     * @param state    of the reported change - enabled/disabled/only logged
+     * @return string to log
+     */
+    public static String createLogString(int uid, long changeId, int state) {
+        return String.format("Compat change id reported: %d; UID %d; state: %s", changeId, uid,
+                stateToString(state));
+    }
+
+    /**
+     * Report the change to stats log.
+     *
+     * @param uid      affected by the change
+     * @param changeId the reported change id
+     * @param state    of the reported change - enabled/disabled/only logged
+     * @param source   of the logging - app process or system server
+     */
+    public void reportChange(int uid, long changeId, int state, int source) {
+        //TODO(b/138374585): Implement rate limiting for stats log.
+        StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
+                state, source);
+    }
+}
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index cbae2da..b6427c9a 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -152,7 +152,7 @@
         uint32_t flags,
         TransactCallback callback) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    bool isOneway = (flags & TF_ONE_WAY) != 0;
+    bool isOneway = (flags & IBinder::FLAG_ONEWAY) != 0;
     ScopedLocalRef<jobject> replyObj(env, nullptr);
     sp<JHwParcel> replyContext = nullptr;
 
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 9ec7517..87f498a 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -109,7 +109,7 @@
     if (!ConvertKeyAndForward(env, keyJ, true, handler)) {
         // Must have been a failure in SetProperty.
         jniThrowException(env, "java/lang/RuntimeException",
-                          "failed to set system property");
+                          "failed to set system property (check logcat for reason)");
     }
 }
 
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index 349b9e0..3cd6ccf 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -18,7 +18,7 @@
     name: "com.android.location.provider",
     srcs: [
         "java/**/*.java",
-        ":framework-srcs",
+        ":framework-all-sources",
     ],
     api_packages: ["com.android.location.provider"],
 }
diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp
index 85a007f..2286c53 100644
--- a/media/lib/signer/Android.bp
+++ b/media/lib/signer/Android.bp
@@ -18,7 +18,7 @@
     name: "com.android.mediadrm.signer",
     srcs: [
         "java/**/*.java",
-        ":framework-srcs",
+        ":framework-all-sources",
     ],
     api_packages: ["com.android.mediadrm.signer"],
 }
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 7bdaaa1..857cb2a 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -1079,9 +1079,7 @@
         }
         return new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
                 .addExtras(sNotificationBundle)
-                .setSmallIcon(
-                        isTv(context) ? R.drawable.ic_bug_report_black_24dp
-                                : com.android.internal.R.drawable.stat_sys_adb)
+                .setSmallIcon(R.drawable.ic_bug_report_black_24dp)
                 .setLocalOnly(true)
                 .setColor(context.getColor(
                         com.android.internal.R.color.system_notification_accent_color))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 01498e6..6fc265e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -19,7 +19,6 @@
 public interface KeyguardMonitor extends CallbackController<Callback> {
 
     boolean isSecure();
-    boolean canSkipBouncer();
     boolean isShowing();
     boolean isOccluded();
     boolean isKeyguardFadingAway();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index b53ff0e..2b08d68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -17,13 +17,11 @@
 package com.android.systemui.statusbar.policy;
 
 import android.annotation.NonNull;
-import android.app.ActivityManager;
 import android.content.Context;
 
 import com.android.internal.util.Preconditions;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.settings.CurrentUserTracker;
 
 import java.util.ArrayList;
 
@@ -39,14 +37,11 @@
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
 
     private final Context mContext;
-    private final CurrentUserTracker mUserTracker;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
-    private int mCurrentUser;
     private boolean mShowing;
     private boolean mSecure;
     private boolean mOccluded;
-    private boolean mCanSkipBouncer;
 
     private boolean mListening;
     private boolean mKeyguardFadingAway;
@@ -61,13 +56,6 @@
     public KeyguardMonitorImpl(Context context) {
         mContext = context;
         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-        mUserTracker = new CurrentUserTracker(mContext) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                mCurrentUser = newUserId;
-                updateCanSkipBouncerState();
-            }
-        };
     }
 
     @Override
@@ -76,10 +64,7 @@
         mCallbacks.add(callback);
         if (mCallbacks.size() != 0 && !mListening) {
             mListening = true;
-            mCurrentUser = ActivityManager.getCurrentUser();
-            updateCanSkipBouncerState();
             mKeyguardUpdateMonitor.registerCallback(this);
-            mUserTracker.startTracking();
         }
     }
 
@@ -89,7 +74,6 @@
         if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
             mListening = false;
             mKeyguardUpdateMonitor.removeCallback(this);
-            mUserTracker.stopTracking();
         }
     }
 
@@ -108,11 +92,6 @@
         return mOccluded;
     }
 
-    @Override
-    public boolean canSkipBouncer() {
-        return mCanSkipBouncer;
-    }
-
     public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
         if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
         mShowing = showing;
@@ -123,7 +102,6 @@
 
     @Override
     public void onTrustChanged(int userId) {
-        updateCanSkipBouncerState();
         notifyKeyguardChanged();
     }
 
@@ -131,10 +109,6 @@
         return mKeyguardUpdateMonitor.isDeviceInteractive();
     }
 
-    private void updateCanSkipBouncerState() {
-        mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
-    }
-
     private void notifyKeyguardChanged() {
         // Copy the list to allow removal during callback.
         new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 395add7..35e3923 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -61,6 +61,7 @@
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.tiles.UserDetailView;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.UnlockMethodCache;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -595,17 +596,19 @@
 
         final UserSwitcherController mController;
         private final KeyguardMonitor mKeyguardMonitor;
+        private final UnlockMethodCache mUnlockMethodCache;
 
         protected BaseUserAdapter(UserSwitcherController controller) {
             mController = controller;
             mKeyguardMonitor = controller.mKeyguardMonitor;
+            mUnlockMethodCache = UnlockMethodCache.getInstance(controller.mContext);
             controller.addAdapter(new WeakReference<>(this));
         }
 
         public int getUserCount() {
             boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
                     && mKeyguardMonitor.isSecure()
-                    && !mKeyguardMonitor.canSkipBouncer();
+                    && !mUnlockMethodCache.canSkipBouncer();
             if (!secureKeyguardShowing) {
                 return mController.getUsers().size();
             }
@@ -627,7 +630,7 @@
         public int getCount() {
             boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
                     && mKeyguardMonitor.isSecure()
-                    && !mKeyguardMonitor.canSkipBouncer();
+                    && !mUnlockMethodCache.canSkipBouncer();
             if (!secureKeyguardShowing) {
                 return mController.getUsers().size();
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 95c7a4d..2fb0e0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -80,9 +80,4 @@
     public long calculateGoingToFullShadeDelay() {
         return 0;
     }
-
-    @Override
-    public boolean canSkipBouncer() {
-        return false;
-    }
 }
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 9bbc315..8e5c73bf 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -16,33 +16,33 @@
 
 package com.android.server;
 
+import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT;
+import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT_BIT;
+import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT;
+import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT_BIT;
+import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT;
+import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT_BIT;
+
 import android.content.Context;
+import android.media.AudioManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.os.UEventObserver;
+import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
-import android.media.AudioManager;
-import android.util.Log;
 import android.view.InputDevice;
 
 import com.android.internal.R;
 import com.android.server.input.InputManagerService;
 import com.android.server.input.InputManagerService.WiredAccessoryCallbacks;
 
-import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT;
-import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT;
-import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT;
-import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT_BIT;
-import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT_BIT;
-import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT_BIT;
-
 import java.io.File;
-import java.io.FileReader;
 import java.io.FileNotFoundException;
+import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -538,7 +538,7 @@
             synchronized (mLock) {
                 int mask = maskAndState.first;
                 int state = maskAndState.second;
-                updateLocked(name, mHeadsetState | (mask & state) & ~(mask & ~state));
+                updateLocked(name, mHeadsetState & ~(mask & ~state) | (mask & state));
                 return;
             }
         }
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 0509f9f..2f9a5c9 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -12,6 +12,7 @@
 varunshah@google.com
 kwekua@google.com
 bookatz@google.com
+jji@google.com
 
 # Windows & Activities
 ogunwale@google.com
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index fc38735..81e507c 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -19,7 +19,9 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.util.Slog;
+import android.util.StatsLog;
 
+import com.android.internal.compat.ChangeReporter;
 import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.util.DumpUtils;
 
@@ -34,23 +36,27 @@
     private static final String TAG = "Compatibility";
 
     private final Context mContext;
+    private final ChangeReporter mChangeReporter;
 
     public PlatformCompat(Context context) {
         mContext = context;
+        mChangeReporter = new ChangeReporter();
     }
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
-        Slog.d(TAG, "Compat change reported: " + changeId + "; UID " + appInfo.uid);
-        // TODO log via StatsLog
+        reportChange(changeId, appInfo, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
         if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) {
-            reportChange(changeId, appInfo);
+            reportChange(changeId, appInfo,
+                    StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
             return true;
         }
+        reportChange(changeId, appInfo,
+                StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
         return false;
     }
 
@@ -59,4 +65,13 @@
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         CompatConfig.get().dumpConfig(pw);
     }
+
+    private void reportChange(long changeId, ApplicationInfo appInfo, int state) {
+        int uid = appInfo.uid;
+        //TODO(b/138374585): Implement rate limiting for the logs.
+        Slog.d(TAG, ChangeReporter.createLogString(uid, changeId, state));
+        mChangeReporter.reportChange(uid, changeId,
+                state, /* source */
+                StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 436a5c7..3da7fb3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7778,4 +7778,64 @@
                     0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
         }
     }
+
+    /** Return whether layer tracing is enabled */
+    public boolean isLayerTracing() {
+        mAtmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.DUMP,
+                "isLayerTracing");
+        long token = Binder.clearCallingIdentity();
+        try {
+            Parcel data = null;
+            Parcel reply = null;
+            try {
+                IBinder sf = ServiceManager.getService("SurfaceFlinger");
+                if (sf != null) {
+                    reply = Parcel.obtain();
+                    data = Parcel.obtain();
+                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
+                    sf.transact(/* LAYER_TRACE_STATUS_CODE */ 1026, data, reply, 0 /* flags */);
+                    return reply.readBoolean();
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to get layer tracing");
+            } finally {
+                if (data != null) {
+                    data.recycle();
+                }
+                if (reply != null) {
+                    reply.recycle();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        return false;
+    }
+
+    /** Enable or disable layer tracing */
+    public void setLayerTracing(boolean enabled) {
+        mAtmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.DUMP,
+                "setLayerTracing");
+        long token = Binder.clearCallingIdentity();
+        try {
+            Parcel data = null;
+            try {
+                IBinder sf = ServiceManager.getService("SurfaceFlinger");
+                if (sf != null) {
+                    data = Parcel.obtain();
+                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
+                    data.writeInt(enabled ? 1 : 0);
+                    sf.transact(/* LAYER_TRACE_CONTROL_CODE */ 1025, data, null, 0 /* flags */);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to set layer tracing");
+            } finally {
+                if (data != null) {
+                    data.recycle();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
 }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 3548810..0abd9fc 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -30,6 +30,7 @@
 import android.os.RemoteException;
 import android.telecom.Logging.Session;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telecom.IConnectionService;
 import com.android.internal.telecom.IConnectionServiceAdapter;
@@ -2672,4 +2673,13 @@
             return ++mId;
         }
     }
+
+    /**
+     * Returns this handler, ONLY FOR TESTING.
+     * @hide
+     */
+    @VisibleForTesting
+    public Handler getHandler() {
+        return mHandler;
+    }
 }
diff --git a/telecomm/java/android/telecom/Logging/SessionManager.java b/telecomm/java/android/telecom/Logging/SessionManager.java
index 949f7b7..49c3a72 100644
--- a/telecomm/java/android/telecom/Logging/SessionManager.java
+++ b/telecomm/java/android/telecom/Logging/SessionManager.java
@@ -391,6 +391,20 @@
         return mCurrentThreadId.get();
     }
 
+    /**
+     * @return A String representation of the active sessions at the time that this method is
+     * called.
+     */
+    @VisibleForTesting
+    public synchronized String printActiveSessions() {
+        StringBuilder message = new StringBuilder();
+        for (ConcurrentHashMap.Entry<Integer, Session> entry : mSessionMapper.entrySet()) {
+            message.append(entry.getValue().printFullSessionTree());
+            message.append("\n");
+        }
+        return message.toString();
+    }
+
     @VisibleForTesting
     public synchronized void cleanupStaleSessions(long timeoutMs) {
         String logMessage = "Stale Sessions Cleaned:\n";
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 74c6d5d..8bd8625 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -67,6 +67,7 @@
 import android.telephony.data.ApnSetting;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
+import android.telephony.ims.ImsMmTelManager;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsMmTelFeature;
 import android.telephony.ims.aidl.IImsRcsFeature;
@@ -3202,6 +3203,31 @@
         }
     }
 
+
+    /**
+     * Returns true if the specified type of application (e.g. {@link #APPTYPE_CSIM} is present
+     * on the UICC card.
+     *
+     * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission
+     *
+     * @param appType the uicc app type like {@link APPTYPE_CSIM}
+     * @return true if the specified type of application in UICC CARD or false if no uicc or error.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isApplicationOnUicc(@UiccAppType int appType) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.isApplicationOnUicc(getSubId(), appType);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#isApplicationOnUicc", e);
+        }
+        return false;
+    }
+
     /**
      * Returns a constant indicating the state of the device SIM card in a logical slot.
      *
@@ -8554,7 +8580,12 @@
         return -1;
     }
 
-    /** @hide */
+    /**
+     * @deprecated Use {@link android.telephony.ims.ImsMmTelManager#setVtSettingEnabled(boolean)}
+     * instead.
+     * @hide
+     */
+    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void enableVideoCalling(boolean enable) {
@@ -8567,7 +8598,14 @@
         }
     }
 
-    /** @hide */
+    /**
+     * @deprecated Use {@link ImsMmTelManager#isVtSettingEnabled()} instead to check if the user
+     * has enabled the Video Calling setting, {@link ImsMmTelManager#isAvailable(int, int)} to
+     * determine if video calling is available, or {@link ImsMmTelManager#isCapable(int, int)} to
+     * determine if video calling is capable.
+     * @hide
+     */
+    @Deprecated
     @SystemApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
@@ -8687,6 +8725,7 @@
      * @param subId Subscription ID
      * @return true if IMS status is registered, false if the IMS status is not registered or a
      * RemoteException occurred.
+     * Use {@link ImsMmTelManager.RegistrationCallback} instead.
      * @hide
      */
     public boolean isImsRegistered(int subId) {
@@ -8723,6 +8762,8 @@
      * used during creation, the default subscription ID will be used.
      * @return true if Voice over LTE is available or false if it is unavailable or unknown.
      * @see SubscriptionManager#getDefaultSubscriptionId()
+     * <p>
+     * Use {@link ImsMmTelManager#isAvailable(int, int)} instead.
      * @hide
      */
     @UnsupportedAppUsage
@@ -8742,6 +8783,7 @@
      * used during creation, the default subscription ID will be used. To query the
      * underlying technology that VT is available on, use {@link #getImsRegTechnologyForMmTel}.
      * @return true if VT is available, or false if it is unavailable or unknown.
+     * Use {@link ImsMmTelManager#isAvailable(int, int)} instead.
      * @hide
      */
     @UnsupportedAppUsage
@@ -8757,6 +8799,7 @@
      * Returns the Status of Wi-Fi calling (Voice over WiFi) for the subscription ID specified.
      * @param subId the subscription ID.
      * @return true if VoWiFi is available, or false if it is unavailable or unknown.
+     * Use {@link ImsMmTelManager#isAvailable(int, int)} instead.
      * @hide
      */
     @UnsupportedAppUsage
@@ -8777,6 +8820,7 @@
      *  - {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} for IWLAN registration, or
      *  - {@link ImsRegistrationImplBase#REGISTRATION_TECH_NONE} if we are not registered or the
      *  result is unavailable.
+     *  Use {@link ImsMmTelManager.RegistrationCallback} instead.
      *  @hide
      */
     public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel() {
diff --git a/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
index 606df15..5aa58c1 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
@@ -21,8 +21,7 @@
  * {@hide}
  */
 oneway interface IImsSmsListener {
-    void onSendSmsResult(int token, int messageRef, int status, int reason);
-    void onSmsStatusReportReceived(int token, int messageRef, in String format,
-            in byte[] pdu);
+    void onSendSmsResult(int token, int messageRef, int status, int reason, int networkErrorCode);
+    void onSmsStatusReportReceived(int token, in String format, in byte[] pdu);
     void onSmsReceived(int token, in String format, in byte[] pdu);
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 852c8e0..175769b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -118,6 +118,12 @@
      */
     public static final int STATUS_REPORT_STATUS_ERROR = 2;
 
+    /**
+     * No network error was generated while processing the SMS message.
+     */
+    // Should match SmsResponse.NO_ERROR_CODE
+    public static final int RESULT_NO_NETWORK_ERROR = -1;
+
     // Lock for feature synchronization
     private final Object mLock = new Object();
     private IImsSmsListener mListener;
@@ -147,7 +153,7 @@
      *               {@link SmsMessage#FORMAT_3GPP2}.
      * @param smsc the Short Message Service Center address.
      * @param isRetry whether it is a retry of an already attempted message or not.
-     * @param pdu PDUs representing the contents of the message.
+     * @param pdu PDU representing the contents of the message.
      */
     public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
             byte[] pdu) {
@@ -166,27 +172,29 @@
      * provider.
      *
      * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
+     * @param messageRef the message reference
      * @param result result of delivering the message. Valid values are:
      *  {@link #DELIVER_STATUS_OK},
      *  {@link #DELIVER_STATUS_ERROR_GENERIC},
      *  {@link #DELIVER_STATUS_ERROR_NO_MEMORY},
      *  {@link #DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED}
-     * @param messageRef the message reference
      */
-    public void acknowledgeSms(int token, @DeliverStatusResult int messageRef, int result) {
+    public void acknowledgeSms(int token, int messageRef, @DeliverStatusResult int result) {
         Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
     }
 
     /**
      * This method will be triggered by the platform after
-     * {@link #onSmsStatusReportReceived(int, int, String, byte[])} has been called to provide the
+     * {@link #onSmsStatusReportReceived(int, int, String, byte[])} or
+     * {@link #onSmsStatusReportReceived(int, String, byte[])} has been called to provide the
      * result to the IMS provider.
      *
-     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param token token provided in {@link #onSmsStatusReportReceived(int, int, String, byte[])}
+     *              or {@link #onSmsStatusReportReceived(int, String, byte[])}
+     * @param messageRef the message reference
      * @param result result of delivering the message. Valid values are:
      *  {@link #STATUS_REPORT_STATUS_OK},
      *  {@link #STATUS_REPORT_STATUS_ERROR}
-     * @param messageRef the message reference
      */
     public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
         Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
@@ -204,7 +212,7 @@
      *              callbacks for this message.
      * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
      * {@link SmsMessage#FORMAT_3GPP2}.
-     * @param pdu PDUs representing the contents of the message.
+     * @param pdu PDU representing the contents of the message.
      * @throws RuntimeException if called before {@link #onReady()} is triggered.
      */
     public final void onSmsReceived(int token, String format, byte[] pdu) throws RuntimeException {
@@ -229,16 +237,37 @@
     }
 
     /**
+     * This method should be triggered by the IMS providers when an outgoing SMS message has been
+     * sent successfully.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
+     *
+     * @throws RuntimeException if called before {@link #onReady()} is triggered or if the
+     * connection to the framework is not available. If this happens attempting to send the SMS
+     * should be aborted.
+     */
+    public final void onSendSmsResultSuccess(int token, int messageRef) throws RuntimeException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new RuntimeException("Feature not ready.");
+            }
+            try {
+                mListener.onSendSmsResult(token, messageRef, SEND_STATUS_OK,
+                        SmsManager.RESULT_ERROR_NONE, RESULT_NO_NETWORK_ERROR);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
      * This method should be triggered by the IMS providers to pass the result of the sent message
      * to the platform.
      *
      * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
      * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
-     * @param status result of sending the SMS. Valid values are:
-     *  {@link #SEND_STATUS_OK},
-     *  {@link #SEND_STATUS_ERROR},
-     *  {@link #SEND_STATUS_ERROR_RETRY},
-     *  {@link #SEND_STATUS_ERROR_FALLBACK},
+     * @param status result of sending the SMS.
      * @param reason reason in case status is failure. Valid values are:
      *  {@link SmsManager#RESULT_ERROR_NONE},
      *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
@@ -269,7 +298,11 @@
      * @throws RuntimeException if called before {@link #onReady()} is triggered or if the
      * connection to the framework is not available. If this happens attempting to send the SMS
      * should be aborted.
+     * @deprecated Use {@link #onSendSmsResultSuccess(int, int)} or
+     * {@link #onSendSmsResultError(int, int, int, int, int)} to notify the framework of the SMS
+     * send result.
      */
+    @Deprecated
     public final void onSendSmsResult(int token, int messageRef,  @SendStatusResult int status,
             int reason) throws RuntimeException {
         synchronized (mLock) {
@@ -277,7 +310,8 @@
                 throw new RuntimeException("Feature not ready.");
             }
             try {
-                mListener.onSendSmsResult(token, messageRef, status, reason);
+                mListener.onSendSmsResult(token, messageRef, status, reason,
+                        RESULT_NO_NETWORK_ERROR);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
@@ -285,23 +319,89 @@
     }
 
     /**
-     * Sets the status report of the sent message.
+     * This method should be triggered by the IMS providers when an outgoing message fails to be
+     * sent due to an error generated while processing the message or after being sent to the
+     * network.
      *
      * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
-     * @param messageRef the message reference.
-     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
-     * {@link SmsMessage#FORMAT_3GPP2}.
-     * @param pdu PDUs representing the content of the status report.
-     * @throws RuntimeException if called before {@link #onReady()} is triggered
+     * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
+     * @param status result of sending the SMS.
+     * @param reason Valid values are:
+     *  {@link SmsManager#RESULT_ERROR_NONE},
+     *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
+     *  {@link SmsManager#RESULT_ERROR_RADIO_OFF},
+     *  {@link SmsManager#RESULT_ERROR_NULL_PDU},
+     *  {@link SmsManager#RESULT_ERROR_NO_SERVICE},
+     *  {@link SmsManager#RESULT_ERROR_LIMIT_EXCEEDED},
+     *  {@link SmsManager#RESULT_ERROR_FDN_CHECK_FAILURE},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NOT_ALLOWED},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED},
+     *  {@link SmsManager#RESULT_RADIO_NOT_AVAILABLE},
+     *  {@link SmsManager#RESULT_NETWORK_REJECT},
+     *  {@link SmsManager#RESULT_INVALID_ARGUMENTS},
+     *  {@link SmsManager#RESULT_INVALID_STATE},
+     *  {@link SmsManager#RESULT_NO_MEMORY},
+     *  {@link SmsManager#RESULT_INVALID_SMS_FORMAT},
+     *  {@link SmsManager#RESULT_SYSTEM_ERROR},
+     *  {@link SmsManager#RESULT_MODEM_ERROR},
+     *  {@link SmsManager#RESULT_NETWORK_ERROR},
+     *  {@link SmsManager#RESULT_ENCODING_ERROR},
+     *  {@link SmsManager#RESULT_INVALID_SMSC_ADDRESS},
+     *  {@link SmsManager#RESULT_OPERATION_NOT_ALLOWED},
+     *  {@link SmsManager#RESULT_INTERNAL_ERROR},
+     *  {@link SmsManager#RESULT_NO_RESOURCES},
+     *  {@link SmsManager#RESULT_CANCELLED},
+     *  {@link SmsManager#RESULT_REQUEST_NOT_SUPPORTED}
+     * @param networkErrorCode the error code reported by the carrier network if sending this SMS
+     *  has resulted in an error or {@link #RESULT_NO_NETWORK_ERROR} if no network error was
+     *  generated. See 3GPP TS 24.011 Section 7.3.4 for valid error codes and more information.
+     *
+     * @throws RuntimeException if called before {@link #onReady()} is triggered or if the
+     * connection to the framework is not available. If this happens attempting to send the SMS
+     * should be aborted.
      */
-    public final void onSmsStatusReportReceived(int token, int messageRef, String format,
-            byte[] pdu) throws RuntimeException{
+    public final void onSendSmsResultError(int token, int messageRef,  @SendStatusResult int status,
+            int reason, int networkErrorCode)
+            throws RuntimeException {
         synchronized (mLock) {
             if (mListener == null) {
                 throw new RuntimeException("Feature not ready.");
             }
             try {
-                mListener.onSmsStatusReportReceived(token, messageRef, format, pdu);
+                mListener.onSendSmsResult(token, messageRef, status, reason, networkErrorCode);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * This method should be triggered by the IMS providers when the status report of the sent
+     * message is received. The platform will handle the report and notify the IMS provider of the
+     * result by calling {@link #acknowledgeSmsReport(int, int, int)}.
+     *
+     * This method must not be called before {@link #onReady()} is called or the call will fail. If
+     * the platform is not available, {@link #acknowledgeSmsReport(int, int, int)} will be called
+     * with the {@link #STATUS_REPORT_STATUS_ERROR} result code.
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     *               {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDU representing the content of the status report.
+     * @throws RuntimeException if called before {@link #onReady()} is triggered
+     *
+     * @deprecated Use {@link #onSmsStatusReportReceived(int, String, byte[])} instead without the
+     * message reference.
+     */
+    @Deprecated
+    public final void onSmsStatusReportReceived(int token, int messageRef, String format,
+            byte[] pdu) throws RuntimeException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new RuntimeException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsStatusReportReceived(token, format, pdu);
             } catch (RemoteException e) {
                 Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
                 acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
@@ -310,6 +410,46 @@
     }
 
     /**
+     * This method should be triggered by the IMS providers when the status report of the sent
+     * message is received. The platform will handle the report and notify the IMS provider of the
+     * result by calling {@link #acknowledgeSmsReport(int, int, int)}.
+     *
+     * This method must not be called before {@link #onReady()} is called or the call will fail. If
+     * the platform is not available, {@link #acknowledgeSmsReport(int, int, int)} will be called
+     * with the {@link #STATUS_REPORT_STATUS_ERROR} result code.
+     * @param token unique token generated by IMS providers that the platform will use to trigger
+     *              callbacks for this message.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     *               {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDU representing the content of the status report.
+     * @throws RuntimeException if called before {@link #onReady()} is triggered
+     */
+    public final void onSmsStatusReportReceived(int token, String format, byte[] pdu)
+            throws RuntimeException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new RuntimeException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsStatusReportReceived(token, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
+                SmsMessage message = SmsMessage.createFromPdu(pdu, format);
+                if (message != null && message.mWrappedSmsMessage != null) {
+                    acknowledgeSmsReport(
+                            token,
+                            message.mWrappedSmsMessage.mMessageRef,
+                            STATUS_REPORT_STATUS_ERROR);
+                } else {
+                    Log.w(LOG_TAG,
+                            "onSmsStatusReportReceivedWithoutMessageRef: Invalid pdu entered.");
+                    acknowledgeSmsReport(token, 0, STATUS_REPORT_STATUS_ERROR);
+                }
+            }
+        }
+    }
+
+    /**
      * Returns the SMS format. Default is {@link SmsMessage#FORMAT_3GPP} unless overridden by IMS
      * Provider.
      *
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index a2dcc78..b9e6c93 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2003,6 +2003,13 @@
      */
     int getRadioHalVersion();
 
+    /**
+     * Returns true if the specified type of application (e.g. {@link #APPTYPE_CSIM} is present
+     * on the UICC card.
+     * @hide
+     */
+    boolean isApplicationOnUicc(int subId, int appType);
+
     boolean isModemEnabledForSlot(int slotIndex, String callingPackage);
 
     boolean isDataEnabledForApn(int apnType, int subId, String callingPackage);
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 34ac3dc..adc9e22 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -21,7 +21,7 @@
 
     srcs: [
         "src/**/*.java",
-        ":framework-srcs",
+        ":framework-all-sources",
     ],
 
     api_packages: [
diff --git a/tests/FlickerTests/lib/Android.bp b/tests/FlickerTests/lib/Android.bp
index 5d8ed2c..e0f0188 100644
--- a/tests/FlickerTests/lib/Android.bp
+++ b/tests/FlickerTests/lib/Android.bp
@@ -30,10 +30,23 @@
 }
 
 java_library {
+    name: "flickerlib_without_helpers",
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
+    exclude_srcs: ["src/**/helpers/*.java"],
+    static_libs: [
+        "cts-wm-util",
+        "platformprotosnano",
+        "layersprotosnano",
+        "truth-prebuilt"
+    ],
+}
+
+java_library {
     name: "flickerautomationhelperlib",
     sdk_version: "test_current",
     srcs: [
-        "src/com/android/server/wm/flicker/AutomationUtils.java",
+        "src/com/android/server/wm/flicker/helpers/AutomationUtils.java",
         "src/com/android/server/wm/flicker/WindowUtils.java",
     ],
     static_libs: [
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java
index 84f9f871..38255ee 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java
@@ -24,14 +24,14 @@
  * results. Assertions are functions that are applied over a single trace entry and returns a
  * result which includes a detailed reason if the assertion fails.
  */
-class Assertions {
+public class Assertions {
     /**
      * Checks assertion on a single trace entry.
      *
      * @param <T> trace entry type to perform the assertion on.
      */
     @FunctionalInterface
-    interface TraceAssertion<T> extends Function<T, Result> {
+    public interface TraceAssertion<T> extends Function<T, Result> {
         /**
          * Returns an assertion that represents the logical negation of this assertion.
          *
@@ -46,7 +46,7 @@
      * Checks assertion on a single layers trace entry.
      */
     @FunctionalInterface
-    interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> {
+    public interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> {
 
     }
 
@@ -54,11 +54,11 @@
      * Utility class to store assertions with an identifier to help generate more useful debug
      * data when dealing with multiple assertions.
      */
-    static class NamedAssertion<T> {
-        final TraceAssertion<T> assertion;
-        final String name;
+    public static class NamedAssertion<T> {
+        public final TraceAssertion<T> assertion;
+        public final String name;
 
-        NamedAssertion(TraceAssertion<T> assertion, String name) {
+        public NamedAssertion(TraceAssertion<T> assertion, String name) {
             this.assertion = assertion;
             this.name = name;
         }
@@ -67,21 +67,21 @@
     /**
      * Contains the result of an assertion including the reason for failed assertions.
      */
-    static class Result {
-        static final String NEGATION_PREFIX = "!";
-        final boolean success;
-        final long timestamp;
-        final String assertionName;
-        final String reason;
+    public static class Result {
+        public static final String NEGATION_PREFIX = "!";
+        public final boolean success;
+        public final long timestamp;
+        public final String assertionName;
+        public final String reason;
 
-        Result(boolean success, long timestamp, String assertionName, String reason) {
+        public Result(boolean success, long timestamp, String assertionName, String reason) {
             this.success = success;
             this.timestamp = timestamp;
             this.assertionName = assertionName;
             this.reason = reason;
         }
 
-        Result(boolean success, String reason) {
+        public Result(boolean success, String reason) {
             this.success = success;
             this.reason = reason;
             this.assertionName = "";
@@ -91,7 +91,7 @@
         /**
          * Returns the negated {@code Result} and adds a negation prefix to the assertion name.
          */
-        Result negate() {
+        public Result negate() {
             String negatedAssertionName;
             if (this.assertionName.startsWith(NEGATION_PREFIX)) {
                 negatedAssertionName = this.assertionName.substring(NEGATION_PREFIX.length() + 1);
@@ -101,11 +101,11 @@
             return new Result(!this.success, this.timestamp, negatedAssertionName, this.reason);
         }
 
-        boolean passed() {
+        public boolean passed() {
             return this.success;
         }
 
-        boolean failed() {
+        public boolean failed() {
             return !this.success;
         }
 
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java
index 3c65d3c..5c4df81 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java
@@ -38,11 +38,11 @@
     private AssertionOption mOption = AssertionOption.NONE;
     private List<NamedAssertion<T>> mAssertions = new LinkedList<>();
 
-    void add(Assertions.TraceAssertion<T> assertion, String name) {
+    public void add(Assertions.TraceAssertion<T> assertion, String name) {
         mAssertions.add(new NamedAssertion<>(assertion, name));
     }
 
-    void filterByRange(long startTime, long endTime) {
+    public void filterByRange(long startTime, long endTime) {
         mFilterEntriesByRange = true;
         mFilterStartTime = startTime;
         mFilterEndTime = endTime;
@@ -75,7 +75,7 @@
      * @param entries list of entries to perform assertions on
      * @return list of failed assertion results
      */
-    List<Result> test(List<T> entries) {
+    public List<Result> test(List<T> entries) {
         List<T> filteredEntries;
         List<Result> failures;
 
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java
index 9525f41..c47f7f4 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java
@@ -19,7 +19,7 @@
 /**
  * Common interface for Layer and WindowManager trace entries.
  */
-interface ITraceEntry {
+public interface ITraceEntry {
     /**
      * @return timestamp of current entry
      */
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java
index 660ec0f..68986d4 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker;
 
-import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.surfaceflinger.nano.Layers.LayerProto;
 import android.surfaceflinger.nano.Layers.RectProto;
@@ -25,11 +24,14 @@
 import android.surfaceflinger.nano.Layerstrace.LayersTraceProto;
 import android.util.SparseArray;
 
+import androidx.annotation.Nullable;
+
 import com.android.server.wm.flicker.Assertions.Result;
 
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -57,7 +59,7 @@
      * @param data   binary proto data
      * @param source Path to source of data for additional debug information
      */
-    static LayersTrace parseFrom(byte[] data, Path source) {
+    public static LayersTrace parseFrom(byte[] data, Path source) {
         List<Entry> entries = new ArrayList<>();
         LayersTraceFileProto fileProto;
         try {
@@ -79,15 +81,15 @@
      *
      * @param data binary proto data
      */
-    static LayersTrace parseFrom(byte[] data) {
+    public static LayersTrace parseFrom(byte[] data) {
         return parseFrom(data, null);
     }
 
-    List<Entry> getEntries() {
+    public List<Entry> getEntries() {
         return mEntries;
     }
 
-    Entry getEntry(long timestamp) {
+    public Entry getEntry(long timestamp) {
         Optional<Entry> entry = mEntries.stream()
                 .filter(e -> e.getTimestamp() == timestamp)
                 .findFirst();
@@ -97,14 +99,14 @@
         return entry.get();
     }
 
-    Optional<Path> getSource() {
+    public Optional<Path> getSource() {
         return Optional.ofNullable(mSource);
     }
 
     /**
      * Represents a single Layer trace entry.
      */
-    static class Entry implements ITraceEntry {
+    public static class Entry implements ITraceEntry {
         private long mTimestamp;
         private List<Layer> mRootLayers; // hierarchical representation of layers
         private List<Layer> mFlattenedLayers = null;
@@ -117,7 +119,7 @@
         /**
          * Constructs the layer hierarchy from a flattened list of layers.
          */
-        static Entry fromFlattenedLayers(long timestamp, LayerProto[] protos) {
+        public static Entry fromFlattenedLayers(long timestamp, LayerProto[] protos) {
             SparseArray<Layer> layerMap = new SparseArray<>();
             ArrayList<Layer> orphans = new ArrayList<>();
             for (LayerProto proto : protos) {
@@ -181,7 +183,7 @@
         /**
          * Checks if a region specified by {@code testRect} is covered by all visible layers.
          */
-        Result coversRegion(Rect testRect) {
+        public Result coversRegion(Rect testRect) {
             String assertionName = "coversRegion";
             Collection<Layer> layers = asFlattenedLayers();
 
@@ -224,7 +226,7 @@
          * Checks if a layer with name {@code layerName} has a visible region
          * {@code expectedVisibleRegion}.
          */
-        Result hasVisibleRegion(String layerName, Rect expectedVisibleRegion) {
+        public Result hasVisibleRegion(String layerName, Rect expectedVisibleRegion) {
             String assertionName = "hasVisibleRegion";
             String reason = "Could not find " + layerName;
             for (Layer layer : asFlattenedLayers()) {
@@ -252,7 +254,7 @@
         /**
          * Checks if a layer with name {@code layerName} is visible.
          */
-        Result isVisible(String layerName) {
+        public Result isVisible(String layerName) {
             String assertionName = "isVisible";
             String reason = "Could not find " + layerName;
             for (Layer layer : asFlattenedLayers()) {
@@ -277,24 +279,27 @@
             return mTimestamp;
         }
 
-        List<Layer> getRootLayers() {
+        public List<Layer> getRootLayers() {
             return mRootLayers;
         }
 
-        List<Layer> asFlattenedLayers() {
+        /**
+         * Returns all layers as a flattened list using a depth first traversal.
+         */
+        public List<Layer> asFlattenedLayers() {
             if (mFlattenedLayers == null) {
-                mFlattenedLayers = new ArrayList<>();
+                mFlattenedLayers = new LinkedList<>();
                 ArrayList<Layer> pendingLayers = new ArrayList<>(this.mRootLayers);
                 while (!pendingLayers.isEmpty()) {
                     Layer layer = pendingLayers.remove(0);
                     mFlattenedLayers.add(layer);
-                    pendingLayers.addAll(layer.mChildren);
+                    pendingLayers.addAll(0, layer.mChildren);
                 }
             }
             return mFlattenedLayers;
         }
 
-        Rect getVisibleBounds(String layerName) {
+        public Rect getVisibleBounds(String layerName) {
             List<Layer> layers = asFlattenedLayers();
             for (Layer layer : layers) {
                 if (layer.mProto.name.contains(layerName) && layer.isVisible()) {
@@ -308,12 +313,12 @@
     /**
      * Represents a single layer with links to its parent and child layers.
      */
-    static class Layer {
+    public static class Layer {
         @Nullable
-        LayerProto mProto;
-        List<Layer> mChildren;
+        public LayerProto mProto;
+        public List<Layer> mChildren;
         @Nullable
-        Layer mParent = null;
+        public Layer mParent = null;
 
         private Layer(LayerProto proto) {
             this.mProto = proto;
@@ -328,16 +333,16 @@
             this.mParent = parentLayer;
         }
 
-        int getId() {
+        public int getId() {
             return mProto.id;
         }
 
-        boolean isActiveBufferEmpty() {
+        public boolean isActiveBufferEmpty() {
             return this.mProto.activeBuffer == null || this.mProto.activeBuffer.height == 0
                     || this.mProto.activeBuffer.width == 0;
         }
 
-        boolean isVisibleRegionEmpty() {
+        public boolean isVisibleRegionEmpty() {
             if (this.mProto.visibleRegion == null) {
                 return true;
             }
@@ -345,32 +350,35 @@
             return visibleRect.height() == 0 || visibleRect.width() == 0;
         }
 
-        boolean isHidden() {
+        public boolean isHidden() {
             return (this.mProto.flags & /* FLAG_HIDDEN */ 0x1) != 0x0;
         }
 
-        boolean isVisible() {
-            return (!isActiveBufferEmpty() || isColorLayer()) &&
-                    !isHidden() && this.mProto.color.a > 0 && !isVisibleRegionEmpty();
+        public boolean isVisible() {
+            return (!isActiveBufferEmpty() || isColorLayer())
+                    && !isHidden()
+                    && this.mProto.color != null
+                    && this.mProto.color.a > 0
+                    && !isVisibleRegionEmpty();
         }
 
-        boolean isColorLayer() {
+        public boolean isColorLayer() {
             return this.mProto.type.equals("ColorLayer");
         }
 
-        boolean isRootLayer() {
+        public boolean isRootLayer() {
             return mParent == null || mParent.mProto == null;
         }
 
-        boolean isInvisible() {
+        public boolean isInvisible() {
             return !isVisible();
         }
 
-        boolean isHiddenByParent() {
+        public boolean isHiddenByParent() {
             return !isRootLayer() && (mParent.isHidden() || mParent.isHiddenByParent());
         }
 
-        String getHiddenByParentReason() {
+        public String getHiddenByParentReason() {
             String reason = "Layer " + mProto.name;
             if (isHiddenByParent()) {
                 reason += " is hidden by parent: " + mParent.mProto.name;
@@ -380,7 +388,7 @@
             return reason;
         }
 
-        String getVisibilityReason() {
+        public String getVisibilityReason() {
             String reason = "Layer " + mProto.name;
             if (isVisible()) {
                 reason += " is visible:";
@@ -399,7 +407,7 @@
                 if (isHidden()) {
                     reason += " flags=" + this.mProto.flags + " (FLAG_HIDDEN set)";
                 }
-                if (this.mProto.color.a == 0) {
+                if (this.mProto.color == null || this.mProto.color.a == 0) {
                     reason += " color.a=0";
                 }
                 if (isVisibleRegionEmpty()) {
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java
index 4085810..4a5129e 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java
@@ -19,9 +19,10 @@
 import static com.google.common.truth.Truth.assertAbout;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import android.annotation.Nullable;
 import android.graphics.Rect;
 
+import androidx.annotation.Nullable;
+
 import com.android.server.wm.flicker.Assertions.Result;
 import com.android.server.wm.flicker.LayersTrace.Entry;
 import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
index 0a3fe3c..241a1c0 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
@@ -16,10 +16,12 @@
 
 package com.android.server.wm.flicker;
 
-import android.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
+import static com.android.server.wm.flicker.monitor.ITransitionMonitor.OUTPUT_DIR;
+
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.test.InstrumentationRegistry;
 
 import com.android.server.wm.flicker.monitor.ITransitionMonitor;
@@ -89,7 +91,7 @@
  * }
  * </pre>
  */
-class TransitionRunner {
+public class TransitionRunner {
     private static final String TAG = "FLICKER";
     private final ScreenRecorder mScreenRecorder;
     private final WindowManagerTraceMonitor mWmTraceMonitor;
@@ -128,8 +130,12 @@
         mTestTag = builder.mTestTag;
     }
 
-    static TransitionBuilder newBuilder() {
-        return new TransitionBuilder();
+    public static TransitionBuilder newBuilder() {
+        return newBuilder(OUTPUT_DIR.toString());
+    }
+
+    public static TransitionBuilder newBuilder(String outputDir) {
+        return new TransitionBuilder(outputDir);
     }
 
     /**
@@ -138,7 +144,7 @@
      *
      * @return itself
      */
-    TransitionRunner run() {
+    public TransitionRunner run() {
         mResults = new ArrayList<>();
         mAllRunsMonitors.forEach(ITransitionMonitor::start);
         mBeforeAlls.forEach(Runnable::run);
@@ -159,8 +165,7 @@
         mAfterAlls.forEach(Runnable::run);
         mAllRunsMonitors.forEach(monitor -> {
             monitor.stop();
-            Path path = monitor.save(mTestTag);
-            Log.e(TAG, "Video saved to " + path.toString());
+            monitor.save(mTestTag);
         });
         return this;
     }
@@ -170,7 +175,7 @@
      *
      * @return list of transition results.
      */
-    List<TransitionResult> getResults() {
+    public List<TransitionResult> getResults() {
         if (mResults == null) {
             throw new IllegalStateException("Results do not exist!");
         }
@@ -182,7 +187,7 @@
      *
      * @return list of transition results.
      */
-    void deleteResults() {
+    public void deleteResults() {
         if (mResults == null) {
             return;
         }
@@ -228,33 +233,33 @@
     @VisibleForTesting
     public static class TransitionResult {
         @Nullable
-        final Path layersTrace;
+        public final Path layersTrace;
         @Nullable
-        final Path windowManagerTrace;
+        public final Path windowManagerTrace;
         @Nullable
-        final Path screenCaptureVideo;
+        public final Path screenCaptureVideo;
         private boolean flaggedForSaving;
 
-        TransitionResult(@Nullable Path layersTrace, @Nullable Path windowManagerTrace,
+        public TransitionResult(@Nullable Path layersTrace, @Nullable Path windowManagerTrace,
                 @Nullable Path screenCaptureVideo) {
             this.layersTrace = layersTrace;
             this.windowManagerTrace = windowManagerTrace;
             this.screenCaptureVideo = screenCaptureVideo;
         }
 
-        void flagForSaving() {
+        public void flagForSaving() {
             flaggedForSaving = true;
         }
 
-        boolean canDelete() {
+        public boolean canDelete() {
             return !flaggedForSaving;
         }
 
-        boolean layersTraceExists() {
+        public boolean layersTraceExists() {
             return layersTrace != null && layersTrace.toFile().exists();
         }
 
-        byte[] getLayersTrace() {
+        public byte[] getLayersTrace() {
             try {
                 return Files.toByteArray(this.layersTrace.toFile());
             } catch (IOException e) {
@@ -262,11 +267,11 @@
             }
         }
 
-        Path getLayersTracePath() {
+        public Path getLayersTracePath() {
             return layersTrace;
         }
 
-        boolean windowManagerTraceExists() {
+        public boolean windowManagerTraceExists() {
             return windowManagerTrace != null && windowManagerTrace.toFile().exists();
         }
 
@@ -278,19 +283,19 @@
             }
         }
 
-        Path getWindowManagerTracePath() {
+        public Path getWindowManagerTracePath() {
             return windowManagerTrace;
         }
 
-        boolean screenCaptureVideoExists() {
+        public boolean screenCaptureVideoExists() {
             return screenCaptureVideo != null && screenCaptureVideo.toFile().exists();
         }
 
-        Path screenCaptureVideoPath() {
+        public Path screenCaptureVideoPath() {
             return screenCaptureVideo;
         }
 
-        void delete() {
+        public void delete() {
             if (layersTraceExists()) layersTrace.toFile().delete();
             if (windowManagerTraceExists()) windowManagerTrace.toFile().delete();
             if (screenCaptureVideoExists()) screenCaptureVideo.toFile().delete();
@@ -300,7 +305,7 @@
     /**
      * Builds a {@link TransitionRunner} instance.
      */
-    static class TransitionBuilder {
+    public static class TransitionBuilder {
         private ScreenRecorder mScreenRecorder;
         private WindowManagerTraceMonitor mWmTraceMonitor;
         private LayersTraceMonitor mLayersTraceMonitor;
@@ -323,15 +328,15 @@
 
         private boolean mRecordAllRuns = false;
 
-        TransitionBuilder() {
+        public TransitionBuilder(String outputDir) {
             mScreenRecorder = new ScreenRecorder();
-            mWmTraceMonitor = new WindowManagerTraceMonitor();
-            mLayersTraceMonitor = new LayersTraceMonitor();
+            mWmTraceMonitor = new WindowManagerTraceMonitor(outputDir);
+            mLayersTraceMonitor = new LayersTraceMonitor(outputDir);
             mFrameStatsMonitor = new
                     WindowAnimationFrameStatsMonitor(InstrumentationRegistry.getInstrumentation());
         }
 
-        TransitionRunner build() {
+        public TransitionRunner build() {
             if (mCaptureWindowManagerTrace) {
                 mPerRunMonitors.add(mWmTraceMonitor);
             }
@@ -355,52 +360,52 @@
             return new TransitionRunner(this);
         }
 
-        TransitionBuilder runBeforeAll(Runnable runnable) {
+        public TransitionBuilder runBeforeAll(Runnable runnable) {
             mBeforeAlls.add(runnable);
             return this;
         }
 
-        TransitionBuilder runBefore(Runnable runnable) {
+        public TransitionBuilder runBefore(Runnable runnable) {
             mBefores.add(runnable);
             return this;
         }
 
-        TransitionBuilder run(Runnable runnable) {
+        public TransitionBuilder run(Runnable runnable) {
             mTransitions.add(runnable);
             return this;
         }
 
-        TransitionBuilder runAfter(Runnable runnable) {
+        public TransitionBuilder runAfter(Runnable runnable) {
             mAfters.add(runnable);
             return this;
         }
 
-        TransitionBuilder runAfterAll(Runnable runnable) {
+        public TransitionBuilder runAfterAll(Runnable runnable) {
             mAfterAlls.add(runnable);
             return this;
         }
 
-        TransitionBuilder repeat(int iterations) {
+        public TransitionBuilder repeat(int iterations) {
             mIterations = iterations;
             return this;
         }
 
-        TransitionBuilder skipWindowManagerTrace() {
+        public TransitionBuilder skipWindowManagerTrace() {
             mCaptureWindowManagerTrace = false;
             return this;
         }
 
-        TransitionBuilder skipLayersTrace() {
+        public TransitionBuilder skipLayersTrace() {
             mCaptureLayersTrace = false;
             return this;
         }
 
-        TransitionBuilder includeJankyRuns() {
+        public TransitionBuilder includeJankyRuns() {
             mRunJankFree = false;
             return this;
         }
 
-        TransitionBuilder recordEachRun() {
+        public TransitionBuilder recordEachRun() {
             if (mRecordAllRuns) {
                 throw new IllegalArgumentException("Invalid option with recordAllRuns");
             }
@@ -408,7 +413,7 @@
             return this;
         }
 
-        TransitionBuilder recordAllRuns() {
+        public TransitionBuilder recordAllRuns() {
             if (mRecordEachRun) {
                 throw new IllegalArgumentException("Invalid option with recordEachRun");
             }
@@ -416,7 +421,11 @@
             return this;
         }
 
-        TransitionBuilder withTag(String testTag) {
+        public TransitionBuilder withTag(String testTag) {
+            if (testTag.contains(" ")) {
+                throw new IllegalArgumentException("The test tag can not contain spaces since it "
+                        + "is a part of the file name");
+            }
             mTestTag = testTag;
             return this;
         }
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java
index e3592eb..412e72d8 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm.flicker;
 
-import android.annotation.Nullable;
+import androidx.annotation.Nullable;
 
 import com.android.server.wm.flicker.Assertions.Result;
 import com.android.server.wm.nano.AppWindowTokenProto;
@@ -58,7 +58,7 @@
      * @param data   binary proto data
      * @param source Path to source of data for additional debug information
      */
-    static WindowManagerTrace parseFrom(byte[] data, Path source) {
+    public static WindowManagerTrace parseFrom(byte[] data, Path source) {
         List<Entry> entries = new ArrayList<>();
 
         WindowManagerTraceFileProto fileProto;
@@ -73,7 +73,7 @@
         return new WindowManagerTrace(entries, source);
     }
 
-    static WindowManagerTrace parseFrom(byte[] data) {
+    public static WindowManagerTrace parseFrom(byte[] data) {
         return parseFrom(data, null);
     }
 
@@ -81,7 +81,7 @@
         return mEntries;
     }
 
-    Entry getEntry(long timestamp) {
+    public Entry getEntry(long timestamp) {
         Optional<Entry> entry = mEntries.stream()
                 .filter(e -> e.getTimestamp() == timestamp)
                 .findFirst();
@@ -91,17 +91,17 @@
         return entry.get();
     }
 
-    Optional<Path> getSource() {
+    public Optional<Path> getSource() {
         return Optional.ofNullable(mSource);
     }
 
     /**
      * Represents a single WindowManager trace entry.
      */
-    static class Entry implements ITraceEntry {
+    public static class Entry implements ITraceEntry {
         private final WindowManagerTraceProto mProto;
 
-        Entry(WindowManagerTraceProto proto) {
+        public Entry(WindowManagerTraceProto proto) {
             mProto = proto;
         }
 
@@ -162,7 +162,7 @@
         /**
          * Checks if aboveAppWindow with {@code windowTitle} is visible.
          */
-        Result isAboveAppWindowVisible(String windowTitle) {
+        public Result isAboveAppWindowVisible(String windowTitle) {
             WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
                     .rootWindowContainer
                     .displays[DEFAULT_DISPLAY].aboveAppWindows;
@@ -173,7 +173,7 @@
         /**
          * Checks if belowAppWindow with {@code windowTitle} is visible.
          */
-        Result isBelowAppWindowVisible(String windowTitle) {
+        public Result isBelowAppWindowVisible(String windowTitle) {
             WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
                     .rootWindowContainer
                     .displays[DEFAULT_DISPLAY].belowAppWindows;
@@ -185,7 +185,7 @@
         /**
          * Checks if imeWindow with {@code windowTitle} is visible.
          */
-        Result isImeWindowVisible(String windowTitle) {
+        public Result isImeWindowVisible(String windowTitle) {
             WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
                     .rootWindowContainer
                     .displays[DEFAULT_DISPLAY].imeWindows;
@@ -197,7 +197,7 @@
         /**
          * Checks if app window with {@code windowTitle} is on top.
          */
-        Result isVisibleAppWindowOnTop(String windowTitle) {
+        public Result isVisibleAppWindowOnTop(String windowTitle) {
             String topAppWindow = getTopVisibleAppWindow();
             boolean success = topAppWindow.contains(windowTitle);
             String reason = "wanted=" + windowTitle + " found=" + topAppWindow;
@@ -207,7 +207,7 @@
         /**
          * Checks if app window with {@code windowTitle} is visible.
          */
-        Result isAppWindowVisible(String windowTitle) {
+        public Result isAppWindowVisible(String windowTitle) {
             final String assertionName = "isAppWindowVisible";
             boolean titleFound = false;
             StackProto[] stacks = mProto.windowManagerService.rootWindowContainer
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
index c54396f..3d25fbe 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
@@ -28,9 +28,9 @@
 /**
  * Helper functions to retrieve system window sizes and positions.
  */
-class WindowUtils {
+public class WindowUtils {
 
-    static Rect getDisplayBounds() {
+    public static Rect getDisplayBounds() {
         Point display = new Point();
         WindowManager wm =
                 (WindowManager) InstrumentationRegistry.getContext().getSystemService(
@@ -46,7 +46,7 @@
         return wm.getDefaultDisplay().getRotation();
     }
 
-    static Rect getDisplayBounds(int requestedRotation) {
+    public static Rect getDisplayBounds(int requestedRotation) {
         Rect displayBounds = getDisplayBounds();
         int currentDisplayRotation = getCurrentRotation();
 
@@ -66,7 +66,7 @@
     }
 
 
-    static Rect getAppPosition(int requestedRotation) {
+    public static Rect getAppPosition(int requestedRotation) {
         Rect displayBounds = getDisplayBounds();
         int currentDisplayRotation = getCurrentRotation();
 
@@ -85,7 +85,7 @@
         return new Rect(0, 0, displayBounds.width(), displayBounds.height());
     }
 
-    static Rect getStatusBarPosition(int requestedRotation) {
+    public static Rect getStatusBarPosition(int requestedRotation) {
         Resources resources = InstrumentationRegistry.getContext().getResources();
         String resourceName;
         Rect displayBounds = getDisplayBounds();
@@ -104,7 +104,7 @@
         return new Rect(0, 0, width, height);
     }
 
-    static Rect getNavigationBarPosition(int requestedRotation) {
+    public static Rect getNavigationBarPosition(int requestedRotation) {
         Resources resources = InstrumentationRegistry.getContext().getResources();
         Rect displayBounds = getDisplayBounds();
         int displayWidth = Math.min(displayBounds.width(), displayBounds.height());
@@ -129,13 +129,13 @@
         }
     }
 
-    static int getNavigationBarHeight() {
+    public static int getNavigationBarHeight() {
         Resources resources = InstrumentationRegistry.getContext().getResources();
         int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
         return resources.getDimensionPixelSize(resourceId);
     }
 
-    static int getDockedStackDividerInset() {
+    public static int getDockedStackDividerInset() {
         Resources resources = InstrumentationRegistry.getContext().getResources();
         int resourceId = resources.getIdentifier("docked_stack_divider_insets", "dimen",
                 "android");
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java
index e76da6e..064cc27 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java
@@ -19,7 +19,7 @@
 import static com.google.common.truth.Truth.assertAbout;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import android.annotation.Nullable;
+import androidx.annotation.Nullable;
 
 import com.android.server.wm.flicker.Assertions.Result;
 import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/helpers/AutomationUtils.java
similarity index 95%
rename from tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
rename to tests/FlickerTests/lib/src/com/android/server/wm/flicker/helpers/AutomationUtils.java
index e00a247..6821ff0 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/helpers/AutomationUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.wm.flicker;
+package com.android.server.wm.flicker.helpers;
 
 import static android.os.SystemClock.sleep;
 import static android.system.helpers.OverviewHelper.isRecentsInLauncher;
@@ -44,6 +44,8 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.server.wm.flicker.WindowUtils;
+
 /**
  * Collection of UI Automation helper functions.
  */
@@ -70,14 +72,14 @@
      * This removes some delays when using the UIAutomator library required to create fast UI
      * transitions.
      */
-    static void setFastWait() {
+    public static void setFastWait() {
         Configurator.getInstance().setWaitForIdleTimeout(0);
     }
 
     /**
      * Reverts {@link android.app.UiAutomation#waitForIdle(long, long)} to default behavior.
      */
-    static void setDefaultWait() {
+    public static void setDefaultWait() {
         Configurator.getInstance().setWaitForIdleTimeout(10000);
     }
 
@@ -124,7 +126,7 @@
         device.waitForIdle();
     }
 
-    static void clearRecents(UiDevice device) {
+    public static void clearRecents(UiDevice device) {
         if (isQuickstepEnabled(device)) {
             openQuickstep(device);
 
@@ -201,7 +203,7 @@
         sleep(2000);
     }
 
-    static void resizeSplitScreen(UiDevice device, Rational windowHeightRatio) {
+    public static void resizeSplitScreen(UiDevice device, Rational windowHeightRatio) {
         BySelector dividerSelector = By.res(SYSTEMUI_PACKAGE, "docked_divider_handle");
         UiObject2 divider = device.wait(Until.findObject(dividerSelector), FIND_TIMEOUT);
         assertNotNull("Unable to find Split screen divider", divider);
@@ -218,7 +220,7 @@
         sleep(2000);
     }
 
-    static void closePipWindow(UiDevice device) {
+    public static void closePipWindow(UiDevice device) {
         UiObject2 pipWindow = device.findObject(
                 By.res(SYSTEMUI_PACKAGE, "background"));
         pipWindow.click();
@@ -229,7 +231,7 @@
         sleep(2000);
     }
 
-    static void expandPipWindow(UiDevice device) {
+    public static void expandPipWindow(UiDevice device) {
         UiObject2 pipWindow = device.findObject(
                 By.res(SYSTEMUI_PACKAGE, "background"));
         pipWindow.click();
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
index c55d068..da75b3e 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
@@ -16,21 +16,22 @@
 
 package com.android.server.wm.flicker.monitor;
 
-import android.os.IBinder;
-import android.os.Parcel;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
 
 /**
  * Captures Layers trace from SurfaceFlinger.
  */
 public class LayersTraceMonitor extends TraceMonitor {
-    private static final String TAG = "LayersTraceMonitor";
-    private IBinder mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
+    private IWindowManager mWm = WindowManagerGlobal.getWindowManagerService();
 
     public LayersTraceMonitor() {
-        traceFileName = "layers_trace.pb";
+        this(OUTPUT_DIR.toString());
+    }
+
+    public LayersTraceMonitor(String outputDir) {
+        super(outputDir, "layers_trace.pb");
     }
 
     @Override
@@ -45,30 +46,19 @@
 
     @Override
     public boolean isEnabled() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken("android.ui.ISurfaceComposer");
-        mSurfaceFlinger.transact(/* LAYER_TRACE_STATUS_CODE */ 1026,
-                data, reply, 0 /* flags */);
-        return reply.readBoolean();
+        try {
+            return mWm.isLayerTracing();
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+        return false;
     }
 
     private void setEnabled(boolean isEnabled) {
-        Parcel data = null;
         try {
-            if (mSurfaceFlinger != null) {
-                data = Parcel.obtain();
-                data.writeInterfaceToken("android.ui.ISurfaceComposer");
-                data.writeInt(isEnabled ? 1 : 0);
-                mSurfaceFlinger.transact( /* LAYER_TRACE_CONTROL_CODE */ 1025,
-                        data, null, 0 /* flags */);
-            }
+            mWm.setLayerTracing(isEnabled);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not set layer tracing." + e.toString());
-        } finally {
-            if (data != null) {
-                data.recycle();
-            }
+            e.printStackTrace();
         }
     }
 }
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java
index 4787586..dce1c27 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java
@@ -20,25 +20,25 @@
 
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 
-import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 
 /**
  * Captures screen contents and saves it as a mp4 video file.
  */
 public class ScreenRecorder implements ITransitionMonitor {
     @VisibleForTesting
-    static final Path DEFAULT_OUTPUT_PATH = OUTPUT_DIR.resolve("transition.mp4");
+    public static final Path DEFAULT_OUTPUT_PATH = OUTPUT_DIR.resolve("transition.mp4");
     private static final String TAG = "FLICKER";
     private Thread recorderThread;
 
     @VisibleForTesting
-    static Path getPath(String testTag) {
+    public static Path getPath(String testTag) {
         return OUTPUT_DIR.resolve(testTag + ".mp4");
     }
 
@@ -69,8 +69,10 @@
     @Override
     public Path save(String testTag) {
         try {
-            return Files.move(DEFAULT_OUTPUT_PATH, getPath(testTag),
+            Path targetPath = Files.move(DEFAULT_OUTPUT_PATH, getPath(testTag),
                     REPLACE_EXISTING);
+            Log.i(TAG, "Video saved to " + targetPath.toString());
+            return targetPath;
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java
index 0e154ec..1ba36bb 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java
@@ -20,7 +20,7 @@
 
 import android.os.RemoteException;
 
-import com.android.internal.annotations.VisibleForTesting;
+import androidx.annotation.VisibleForTesting;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -34,9 +34,15 @@
     public static final String TAG = "FLICKER";
     private static final String TRACE_DIR = "/data/misc/wmtrace/";
 
-    String traceFileName;
+    private Path mOutputDir;
+    public String mTraceFileName;
 
-    abstract boolean isEnabled() throws RemoteException;
+    public abstract boolean isEnabled() throws RemoteException;
+
+    public TraceMonitor(String outputDir, String traceFileName) {
+        mOutputDir = Paths.get(outputDir);
+        mTraceFileName = traceFileName;
+    }
 
     /**
      * Saves trace file to the external storage directory suffixing the name with the testtag
@@ -53,14 +59,16 @@
     public Path save(String testTag) {
         OUTPUT_DIR.toFile().mkdirs();
         Path traceFileCopy = getOutputTraceFilePath(testTag);
+
+        // Read the input stream fully.
         String copyCommand = String.format(Locale.getDefault(), "mv %s%s %s", TRACE_DIR,
-                traceFileName, traceFileCopy.toString());
+                mTraceFileName, traceFileCopy.toString());
         runShellCommand(copyCommand);
         return traceFileCopy;
     }
 
     @VisibleForTesting
-    Path getOutputTraceFilePath(String testTag) {
-        return OUTPUT_DIR.resolve(traceFileName + "_" + testTag);
+    public Path getOutputTraceFilePath(String testTag) {
+        return mOutputDir.resolve(mTraceFileName + "_" + testTag);
     }
 }
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java
index ae160b68..11de4aa 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java
@@ -24,16 +24,20 @@
  * Captures WindowManager trace from WindowManager.
  */
 public class WindowManagerTraceMonitor extends TraceMonitor {
-    private IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+    private IWindowManager mWm = WindowManagerGlobal.getWindowManagerService();
 
     public WindowManagerTraceMonitor() {
-        traceFileName = "wm_trace.pb";
+        this(OUTPUT_DIR.toString());
+    }
+
+    public WindowManagerTraceMonitor(String outputDir) {
+        super(outputDir, "wm_trace.pb");
     }
 
     @Override
     public void start() {
         try {
-            wm.startWindowTrace();
+            mWm.startWindowTrace();
         } catch (RemoteException e) {
             throw new RuntimeException("Could not start trace", e);
         }
@@ -42,7 +46,7 @@
     @Override
     public void stop() {
         try {
-            wm.stopWindowTrace();
+            mWm.stopWindowTrace();
         } catch (RemoteException e) {
             throw new RuntimeException("Could not stop trace", e);
         }
@@ -50,6 +54,6 @@
 
     @Override
     public boolean isEnabled() throws RemoteException{
-        return wm.isWindowTraceEnabled();
+        return mWm.isWindowTraceEnabled();
     }
 }
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
index dd6fed0..f312384 100644
--- a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm.flicker.monitor;
 
-import static com.android.server.wm.flicker.AutomationUtils.wakeUpAndGoToHomeScreen;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.wakeUpAndGoToHomeScreen;
 
 import androidx.test.InstrumentationRegistry;
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
index 65888ac..5cf2c1c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
@@ -19,12 +19,12 @@
 import static android.os.SystemClock.sleep;
 import static android.view.Surface.rotationToString;
 
-import static com.android.server.wm.flicker.AutomationUtils.clearRecents;
-import static com.android.server.wm.flicker.AutomationUtils.closePipWindow;
-import static com.android.server.wm.flicker.AutomationUtils.exitSplitScreen;
-import static com.android.server.wm.flicker.AutomationUtils.expandPipWindow;
-import static com.android.server.wm.flicker.AutomationUtils.launchSplitScreen;
-import static com.android.server.wm.flicker.AutomationUtils.stopPackage;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.clearRecents;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.closePipWindow;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.exitSplitScreen;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.expandPipWindow;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.launchSplitScreen;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.stopPackage;
 
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +40,7 @@
 import androidx.test.InstrumentationRegistry;
 
 import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
+import com.android.server.wm.flicker.helpers.AutomationUtils;
 
 /**
  * Collection of common transitions which can be used to test different apps or scenarios.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
index 00e11c0..8c9d6b4d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm.flicker;
 
-import static com.android.server.wm.flicker.AutomationUtils.setDefaultWait;
+import static com.android.server.wm.flicker.helpers.AutomationUtils.setDefaultWait;
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 213bdd2..7966ba2 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -177,6 +177,11 @@
   return main_command->Execute(args, &std::cerr);
 }
 
+// TODO(b/141312058) stop leaks
+extern "C" const char *__asan_default_options() {
+    return "detect_leaks=0";
+}
+
 int main(int argc, char** argv) {
 #ifdef _WIN32
   LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &argc);