Merge "Use distinct value for BAL_BLOCK" into main
diff --git a/packages/SystemUI/res/layout/screenshot.xml b/packages/SystemUI/res/layout/screenshot.xml
deleted file mode 100644
index c134c8e..0000000
--- a/packages/SystemUI/res/layout/screenshot.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2011 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<com.android.systemui.screenshot.ScreenshotView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/screenshot_frame"
-    android:theme="@style/FloatingOverlay"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:importantForAccessibility="no">
-    <ImageView
-        android:id="@+id/screenshot_scrolling_scrim"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="gone"
-        android:clickable="true"
-        android:importantForAccessibility="no"/>
-    <ImageView
-        android:id="@+id/screenshot_flash"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="gone"
-        android:elevation="7dp"
-        android:src="@android:color/white"/>
-    <include layout="@layout/screenshot_static"
-             android:id="@+id/screenshot_static"/>
-</com.android.systemui.screenshot.ScreenshotView>
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt
index 1868b4a..54e0319 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt
@@ -40,7 +40,7 @@
     private val intentExecutor: ActionIntentExecutor,
     @Application private val applicationScope: CoroutineScope,
     @Assisted val window: Window,
-    @Assisted val viewProxy: ScreenshotViewProxy,
+    @Assisted val viewProxy: ScreenshotShelfViewProxy,
     @Assisted val finishDismiss: () -> Unit,
 ) {
 
@@ -109,7 +109,7 @@
     interface Factory {
         fun create(
             window: Window,
-            viewProxy: ScreenshotViewProxy,
+            viewProxy: ScreenshotShelfViewProxy,
             finishDismiss: (() -> Unit)
         ): ActionExecutor
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt
deleted file mode 100644
index 3d024a6..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import android.animation.Animator
-import android.app.Notification
-import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.Rect
-import android.util.Log
-import android.view.KeyEvent
-import android.view.LayoutInflater
-import android.view.ScrollCaptureResponse
-import android.view.View
-import android.view.ViewTreeObserver
-import android.view.WindowInsets
-import android.window.OnBackInvokedCallback
-import android.window.OnBackInvokedDispatcher
-import androidx.appcompat.content.res.AppCompatResources
-import com.android.internal.logging.UiEventLogger
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.res.R
-import com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS
-import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER
-import com.android.systemui.screenshot.scroll.ScrollCaptureController
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-
-/**
- * Legacy implementation of screenshot view methods. Just proxies the calls down into the original
- * ScreenshotView.
- */
-class LegacyScreenshotViewProxy
-@AssistedInject
-constructor(
-    private val logger: UiEventLogger,
-    flags: FeatureFlags,
-    @Assisted private val context: Context,
-    @Assisted private val displayId: Int
-) : ScreenshotViewProxy {
-    override val view: ScreenshotView =
-        LayoutInflater.from(context).inflate(R.layout.screenshot, null) as ScreenshotView
-    override val screenshotPreview: View
-    override var packageName: String = ""
-        set(value) {
-            field = value
-            view.setPackageName(value)
-        }
-    override var callbacks: ScreenshotView.ScreenshotViewCallback? = null
-        set(value) {
-            field = value
-            view.setCallbacks(value)
-        }
-    override var screenshot: ScreenshotData? = null
-        set(value) {
-            field = value
-            value?.let {
-                val badgeBg =
-                    AppCompatResources.getDrawable(context, R.drawable.overlay_badge_background)
-                val user = it.userHandle
-                if (badgeBg != null && user != null) {
-                    view.badgeScreenshot(context.packageManager.getUserBadgedIcon(badgeBg, user))
-                }
-                view.setScreenshot(it)
-            }
-        }
-
-    override val isAttachedToWindow
-        get() = view.isAttachedToWindow
-    override val isDismissing
-        get() = view.isDismissing
-    override val isPendingSharedTransition
-        get() = view.isPendingSharedTransition
-
-    init {
-        view.setUiEventLogger(logger)
-        view.setDefaultDisplay(displayId)
-        view.setFlags(flags)
-        addPredictiveBackListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
-        setOnKeyListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
-        if (LogConfig.DEBUG_WINDOW) {
-            Log.d(TAG, "adding OnComputeInternalInsetsListener")
-        }
-        view.viewTreeObserver.addOnComputeInternalInsetsListener(view)
-        screenshotPreview = view.screenshotPreview
-    }
-
-    override fun reset() = view.reset()
-    override fun updateInsets(insets: WindowInsets) = view.updateInsets(insets)
-    override fun updateOrientation(insets: WindowInsets) = view.updateOrientation(insets)
-
-    override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator =
-        view.createScreenshotDropInAnimation(screenRect, showFlash)
-
-    override fun addQuickShareChip(quickShareAction: Notification.Action) =
-        view.addQuickShareChip(quickShareAction)
-
-    override fun setChipIntents(imageData: ScreenshotController.SavedImageData) =
-        view.setChipIntents(imageData)
-
-    override fun requestDismissal(event: ScreenshotEvent?) {
-        if (DEBUG_DISMISS) {
-            Log.d(TAG, "screenshot dismissal requested")
-        }
-        // If we're already animating out, don't restart the animation
-        if (view.isDismissing) {
-            if (DEBUG_DISMISS) {
-                Log.v(TAG, "Already dismissing, ignoring duplicate command $event")
-            }
-            return
-        }
-        event?.let { logger.log(event, 0, packageName) }
-        view.animateDismissal()
-    }
-
-    override fun showScrollChip(packageName: String, onClick: Runnable) =
-        view.showScrollChip(packageName, onClick)
-
-    override fun hideScrollChip() = view.hideScrollChip()
-
-    override fun prepareScrollingTransition(
-        response: ScrollCaptureResponse,
-        screenBitmap: Bitmap,
-        newScreenshot: Bitmap,
-        screenshotTakenInPortrait: Boolean,
-        onTransitionPrepared: Runnable,
-    ) {
-        view.prepareScrollingTransition(
-            response,
-            screenBitmap,
-            newScreenshot,
-            screenshotTakenInPortrait
-        )
-        view.post { onTransitionPrepared.run() }
-    }
-
-    override fun startLongScreenshotTransition(
-        transitionDestination: Rect,
-        onTransitionEnd: Runnable,
-        longScreenshot: ScrollCaptureController.LongScreenshot
-    ) = view.startLongScreenshotTransition(transitionDestination, onTransitionEnd, longScreenshot)
-
-    override fun restoreNonScrollingUi() = view.restoreNonScrollingUi()
-
-    override fun fadeForSharedTransition() {} // unused
-
-    override fun stopInputListening() = view.stopInputListening()
-
-    override fun requestFocus() {
-        view.requestFocus()
-    }
-
-    override fun announceForAccessibility(string: String) = view.announceForAccessibility(string)
-
-    override fun prepareEntranceAnimation(runnable: Runnable) {
-        view.viewTreeObserver.addOnPreDrawListener(
-            object : ViewTreeObserver.OnPreDrawListener {
-                override fun onPreDraw(): Boolean {
-                    if (LogConfig.DEBUG_WINDOW) {
-                        Log.d(TAG, "onPreDraw: startAnimation")
-                    }
-                    view.viewTreeObserver.removeOnPreDrawListener(this)
-                    runnable.run()
-                    return true
-                }
-            }
-        )
-    }
-
-    private fun addPredictiveBackListener(onDismissRequested: (ScreenshotEvent) -> Unit) {
-        val onBackInvokedCallback = OnBackInvokedCallback {
-            if (LogConfig.DEBUG_INPUT) {
-                Log.d(TAG, "Predictive Back callback dispatched")
-            }
-            onDismissRequested.invoke(SCREENSHOT_DISMISSED_OTHER)
-        }
-        view.addOnAttachStateChangeListener(
-            object : View.OnAttachStateChangeListener {
-                override fun onViewAttachedToWindow(v: View) {
-                    if (LogConfig.DEBUG_INPUT) {
-                        Log.d(TAG, "Registering Predictive Back callback")
-                    }
-                    view
-                        .findOnBackInvokedDispatcher()
-                        ?.registerOnBackInvokedCallback(
-                            OnBackInvokedDispatcher.PRIORITY_DEFAULT,
-                            onBackInvokedCallback
-                        )
-                }
-
-                override fun onViewDetachedFromWindow(view: View) {
-                    if (LogConfig.DEBUG_INPUT) {
-                        Log.d(TAG, "Unregistering Predictive Back callback")
-                    }
-                    view
-                        .findOnBackInvokedDispatcher()
-                        ?.unregisterOnBackInvokedCallback(onBackInvokedCallback)
-                }
-            }
-        )
-    }
-    private fun setOnKeyListener(onDismissRequested: (ScreenshotEvent) -> Unit) {
-        view.setOnKeyListener(
-            object : View.OnKeyListener {
-                override fun onKey(view: View, keyCode: Int, event: KeyEvent): Boolean {
-                    if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
-                        if (LogConfig.DEBUG_INPUT) {
-                            Log.d(TAG, "onKeyEvent: $keyCode")
-                        }
-                        onDismissRequested.invoke(SCREENSHOT_DISMISSED_OTHER)
-                        return true
-                    }
-                    return false
-                }
-            }
-        )
-    }
-
-    @AssistedFactory
-    interface Factory : ScreenshotViewProxy.Factory {
-        override fun getProxy(context: Context, displayId: Int): LegacyScreenshotViewProxy
-    }
-
-    companion object {
-        private const val TAG = "LegacyScreenshotViewProxy"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
index 5960462..474afa8b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
@@ -137,7 +137,7 @@
         val offset = container.height + params.topMargin + params.bottomMargin
         val anim = if (animateIn) ValueAnimator.ofFloat(0f, 1f) else ValueAnimator.ofFloat(1f, 0f)
         with(anim) {
-            duration = ScreenshotView.SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS
+            duration = MESSAGE_EXPANSION_DURATION_MS
             interpolator = AccelerateDecelerateInterpolator()
             addUpdateListener { valueAnimator: ValueAnimator ->
                 val interpolation = valueAnimator.animatedValue as Float
@@ -147,4 +147,8 @@
         }
         return anim
     }
+
+    companion object {
+        const val MESSAGE_EXPANSION_DURATION_MS: Long = 400
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 0cbf8f9..7739009 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -191,7 +191,7 @@
 
     private final WindowContext mContext;
     private final FeatureFlags mFlags;
-    private final ScreenshotViewProxy mViewProxy;
+    private final ScreenshotShelfViewProxy mViewProxy;
     private final ScreenshotNotificationsController mNotificationsController;
     private final ScreenshotSmartActions mScreenshotSmartActions;
     private final UiEventLogger mUiEventLogger;
@@ -246,7 +246,7 @@
             Context context,
             WindowManager windowManager,
             FeatureFlags flags,
-            ScreenshotViewProxy.Factory viewProxyFactory,
+            ScreenshotShelfViewProxy.Factory viewProxyFactory,
             ScreenshotSmartActions screenshotSmartActions,
             ScreenshotNotificationsController.Factory screenshotNotificationsControllerFactory,
             UiEventLogger uiEventLogger,
@@ -477,9 +477,6 @@
         }
 
         mViewProxy.setPackageName(mPackageName);
-
-        mViewProxy.updateOrientation(
-                mWindowManager.getCurrentWindowMetrics().getWindowInsets());
     }
 
     /**
@@ -528,7 +525,7 @@
         }
 
         mMessageContainerController.setView(mViewProxy.getView());
-        mViewProxy.setCallbacks(new ScreenshotView.ScreenshotViewCallback() {
+        mViewProxy.setCallbacks(new ScreenshotShelfViewProxy.ScreenshotViewCallback() {
             @Override
             public void onUserInteraction() {
                 if (DEBUG_INPUT) {
@@ -538,13 +535,6 @@
             }
 
             @Override
-            public void onAction(Intent intent, UserHandle owner, boolean overrideTransition) {
-                Pair<ActivityOptions, ExitTransitionCoordinator> exit = createWindowTransition();
-                mActionIntentExecutor.launchIntentAsync(
-                        intent, owner, overrideTransition, exit.first, exit.second);
-            }
-
-            @Override
             public void onDismiss() {
                 finishDismiss();
             }
@@ -871,62 +861,6 @@
         mSaveInBgTask.execute();
     }
 
-
-    /**
-     * Sets up the action shade and its entrance animation, once we get the screenshot URI.
-     */
-    private void showUiOnActionsReady(ScreenshotController.SavedImageData imageData) {
-        logSuccessOnActionsReady(imageData);
-        mScreenshotHandler.resetTimeout();
-
-        if (imageData.uri != null) {
-            if (DEBUG_UI) {
-                Log.d(TAG, "Showing UI actions");
-            }
-            if (!imageData.owner.equals(Process.myUserHandle())) {
-                Log.d(TAG, "Screenshot saved to user " + imageData.owner + " as "
-                        + imageData.uri);
-            }
-            mScreenshotHandler.post(() -> {
-                if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
-                    mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            super.onAnimationEnd(animation);
-                            mViewProxy.setChipIntents(imageData);
-                        }
-                    });
-                } else {
-                    mViewProxy.setChipIntents(imageData);
-                }
-            });
-        }
-    }
-
-    /**
-     * Sets up the action shade and its entrance animation, once we get the Quick Share action data.
-     */
-    private void showUiOnQuickShareActionReady(ScreenshotController.QuickShareData quickShareData) {
-        if (DEBUG_UI) {
-            Log.d(TAG, "Showing UI for Quick Share action");
-        }
-        if (quickShareData.quickShareAction != null) {
-            mScreenshotHandler.post(() -> {
-                if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
-                    mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            super.onAnimationEnd(animation);
-                            mViewProxy.addQuickShareChip(quickShareData.quickShareAction);
-                        }
-                    });
-                } else {
-                    mViewProxy.addQuickShareChip(quickShareData.quickShareAction);
-                }
-            });
-        }
-    }
-
     /**
      * Logs success/failure of the screenshot saving task, and shows an error if it failed.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
index 1b5fa34..50215af 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
@@ -18,7 +18,6 @@
 
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
-import android.app.Notification
 import android.content.Context
 import android.graphics.Bitmap
 import android.graphics.Rect
@@ -45,7 +44,6 @@
 import com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS
 import com.android.systemui.screenshot.LogConfig.DEBUG_INPUT
 import com.android.systemui.screenshot.LogConfig.DEBUG_WINDOW
-import com.android.systemui.screenshot.ScreenshotController.SavedImageData
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER
 import com.android.systemui.screenshot.scroll.ScrollCaptureController
 import com.android.systemui.screenshot.ui.ScreenshotAnimationController
@@ -70,13 +68,23 @@
     private val thumbnailObserver: ThumbnailObserver,
     @Assisted private val context: Context,
     @Assisted private val displayId: Int
-) : ScreenshotViewProxy {
-    override val view: ScreenshotShelfView =
+) {
+
+    interface ScreenshotViewCallback {
+        fun onUserInteraction()
+
+        fun onDismiss()
+
+        /** DOWN motion event was observed outside of the touchable areas of this view. */
+        fun onTouchOutside()
+    }
+
+    val view: ScreenshotShelfView =
         LayoutInflater.from(context).inflate(R.layout.screenshot_shelf, null) as ScreenshotShelfView
-    override val screenshotPreview: View
-    override var packageName: String = ""
-    override var callbacks: ScreenshotView.ScreenshotViewCallback? = null
-    override var screenshot: ScreenshotData? = null
+    val screenshotPreview: View
+    var packageName: String = ""
+    var callbacks: ScreenshotViewCallback? = null
+    var screenshot: ScreenshotData? = null
         set(value) {
             value?.let {
                 viewModel.setScreenshotBitmap(it.bitmap)
@@ -92,10 +100,11 @@
             field = value
         }
 
-    override val isAttachedToWindow
+    val isAttachedToWindow
         get() = view.isAttachedToWindow
-    override var isDismissing = false
-    override var isPendingSharedTransition = false
+
+    var isDismissing = false
+    var isPendingSharedTransition = false
 
     private val animationController = ScreenshotAnimationController(view, viewModel)
     private var inputMonitor: InputMonitorCompat? = null
@@ -136,17 +145,17 @@
         )
     }
 
-    override fun reset() {
+    fun reset() {
         animationController.cancel()
         isPendingSharedTransition = false
         viewModel.reset()
     }
-    override fun updateInsets(insets: WindowInsets) {
+
+    fun updateInsets(insets: WindowInsets) {
         view.updateInsets(insets)
     }
-    override fun updateOrientation(insets: WindowInsets) {}
 
-    override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
+    fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
         val entrance =
             animationController.getEntranceAnimation(screenRect, showFlash) {
                 viewModel.setAnimationState(AnimationState.ENTRANCE_REVEAL)
@@ -164,11 +173,7 @@
         return entrance
     }
 
-    override fun addQuickShareChip(quickShareAction: Notification.Action) {}
-
-    override fun setChipIntents(imageData: SavedImageData) {}
-
-    override fun requestDismissal(event: ScreenshotEvent?) {
+    fun requestDismissal(event: ScreenshotEvent?) {
         requestDismissal(event, null)
     }
 
@@ -187,6 +192,7 @@
                 override fun onAnimationStart(animator: Animator) {
                     isDismissing = true
                 }
+
                 override fun onAnimationEnd(animator: Animator) {
                     isDismissing = false
                     callbacks?.onDismiss()
@@ -196,11 +202,7 @@
         animator.start()
     }
 
-    override fun showScrollChip(packageName: String, onClick: Runnable) {}
-
-    override fun hideScrollChip() {}
-
-    override fun prepareScrollingTransition(
+    fun prepareScrollingTransition(
         response: ScrollCaptureResponse,
         screenBitmap: Bitmap, // unused
         newScreenshot: Bitmap,
@@ -228,7 +230,7 @@
         return r
     }
 
-    override fun startLongScreenshotTransition(
+    fun startLongScreenshotTransition(
         transitionDestination: Rect,
         onTransitionEnd: Runnable,
         longScreenshot: ScrollCaptureController.LongScreenshot,
@@ -243,27 +245,27 @@
         transitionAnimation.start()
     }
 
-    override fun restoreNonScrollingUi() {
+    fun restoreNonScrollingUi() {
         viewModel.setScrollableRect(null)
         viewModel.setScrollingScrimBitmap(null)
         animationController.restoreUI()
         callbacks?.onUserInteraction() // reset the timeout
     }
 
-    override fun stopInputListening() {
+    fun stopInputListening() {
         inputMonitor?.dispose()
         inputMonitor = null
         inputEventReceiver?.dispose()
         inputEventReceiver = null
     }
 
-    override fun requestFocus() {
+    fun requestFocus() {
         view.requestFocus()
     }
 
-    override fun announceForAccessibility(string: String) = view.announceForAccessibility(string)
+    fun announceForAccessibility(string: String) = view.announceForAccessibility(string)
 
-    override fun prepareEntranceAnimation(runnable: Runnable) {
+    fun prepareEntranceAnimation(runnable: Runnable) {
         view.viewTreeObserver.addOnPreDrawListener(
             object : ViewTreeObserver.OnPreDrawListener {
                 override fun onPreDraw(): Boolean {
@@ -276,7 +278,7 @@
         )
     }
 
-    override fun fadeForSharedTransition() {
+    fun fadeForSharedTransition() {
         animationController.fadeForSharedTransition()
     }
 
@@ -349,7 +351,7 @@
     }
 
     @AssistedFactory
-    interface Factory : ScreenshotViewProxy.Factory {
-        override fun getProxy(context: Context, displayId: Int): ScreenshotShelfViewProxy
+    interface Factory {
+        fun getProxy(context: Context, displayId: Int): ScreenshotShelfViewProxy
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
deleted file mode 100644
index 59e38a8..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ /dev/null
@@ -1,1126 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot;
-
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_TAKE_SCREENSHOT;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_SCROLL;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_UI;
-import static com.android.systemui.screenshot.LogConfig.DEBUG_WINDOW;
-import static com.android.systemui.screenshot.LogConfig.logTag;
-import static com.android.systemui.screenshot.ScreenshotController.SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS;
-
-import static java.util.Objects.requireNonNull;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.BroadcastOptions;
-import android.app.Notification;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BlendMode;
-import android.graphics.Color;
-import android.graphics.Insets;
-import android.graphics.Matrix;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.graphics.drawable.InsetDrawable;
-import android.graphics.drawable.LayerDrawable;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.Choreographer;
-import android.view.Display;
-import android.view.DisplayCutout;
-import android.view.GestureDetector;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.ScrollCaptureResponse;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
-import android.widget.HorizontalScrollView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import androidx.constraintlayout.widget.ConstraintLayout;
-
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.res.R;
-import com.android.systemui.screenshot.scroll.ScrollCaptureController;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.shared.system.InputMonitorCompat;
-import com.android.systemui.shared.system.QuickStepContract;
-
-import java.util.ArrayList;
-
-/**
- * Handles the visual elements and animations for the screenshot flow.
- */
-public class ScreenshotView extends FrameLayout implements
-        ViewTreeObserver.OnComputeInternalInsetsListener {
-
-    public interface ScreenshotViewCallback {
-        void onUserInteraction();
-
-        void onAction(Intent intent, UserHandle owner, boolean overrideTransition);
-
-        void onDismiss();
-
-        /** DOWN motion event was observed outside of the touchable areas of this view. */
-        void onTouchOutside();
-    }
-
-    private static final String TAG = logTag(ScreenshotView.class);
-
-    private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133;
-    private static final long SCREENSHOT_FLASH_OUT_DURATION_MS = 217;
-    // delay before starting to fade in dismiss button
-    private static final long SCREENSHOT_TO_CORNER_DISMISS_DELAY_MS = 200;
-    private static final long SCREENSHOT_TO_CORNER_X_DURATION_MS = 234;
-    private static final long SCREENSHOT_TO_CORNER_Y_DURATION_MS = 500;
-    private static final long SCREENSHOT_TO_CORNER_SCALE_DURATION_MS = 234;
-    public static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 400;
-    private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 100;
-    private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
-
-    private final Resources mResources;
-    private final Interpolator mFastOutSlowIn;
-    private final DisplayMetrics mDisplayMetrics;
-    private final float mFixedSize;
-    private final AccessibilityManager mAccessibilityManager;
-    private final GestureDetector mSwipeDetector;
-
-    private int mDefaultDisplay = Display.DEFAULT_DISPLAY;
-    private int mNavMode;
-    private boolean mOrientationPortrait;
-    private boolean mDirectionLTR;
-
-    private ImageView mScrollingScrim;
-    private DraggableConstraintLayout mScreenshotStatic;
-    private ImageView mScreenshotPreview;
-    private ImageView mScreenshotBadge;
-    private View mScreenshotPreviewBorder;
-    private ImageView mScrollablePreview;
-    private ImageView mScreenshotFlash;
-    private ImageView mActionsContainerBackground;
-    private HorizontalScrollView mActionsContainer;
-    private LinearLayout mActionsView;
-    private FrameLayout mDismissButton;
-    private OverlayActionChip mShareChip;
-    private OverlayActionChip mEditChip;
-    private OverlayActionChip mScrollChip;
-    private OverlayActionChip mQuickShareChip;
-
-    private UiEventLogger mUiEventLogger;
-    private ScreenshotViewCallback mCallbacks;
-    private boolean mPendingSharedTransition;
-    private InputMonitorCompat mInputMonitor;
-    private InputChannelCompat.InputEventReceiver mInputEventReceiver;
-    private boolean mShowScrollablePreview;
-    private String mPackageName = "";
-
-    private final ArrayList<OverlayActionChip> mSmartChips = new ArrayList<>();
-    private PendingInteraction mPendingInteraction;
-    // Should only be set/used if the SCREENSHOT_METADATA flag is set.
-    private ScreenshotData mScreenshotData;
-
-    private final InteractionJankMonitor mInteractionJankMonitor;
-    private FeatureFlags mFlags;
-    private final Bundle mInteractiveBroadcastOption;
-
-    private enum PendingInteraction {
-        PREVIEW,
-        EDIT,
-        SHARE,
-        QUICK_SHARE
-    }
-
-    public ScreenshotView(Context context) {
-        this(context, null);
-    }
-
-    public ScreenshotView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public ScreenshotView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public ScreenshotView(
-            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mResources = mContext.getResources();
-        mInteractionJankMonitor = getInteractionJankMonitorInstance();
-
-        BroadcastOptions options = BroadcastOptions.makeBasic();
-        options.setInteractive(true);
-        mInteractiveBroadcastOption = options.toBundle();
-
-        mFixedSize = mResources.getDimensionPixelSize(R.dimen.overlay_x_scale);
-
-        // standard material ease
-        mFastOutSlowIn =
-                AnimationUtils.loadInterpolator(mContext, android.R.interpolator.fast_out_slow_in);
-
-        mDisplayMetrics = new DisplayMetrics();
-        mContext.getDisplay().getRealMetrics(mDisplayMetrics);
-
-        mAccessibilityManager = AccessibilityManager.getInstance(mContext);
-
-        mSwipeDetector = new GestureDetector(mContext,
-                new GestureDetector.SimpleOnGestureListener() {
-                    final Rect mActionsRect = new Rect();
-
-                    @Override
-                    public boolean onScroll(
-                            MotionEvent ev1, MotionEvent ev2, float distanceX, float distanceY) {
-                        mActionsContainer.getBoundsOnScreen(mActionsRect);
-                        // return true if we aren't in the actions bar, or if we are but it isn't
-                        // scrollable in the direction of movement
-                        return !mActionsRect.contains((int) ev2.getRawX(), (int) ev2.getRawY())
-                                || !mActionsContainer.canScrollHorizontally((int) distanceX);
-                    }
-                });
-        mSwipeDetector.setIsLongpressEnabled(false);
-        addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
-            @Override
-            public void onViewAttachedToWindow(View v) {
-                startInputListening();
-            }
-
-            @Override
-            public void onViewDetachedFromWindow(View v) {
-                stopInputListening();
-            }
-        });
-    }
-
-    private InteractionJankMonitor getInteractionJankMonitorInstance() {
-        return InteractionJankMonitor.getInstance();
-    }
-
-    public void hideScrollChip() {
-        mScrollChip.setVisibility(View.GONE);
-    }
-
-    /**
-     * Called to display the scroll action chip when support is detected.
-     *
-     * @param packageName the owning package of the window to be captured
-     * @param onClick     the action to take when the chip is clicked.
-     */
-    public void showScrollChip(String packageName, Runnable onClick) {
-        if (DEBUG_SCROLL) {
-            Log.d(TAG, "Showing Scroll option");
-        }
-        mScrollChip.setVisibility(VISIBLE);
-        mScrollChip.setOnClickListener((v) -> onClick.run());
-    }
-
-    @Override // ViewTreeObserver.OnComputeInternalInsetsListener
-    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
-        inoutInfo.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-        inoutInfo.touchableRegion.set(getTouchRegion(true));
-    }
-
-    private Region getSwipeRegion() {
-        Region swipeRegion = new Region();
-
-        final Rect tmpRect = new Rect();
-        int swipePadding = (int) FloatingWindowUtil.dpToPx(
-                mDisplayMetrics, DraggableConstraintLayout.SWIPE_PADDING_DP * -1);
-        mScreenshotPreview.getBoundsOnScreen(tmpRect);
-        tmpRect.inset(swipePadding, swipePadding);
-        swipeRegion.op(tmpRect, Region.Op.UNION);
-        mActionsContainerBackground.getBoundsOnScreen(tmpRect);
-        tmpRect.inset(swipePadding, swipePadding);
-        swipeRegion.op(tmpRect, Region.Op.UNION);
-        mDismissButton.getBoundsOnScreen(tmpRect);
-        swipeRegion.op(tmpRect, Region.Op.UNION);
-
-        View messageContainer = findViewById(R.id.screenshot_message_container);
-        if (messageContainer != null) {
-            messageContainer.getBoundsOnScreen(tmpRect);
-            swipeRegion.op(tmpRect, Region.Op.UNION);
-        }
-        View messageDismiss = findViewById(R.id.message_dismiss_button);
-        if (messageDismiss != null) {
-            messageDismiss.getBoundsOnScreen(tmpRect);
-            swipeRegion.op(tmpRect, Region.Op.UNION);
-        }
-
-        return swipeRegion;
-    }
-
-    private Region getTouchRegion(boolean includeScrim) {
-        Region touchRegion = getSwipeRegion();
-
-        if (includeScrim && mScrollingScrim.getVisibility() == View.VISIBLE) {
-            final Rect tmpRect = new Rect();
-            mScrollingScrim.getBoundsOnScreen(tmpRect);
-            touchRegion.op(tmpRect, Region.Op.UNION);
-        }
-
-        if (QuickStepContract.isGesturalMode(mNavMode)) {
-            final WindowManager wm = mContext.getSystemService(WindowManager.class);
-            final WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
-            final Insets gestureInsets = windowMetrics.getWindowInsets().getInsets(
-                    WindowInsets.Type.systemGestures());
-            // Receive touches in gesture insets such that they don't cause TOUCH_OUTSIDE
-            Rect inset = new Rect(0, 0, gestureInsets.left, mDisplayMetrics.heightPixels);
-            touchRegion.op(inset, Region.Op.UNION);
-            inset.set(mDisplayMetrics.widthPixels - gestureInsets.right, 0,
-                    mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels);
-            touchRegion.op(inset, Region.Op.UNION);
-        }
-        return touchRegion;
-    }
-
-    private void startInputListening() {
-        stopInputListening();
-        mInputMonitor = new InputMonitorCompat("Screenshot", mDefaultDisplay);
-        mInputEventReceiver = mInputMonitor.getInputReceiver(
-                Looper.getMainLooper(), Choreographer.getInstance(), ev -> {
-                    if (ev instanceof MotionEvent) {
-                        MotionEvent event = (MotionEvent) ev;
-                        if (event.getActionMasked() == MotionEvent.ACTION_DOWN
-                                && !getTouchRegion(false).contains(
-                                (int) event.getRawX(), (int) event.getRawY())) {
-                            mCallbacks.onTouchOutside();
-                        }
-                    }
-                });
-    }
-
-    void stopInputListening() {
-        if (mInputMonitor != null) {
-            mInputMonitor.dispose();
-            mInputMonitor = null;
-        }
-        if (mInputEventReceiver != null) {
-            mInputEventReceiver.dispose();
-            mInputEventReceiver = null;
-        }
-    }
-
-    @Override // View
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mScrollingScrim = requireNonNull(findViewById(R.id.screenshot_scrolling_scrim));
-        mScreenshotStatic = requireNonNull(findViewById(R.id.screenshot_static));
-        mScreenshotPreview = requireNonNull(findViewById(R.id.screenshot_preview));
-
-        mScreenshotPreviewBorder = requireNonNull(
-                findViewById(R.id.screenshot_preview_border));
-        mScreenshotPreview.setClipToOutline(true);
-        mScreenshotBadge = requireNonNull(findViewById(R.id.screenshot_badge));
-
-        mActionsContainerBackground = requireNonNull(findViewById(
-                R.id.actions_container_background));
-        mActionsContainer = requireNonNull(findViewById(R.id.actions_container));
-        mActionsView = requireNonNull(findViewById(R.id.screenshot_actions));
-        mDismissButton = requireNonNull(findViewById(R.id.screenshot_dismiss_button));
-        mScrollablePreview = requireNonNull(findViewById(R.id.screenshot_scrollable_preview));
-        mScreenshotFlash = requireNonNull(findViewById(R.id.screenshot_flash));
-        mShareChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_share_chip));
-        mEditChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_edit_chip));
-        mScrollChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_scroll_chip));
-
-        setFocusable(true);
-        mActionsContainer.setScrollX(0);
-
-        mNavMode = getResources().getInteger(
-                com.android.internal.R.integer.config_navBarInteractionMode);
-        mOrientationPortrait =
-                getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT;
-        mDirectionLTR =
-                getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
-
-        // Get focus so that the key events go to the layout.
-        setFocusableInTouchMode(true);
-        requestFocus();
-
-        mScreenshotStatic.setCallbacks(new DraggableConstraintLayout.SwipeDismissCallbacks() {
-            @Override
-            public void onInteraction() {
-                mCallbacks.onUserInteraction();
-            }
-
-            @Override
-            public void onSwipeDismissInitiated(Animator animator) {
-                if (DEBUG_DISMISS) {
-                    Log.d(ScreenshotView.TAG, "dismiss triggered via swipe gesture");
-                }
-                mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SWIPE_DISMISSED, 0,
-                        mPackageName);
-            }
-
-            @Override
-            public void onDismissComplete() {
-                if (mInteractionJankMonitor.isInstrumenting(CUJ_TAKE_SCREENSHOT)) {
-                    mInteractionJankMonitor.end(CUJ_TAKE_SCREENSHOT);
-                }
-                mCallbacks.onDismiss();
-            }
-        });
-    }
-
-    View getScreenshotPreview() {
-        return mScreenshotPreview;
-    }
-
-    void setUiEventLogger(UiEventLogger uiEventLogger) {
-        mUiEventLogger = uiEventLogger;
-    }
-
-    void setCallbacks(ScreenshotViewCallback callbacks) {
-        mCallbacks = callbacks;
-    }
-
-    void setFlags(FeatureFlags flags) {
-        mFlags = flags;
-    }
-
-    void setScreenshot(Bitmap bitmap, Insets screenInsets) {
-        mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
-    }
-
-    void setScreenshot(ScreenshotData screenshot) {
-        mScreenshotData = screenshot;
-        setScreenshot(screenshot.getBitmap(), screenshot.getInsets());
-        mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, screenshot.getBitmap(),
-                screenshot.getInsets()));
-    }
-
-    void setPackageName(String packageName) {
-        mPackageName = packageName;
-    }
-
-    void setDefaultDisplay(int displayId) {
-        mDefaultDisplay = displayId;
-    }
-
-    void updateInsets(WindowInsets insets) {
-        int orientation = mContext.getResources().getConfiguration().orientation;
-        mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT);
-        FrameLayout.LayoutParams p =
-                (FrameLayout.LayoutParams) mScreenshotStatic.getLayoutParams();
-        DisplayCutout cutout = insets.getDisplayCutout();
-        Insets navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars());
-        if (cutout == null) {
-            p.setMargins(0, 0, 0, navBarInsets.bottom);
-        } else {
-            Insets waterfall = cutout.getWaterfallInsets();
-            if (mOrientationPortrait) {
-                p.setMargins(
-                        waterfall.left,
-                        Math.max(cutout.getSafeInsetTop(), waterfall.top),
-                        waterfall.right,
-                        Math.max(cutout.getSafeInsetBottom(),
-                                Math.max(navBarInsets.bottom, waterfall.bottom)));
-            } else {
-                p.setMargins(
-                        Math.max(cutout.getSafeInsetLeft(), waterfall.left),
-                        waterfall.top,
-                        Math.max(cutout.getSafeInsetRight(), waterfall.right),
-                        Math.max(navBarInsets.bottom, waterfall.bottom));
-            }
-        }
-        mScreenshotStatic.setLayoutParams(p);
-        mScreenshotStatic.requestLayout();
-    }
-
-    void updateOrientation(WindowInsets insets) {
-        int orientation = mContext.getResources().getConfiguration().orientation;
-        mOrientationPortrait = (orientation == ORIENTATION_PORTRAIT);
-        updateInsets(insets);
-        ViewGroup.LayoutParams params = mScreenshotPreview.getLayoutParams();
-        if (mOrientationPortrait) {
-            params.width = (int) mFixedSize;
-            params.height = LayoutParams.WRAP_CONTENT;
-            mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_START);
-        } else {
-            params.width = LayoutParams.WRAP_CONTENT;
-            params.height = (int) mFixedSize;
-            mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_END);
-        }
-
-        mScreenshotPreview.setLayoutParams(params);
-    }
-
-    AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) {
-        if (DEBUG_ANIM) {
-            Log.d(TAG, "createAnim: bounds=" + bounds + " showFlash=" + showFlash);
-        }
-
-        Rect targetPosition = new Rect();
-        mScreenshotPreview.getHitRect(targetPosition);
-
-        // ratio of preview width, end vs. start size
-        float cornerScale =
-                mFixedSize / (mOrientationPortrait ? bounds.width() : bounds.height());
-        final float currentScale = 1 / cornerScale;
-
-        AnimatorSet dropInAnimation = new AnimatorSet();
-        ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1);
-        flashInAnimator.setDuration(SCREENSHOT_FLASH_IN_DURATION_MS);
-        flashInAnimator.setInterpolator(mFastOutSlowIn);
-        flashInAnimator.addUpdateListener(animation ->
-                mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
-
-        ValueAnimator flashOutAnimator = ValueAnimator.ofFloat(1, 0);
-        flashOutAnimator.setDuration(SCREENSHOT_FLASH_OUT_DURATION_MS);
-        flashOutAnimator.setInterpolator(mFastOutSlowIn);
-        flashOutAnimator.addUpdateListener(animation ->
-                mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
-
-        // animate from the current location, to the static preview location
-        final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
-        final PointF finalPos = new PointF(targetPosition.exactCenterX(),
-                targetPosition.exactCenterY());
-
-        // Shift to screen coordinates so that the animation runs on top of the entire screen,
-        // including e.g. bars covering the display cutout.
-        int[] locInScreen = mScreenshotPreview.getLocationOnScreen();
-        startPos.offset(targetPosition.left - locInScreen[0], targetPosition.top - locInScreen[1]);
-
-        if (DEBUG_ANIM) {
-            Log.d(TAG, "toCorner: startPos=" + startPos);
-            Log.d(TAG, "toCorner: finalPos=" + finalPos);
-        }
-
-        ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
-        toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
-
-        toCorner.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mScreenshotPreview.setScaleX(currentScale);
-                mScreenshotPreview.setScaleY(currentScale);
-                mScreenshotPreview.setVisibility(View.VISIBLE);
-                if (mAccessibilityManager.isEnabled()) {
-                    mDismissButton.setAlpha(0);
-                    mDismissButton.setVisibility(View.VISIBLE);
-                }
-            }
-        });
-
-        float xPositionPct =
-                SCREENSHOT_TO_CORNER_X_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
-        float dismissPct =
-                SCREENSHOT_TO_CORNER_DISMISS_DELAY_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
-        float scalePct =
-                SCREENSHOT_TO_CORNER_SCALE_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
-        toCorner.addUpdateListener(animation -> {
-            float t = animation.getAnimatedFraction();
-            if (t < scalePct) {
-                float scale = MathUtils.lerp(
-                        currentScale, 1, mFastOutSlowIn.getInterpolation(t / scalePct));
-                mScreenshotPreview.setScaleX(scale);
-                mScreenshotPreview.setScaleY(scale);
-            } else {
-                mScreenshotPreview.setScaleX(1);
-                mScreenshotPreview.setScaleY(1);
-            }
-
-            if (t < xPositionPct) {
-                float xCenter = MathUtils.lerp(startPos.x, finalPos.x,
-                        mFastOutSlowIn.getInterpolation(t / xPositionPct));
-                mScreenshotPreview.setX(xCenter - mScreenshotPreview.getWidth() / 2f);
-            } else {
-                mScreenshotPreview.setX(finalPos.x - mScreenshotPreview.getWidth() / 2f);
-            }
-            float yCenter = MathUtils.lerp(
-                    startPos.y, finalPos.y, mFastOutSlowIn.getInterpolation(t));
-            mScreenshotPreview.setY(yCenter - mScreenshotPreview.getHeight() / 2f);
-
-            if (t >= dismissPct) {
-                mDismissButton.setAlpha((t - dismissPct) / (1 - dismissPct));
-                float currentX = mScreenshotPreview.getX();
-                float currentY = mScreenshotPreview.getY();
-                mDismissButton.setY(currentY - mDismissButton.getHeight() / 2f);
-                if (mDirectionLTR) {
-                    mDismissButton.setX(currentX + mScreenshotPreview.getWidth()
-                            - mDismissButton.getWidth() / 2f);
-                } else {
-                    mDismissButton.setX(currentX - mDismissButton.getWidth() / 2f);
-                }
-            }
-        });
-
-        mScreenshotFlash.setAlpha(0f);
-        mScreenshotFlash.setVisibility(View.VISIBLE);
-
-        ValueAnimator borderFadeIn = ValueAnimator.ofFloat(0, 1);
-        borderFadeIn.setDuration(100);
-        borderFadeIn.addUpdateListener((animation) -> {
-            float borderAlpha = animation.getAnimatedFraction();
-            mScreenshotPreviewBorder.setAlpha(borderAlpha);
-            mScreenshotBadge.setAlpha(borderAlpha);
-        });
-
-        if (showFlash) {
-            dropInAnimation.play(flashOutAnimator).after(flashInAnimator);
-            dropInAnimation.play(flashOutAnimator).with(toCorner);
-        } else {
-            dropInAnimation.play(toCorner);
-        }
-        dropInAnimation.play(borderFadeIn).after(toCorner);
-
-        dropInAnimation.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mInteractionJankMonitor.cancel(CUJ_TAKE_SCREENSHOT);
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                InteractionJankMonitor.Configuration.Builder builder =
-                        InteractionJankMonitor.Configuration.Builder.withView(
-                                        CUJ_TAKE_SCREENSHOT, mScreenshotPreview)
-                                .setTag("DropIn");
-                mInteractionJankMonitor.begin(builder);
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (DEBUG_ANIM) {
-                    Log.d(TAG, "drop-in animation ended");
-                }
-                mDismissButton.setOnClickListener(view -> {
-                    if (DEBUG_INPUT) {
-                        Log.d(TAG, "dismiss button clicked");
-                    }
-                    mUiEventLogger.log(
-                            ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL, 0, mPackageName);
-                    animateDismissal();
-                });
-                mDismissButton.setAlpha(1);
-                float dismissOffset = mDismissButton.getWidth() / 2f;
-                float finalDismissX = mDirectionLTR
-                        ? finalPos.x - dismissOffset + bounds.width() * cornerScale / 2f
-                        : finalPos.x - dismissOffset - bounds.width() * cornerScale / 2f;
-                mDismissButton.setX(finalDismissX);
-                mDismissButton.setY(
-                        finalPos.y - dismissOffset - bounds.height() * cornerScale / 2f);
-                mScreenshotPreview.setScaleX(1);
-                mScreenshotPreview.setScaleY(1);
-                mScreenshotPreview.setX(finalPos.x - mScreenshotPreview.getWidth() / 2f);
-                mScreenshotPreview.setY(finalPos.y - mScreenshotPreview.getHeight() / 2f);
-                requestLayout();
-                mInteractionJankMonitor.end(CUJ_TAKE_SCREENSHOT);
-                createScreenshotActionsShadeAnimation().start();
-            }
-        });
-
-        return dropInAnimation;
-    }
-
-    ValueAnimator createScreenshotActionsShadeAnimation() {
-        // By default the activities won't be able to start immediately; override this to keep
-        // the same behavior as if started from a notification
-        try {
-            ActivityManager.getService().resumeAppSwitches();
-        } catch (RemoteException e) {
-        }
-
-        ArrayList<OverlayActionChip> chips = new ArrayList<>();
-
-        mShareChip.setContentDescription(mContext.getString(R.string.screenshot_share_description));
-        mShareChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_share), true);
-        mShareChip.setOnClickListener(v -> {
-            mShareChip.setIsPending(true);
-            mEditChip.setIsPending(false);
-            if (mQuickShareChip != null) {
-                mQuickShareChip.setIsPending(false);
-            }
-            mPendingInteraction = PendingInteraction.SHARE;
-        });
-        chips.add(mShareChip);
-
-        mEditChip.setContentDescription(
-                mContext.getString(R.string.screenshot_edit_description));
-        mEditChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_edit),
-                true);
-        mEditChip.setOnClickListener(v -> {
-            mEditChip.setIsPending(true);
-            mShareChip.setIsPending(false);
-            if (mQuickShareChip != null) {
-                mQuickShareChip.setIsPending(false);
-            }
-            mPendingInteraction = PendingInteraction.EDIT;
-        });
-        chips.add(mEditChip);
-
-        mScreenshotPreview.setOnClickListener(v -> {
-            mShareChip.setIsPending(false);
-            mEditChip.setIsPending(false);
-            if (mQuickShareChip != null) {
-                mQuickShareChip.setIsPending(false);
-            }
-            mPendingInteraction = PendingInteraction.PREVIEW;
-        });
-
-        mScrollChip.setText(mContext.getString(R.string.screenshot_scroll_label));
-        mScrollChip.setIcon(Icon.createWithResource(mContext,
-                R.drawable.ic_screenshot_scroll), true);
-        chips.add(mScrollChip);
-
-        // remove the margin from the last chip so that it's correctly aligned with the end
-        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
-                mActionsView.getChildAt(0).getLayoutParams();
-        params.setMarginEnd(0);
-        mActionsView.getChildAt(0).setLayoutParams(params);
-
-        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
-        animator.setDuration(SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS);
-        float alphaFraction = (float) SCREENSHOT_ACTIONS_ALPHA_DURATION_MS
-                / SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS;
-        mActionsContainer.setAlpha(0f);
-        mActionsContainerBackground.setAlpha(0f);
-        mActionsContainer.setVisibility(View.VISIBLE);
-        mActionsContainerBackground.setVisibility(View.VISIBLE);
-
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mInteractionJankMonitor.cancel(CUJ_TAKE_SCREENSHOT);
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mInteractionJankMonitor.end(CUJ_TAKE_SCREENSHOT);
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                InteractionJankMonitor.Configuration.Builder builder =
-                        InteractionJankMonitor.Configuration.Builder.withView(
-                                        CUJ_TAKE_SCREENSHOT, mScreenshotStatic)
-                                .setTag("Actions")
-                                .setTimeout(SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS);
-                mInteractionJankMonitor.begin(builder);
-            }
-        });
-
-        animator.addUpdateListener(animation -> {
-            float t = animation.getAnimatedFraction();
-            float containerAlpha = t < alphaFraction ? t / alphaFraction : 1;
-            mActionsContainer.setAlpha(containerAlpha);
-            mActionsContainerBackground.setAlpha(containerAlpha);
-            float containerScale = SCREENSHOT_ACTIONS_START_SCALE_X
-                    + (t * (1 - SCREENSHOT_ACTIONS_START_SCALE_X));
-            mActionsContainer.setScaleX(containerScale);
-            mActionsContainerBackground.setScaleX(containerScale);
-            for (OverlayActionChip chip : chips) {
-                chip.setAlpha(t);
-                chip.setScaleX(1 / containerScale); // invert to keep size of children constant
-            }
-            mActionsContainer.setScrollX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
-            mActionsContainer.setPivotX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
-            mActionsContainerBackground.setPivotX(
-                    mDirectionLTR ? 0 : mActionsContainerBackground.getWidth());
-        });
-        return animator;
-    }
-
-    void badgeScreenshot(@Nullable Drawable badge) {
-        mScreenshotBadge.setImageDrawable(badge);
-        mScreenshotBadge.setVisibility(badge != null ? View.VISIBLE : View.GONE);
-    }
-
-    void setChipIntents(ScreenshotController.SavedImageData imageData) {
-        mShareChip.setOnClickListener(v -> {
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED, 0, mPackageName);
-            prepareSharedTransition();
-
-            Intent shareIntent = ActionIntentCreator.INSTANCE.createShareWithSubject(
-                    imageData.uri, imageData.subject);
-            mCallbacks.onAction(shareIntent, imageData.owner, false);
-
-        });
-        mEditChip.setOnClickListener(v -> {
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED, 0, mPackageName);
-            prepareSharedTransition();
-            mCallbacks.onAction(
-                    ActionIntentCreator.INSTANCE.createEdit(imageData.uri, mContext),
-                    imageData.owner, true);
-        });
-        mScreenshotPreview.setOnClickListener(v -> {
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED, 0, mPackageName);
-            prepareSharedTransition();
-            mCallbacks.onAction(
-                    ActionIntentCreator.INSTANCE.createEdit(imageData.uri, mContext),
-                    imageData.owner, true);
-        });
-        if (mQuickShareChip != null) {
-            if (imageData.quickShareAction != null) {
-                mQuickShareChip.setPendingIntent(imageData.quickShareAction.actionIntent,
-                        () -> {
-                            mUiEventLogger.log(
-                                    ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED, 0,
-                                    mPackageName);
-                            animateDismissal();
-                        });
-            } else {
-                // hide chip and unset pending interaction if necessary, since we don't actually
-                // have a useable quick share intent
-                Log.wtf(TAG, "Showed quick share chip, but quick share intent was null");
-                if (mPendingInteraction == PendingInteraction.QUICK_SHARE) {
-                    mPendingInteraction = null;
-                }
-                mQuickShareChip.setVisibility(GONE);
-            }
-        }
-
-        if (mPendingInteraction != null) {
-            switch (mPendingInteraction) {
-                case PREVIEW:
-                    mScreenshotPreview.callOnClick();
-                    break;
-                case SHARE:
-                    mShareChip.callOnClick();
-                    break;
-                case EDIT:
-                    mEditChip.callOnClick();
-                    break;
-                case QUICK_SHARE:
-                    mQuickShareChip.callOnClick();
-                    break;
-            }
-        } else {
-            LayoutInflater inflater = LayoutInflater.from(mContext);
-
-            for (Notification.Action smartAction : imageData.smartActions) {
-                OverlayActionChip actionChip = (OverlayActionChip) inflater.inflate(
-                        R.layout.overlay_action_chip, mActionsView, false);
-                actionChip.setText(smartAction.title);
-                actionChip.setIcon(smartAction.getIcon(), false);
-                actionChip.setPendingIntent(smartAction.actionIntent,
-                        () -> {
-                            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED,
-                                    0, mPackageName);
-                            animateDismissal();
-                        });
-                actionChip.setAlpha(1);
-                mActionsView.addView(actionChip, mActionsView.getChildCount() - 1);
-                mSmartChips.add(actionChip);
-            }
-        }
-    }
-
-    void addQuickShareChip(Notification.Action quickShareAction) {
-        if (mQuickShareChip != null) {
-            mSmartChips.remove(mQuickShareChip);
-            mActionsView.removeView(mQuickShareChip);
-        }
-        if (mPendingInteraction == PendingInteraction.QUICK_SHARE) {
-            mPendingInteraction = null;
-        }
-        if (mPendingInteraction == null) {
-            LayoutInflater inflater = LayoutInflater.from(mContext);
-            mQuickShareChip = (OverlayActionChip) inflater.inflate(
-                    R.layout.overlay_action_chip, mActionsView, false);
-            mQuickShareChip.setText(quickShareAction.title);
-            mQuickShareChip.setIcon(quickShareAction.getIcon(), false);
-            mQuickShareChip.setOnClickListener(v -> {
-                mShareChip.setIsPending(false);
-                mEditChip.setIsPending(false);
-                mQuickShareChip.setIsPending(true);
-                mPendingInteraction = PendingInteraction.QUICK_SHARE;
-            });
-            mQuickShareChip.setAlpha(1);
-            mActionsView.addView(mQuickShareChip);
-            mSmartChips.add(mQuickShareChip);
-        }
-    }
-
-    private Rect scrollableAreaOnScreen(ScrollCaptureResponse response) {
-        Rect r = new Rect(response.getBoundsInWindow());
-        Rect windowInScreen = response.getWindowBounds();
-        r.offset(windowInScreen.left, windowInScreen.top);
-        r.intersect(new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
-        return r;
-    }
-
-    void startLongScreenshotTransition(Rect destination, Runnable onTransitionEnd,
-            ScrollCaptureController.LongScreenshot longScreenshot) {
-        mPendingSharedTransition = true;
-        AnimatorSet animSet = new AnimatorSet();
-
-        ValueAnimator scrimAnim = ValueAnimator.ofFloat(0, 1);
-        scrimAnim.addUpdateListener(animation ->
-                mScrollingScrim.setAlpha(1 - animation.getAnimatedFraction()));
-
-        if (mShowScrollablePreview) {
-            mScrollablePreview.setImageBitmap(longScreenshot.toBitmap());
-            float startX = mScrollablePreview.getX();
-            float startY = mScrollablePreview.getY();
-            int[] locInScreen = mScrollablePreview.getLocationOnScreen();
-            destination.offset((int) startX - locInScreen[0], (int) startY - locInScreen[1]);
-            mScrollablePreview.setPivotX(0);
-            mScrollablePreview.setPivotY(0);
-            mScrollablePreview.setAlpha(1f);
-            float currentScale = mScrollablePreview.getWidth() / (float) longScreenshot.getWidth();
-            Matrix matrix = new Matrix();
-            matrix.setScale(currentScale, currentScale);
-            matrix.postTranslate(
-                    longScreenshot.getLeft() * currentScale,
-                    longScreenshot.getTop() * currentScale);
-            mScrollablePreview.setImageMatrix(matrix);
-            float destinationScale = destination.width() / (float) mScrollablePreview.getWidth();
-
-            ValueAnimator previewAnim = ValueAnimator.ofFloat(0, 1);
-            previewAnim.addUpdateListener(animation -> {
-                float t = animation.getAnimatedFraction();
-                float currScale = MathUtils.lerp(1, destinationScale, t);
-                mScrollablePreview.setScaleX(currScale);
-                mScrollablePreview.setScaleY(currScale);
-                mScrollablePreview.setX(MathUtils.lerp(startX, destination.left, t));
-                mScrollablePreview.setY(MathUtils.lerp(startY, destination.top, t));
-            });
-            ValueAnimator previewFadeAnim = ValueAnimator.ofFloat(1, 0);
-            previewFadeAnim.addUpdateListener(animation ->
-                    mScrollablePreview.setAlpha(1 - animation.getAnimatedFraction()));
-            animSet.play(previewAnim).with(scrimAnim).before(previewFadeAnim);
-            previewAnim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    super.onAnimationEnd(animation);
-                    onTransitionEnd.run();
-                }
-            });
-        } else {
-            // if we switched orientations between the original screenshot and the long screenshot
-            // capture, just fade out the scrim instead of running the preview animation
-            animSet.play(scrimAnim);
-            animSet.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    super.onAnimationEnd(animation);
-                    onTransitionEnd.run();
-                }
-            });
-        }
-        animSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                mCallbacks.onDismiss();
-            }
-        });
-        animSet.start();
-    }
-
-    void prepareScrollingTransition(ScrollCaptureResponse response, Bitmap screenBitmap,
-            Bitmap newBitmap, boolean screenshotTakenInPortrait) {
-        mShowScrollablePreview = (screenshotTakenInPortrait == mOrientationPortrait);
-
-        mScrollingScrim.setImageBitmap(newBitmap);
-        mScrollingScrim.setVisibility(View.VISIBLE);
-
-        if (mShowScrollablePreview) {
-            Rect scrollableArea = scrollableAreaOnScreen(response);
-
-            float scale = mFixedSize
-                    / (mOrientationPortrait ? screenBitmap.getWidth() : screenBitmap.getHeight());
-            ConstraintLayout.LayoutParams params =
-                    (ConstraintLayout.LayoutParams) mScrollablePreview.getLayoutParams();
-
-            params.width = (int) (scale * scrollableArea.width());
-            params.height = (int) (scale * scrollableArea.height());
-            Matrix matrix = new Matrix();
-            matrix.setScale(scale, scale);
-            matrix.postTranslate(-scrollableArea.left * scale, -scrollableArea.top * scale);
-
-            mScrollablePreview.setTranslationX(scale
-                    * (mDirectionLTR ? scrollableArea.left : scrollableArea.right - getWidth()));
-            mScrollablePreview.setTranslationY(scale * scrollableArea.top);
-            mScrollablePreview.setImageMatrix(matrix);
-            mScrollablePreview.setImageBitmap(screenBitmap);
-            mScrollablePreview.setVisibility(View.VISIBLE);
-        }
-        mDismissButton.setVisibility(View.GONE);
-        mActionsContainer.setVisibility(View.GONE);
-        // set these invisible, but not gone, so that the views are laid out correctly
-        mActionsContainerBackground.setVisibility(View.INVISIBLE);
-        mScreenshotPreviewBorder.setVisibility(View.INVISIBLE);
-        mScreenshotPreview.setVisibility(View.INVISIBLE);
-        mScrollingScrim.setImageTintBlendMode(BlendMode.SRC_ATOP);
-        ValueAnimator anim = ValueAnimator.ofFloat(0, .3f);
-        anim.addUpdateListener(animation -> mScrollingScrim.setImageTintList(
-                ColorStateList.valueOf(Color.argb((float) animation.getAnimatedValue(), 0, 0, 0))));
-        anim.setDuration(200);
-        anim.start();
-    }
-
-    void restoreNonScrollingUi() {
-        mScrollChip.setVisibility(View.GONE);
-        mScrollablePreview.setVisibility(View.GONE);
-        mScrollingScrim.setVisibility(View.GONE);
-
-        if (mAccessibilityManager.isEnabled()) {
-            mDismissButton.setVisibility(View.VISIBLE);
-        }
-        mActionsContainer.setVisibility(View.VISIBLE);
-        mActionsContainerBackground.setVisibility(View.VISIBLE);
-        mScreenshotPreviewBorder.setVisibility(View.VISIBLE);
-        mScreenshotPreview.setVisibility(View.VISIBLE);
-        // reset the timeout
-        mCallbacks.onUserInteraction();
-    }
-
-    boolean isDismissing() {
-        return mScreenshotStatic.isDismissing();
-    }
-
-    boolean isPendingSharedTransition() {
-        return mPendingSharedTransition;
-    }
-
-    void animateDismissal() {
-        mScreenshotStatic.dismiss();
-    }
-
-    void reset() {
-        if (DEBUG_UI) {
-            Log.d(TAG, "reset screenshot view");
-        }
-        mScreenshotStatic.cancelDismissal();
-        if (DEBUG_WINDOW) {
-            Log.d(TAG, "removing OnComputeInternalInsetsListener");
-        }
-        // Make sure we clean up the view tree observer
-        getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
-        // Clear any references to the bitmap
-        mScreenshotPreview.setImageDrawable(null);
-        mScreenshotPreview.setVisibility(View.INVISIBLE);
-        mScreenshotPreview.setAlpha(1f);
-        mScreenshotPreviewBorder.setAlpha(0);
-        mScreenshotBadge.setAlpha(0f);
-        mScreenshotBadge.setVisibility(View.GONE);
-        mScreenshotBadge.setImageDrawable(null);
-        mPendingSharedTransition = false;
-        mActionsContainerBackground.setVisibility(View.INVISIBLE);
-        mActionsContainer.setVisibility(View.GONE);
-        mDismissButton.setVisibility(View.GONE);
-        mScrollingScrim.setVisibility(View.GONE);
-        mScrollablePreview.setVisibility(View.GONE);
-        mScreenshotStatic.setTranslationX(0);
-        mScreenshotPreview.setContentDescription(
-                mContext.getResources().getString(R.string.screenshot_preview_description));
-        mScreenshotPreview.setOnClickListener(null);
-        mShareChip.setOnClickListener(null);
-        mScrollingScrim.setVisibility(View.GONE);
-        mEditChip.setOnClickListener(null);
-        mShareChip.setIsPending(false);
-        mEditChip.setIsPending(false);
-        mPendingInteraction = null;
-        for (OverlayActionChip chip : mSmartChips) {
-            mActionsView.removeView(chip);
-        }
-        mSmartChips.clear();
-        mQuickShareChip = null;
-        setAlpha(1);
-        mScreenshotStatic.setAlpha(1);
-        mScreenshotData = null;
-    }
-
-    private void prepareSharedTransition() {
-        mPendingSharedTransition = true;
-        // fade out non-preview UI
-        createScreenshotFadeDismissAnimation().start();
-    }
-
-    ValueAnimator createScreenshotFadeDismissAnimation() {
-        ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
-        alphaAnim.addUpdateListener(animation -> {
-            float alpha = 1 - animation.getAnimatedFraction();
-            mDismissButton.setAlpha(alpha);
-            mActionsContainerBackground.setAlpha(alpha);
-            mActionsContainer.setAlpha(alpha);
-            mScreenshotPreviewBorder.setAlpha(alpha);
-            mScreenshotBadge.setAlpha(alpha);
-        });
-        alphaAnim.setDuration(600);
-        return alphaAnim;
-    }
-
-    /**
-     * Create a drawable using the size of the bitmap and insets as the fractional inset parameters.
-     */
-    private static Drawable createScreenDrawable(Resources res, Bitmap bitmap, Insets insets) {
-        int insettedWidth = bitmap.getWidth() - insets.left - insets.right;
-        int insettedHeight = bitmap.getHeight() - insets.top - insets.bottom;
-
-        BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bitmap);
-        if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
-                || bitmap.getHeight() == 0) {
-            Log.e(TAG, "Can't create inset drawable, using 0 insets bitmap and insets create "
-                    + "degenerate region: " + bitmap.getWidth() + "x" + bitmap.getHeight() + " "
-                    + bitmapDrawable);
-            return bitmapDrawable;
-        }
-
-        InsetDrawable insetDrawable = new InsetDrawable(bitmapDrawable,
-                -1f * insets.left / insettedWidth,
-                -1f * insets.top / insettedHeight,
-                -1f * insets.right / insettedWidth,
-                -1f * insets.bottom / insettedHeight);
-
-        if (insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0) {
-            // Are any of the insets negative, meaning the bitmap is smaller than the bounds so need
-            // to fill in the background of the drawable.
-            return new LayerDrawable(new Drawable[]{
-                    new ColorDrawable(Color.BLACK), insetDrawable});
-        } else {
-            return insetDrawable;
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt
deleted file mode 100644
index df93a5e..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import android.animation.Animator
-import android.app.Notification
-import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.Rect
-import android.view.ScrollCaptureResponse
-import android.view.View
-import android.view.ViewGroup
-import android.view.WindowInsets
-import com.android.systemui.screenshot.scroll.ScrollCaptureController
-
-/** Abstraction of the surface between ScreenshotController and ScreenshotView */
-interface ScreenshotViewProxy {
-    val view: ViewGroup
-    val screenshotPreview: View
-
-    var packageName: String
-    var callbacks: ScreenshotView.ScreenshotViewCallback?
-    var screenshot: ScreenshotData?
-
-    val isAttachedToWindow: Boolean
-    val isDismissing: Boolean
-    val isPendingSharedTransition: Boolean
-
-    fun reset()
-    fun updateInsets(insets: WindowInsets)
-    fun updateOrientation(insets: WindowInsets)
-    fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator
-    fun addQuickShareChip(quickShareAction: Notification.Action)
-    fun setChipIntents(imageData: ScreenshotController.SavedImageData)
-    fun requestDismissal(event: ScreenshotEvent?)
-
-    fun showScrollChip(packageName: String, onClick: Runnable)
-    fun hideScrollChip()
-    fun prepareScrollingTransition(
-        response: ScrollCaptureResponse,
-        screenBitmap: Bitmap,
-        newScreenshot: Bitmap,
-        screenshotTakenInPortrait: Boolean,
-        onTransitionPrepared: Runnable,
-    )
-    fun startLongScreenshotTransition(
-        transitionDestination: Rect,
-        onTransitionEnd: Runnable,
-        longScreenshot: ScrollCaptureController.LongScreenshot
-    )
-    fun restoreNonScrollingUi()
-    fun fadeForSharedTransition()
-
-    fun stopInputListening()
-    fun requestFocus()
-    fun announceForAccessibility(string: String)
-    fun prepareEntranceAnimation(runnable: Runnable)
-
-    interface Factory {
-        fun getProxy(context: Context, displayId: Int): ScreenshotViewProxy
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index 56ba1af4..682f848 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -24,12 +24,10 @@
 import com.android.systemui.screenshot.ImageCaptureImpl;
 import com.android.systemui.screenshot.ScreenshotPolicy;
 import com.android.systemui.screenshot.ScreenshotPolicyImpl;
-import com.android.systemui.screenshot.ScreenshotShelfViewProxy;
 import com.android.systemui.screenshot.ScreenshotSoundController;
 import com.android.systemui.screenshot.ScreenshotSoundControllerImpl;
 import com.android.systemui.screenshot.ScreenshotSoundProvider;
 import com.android.systemui.screenshot.ScreenshotSoundProviderImpl;
-import com.android.systemui.screenshot.ScreenshotViewProxy;
 import com.android.systemui.screenshot.TakeScreenshotExecutor;
 import com.android.systemui.screenshot.TakeScreenshotExecutorImpl;
 import com.android.systemui.screenshot.TakeScreenshotService;
@@ -92,8 +90,4 @@
             AccessibilityManager accessibilityManager) {
         return new ScreenshotViewModel(accessibilityManager);
     }
-
-    @Binds
-    abstract ScreenshotViewProxy.Factory bindScreenshotViewProxyFactory(
-            ScreenshotShelfViewProxy.Factory shelfScreenshotViewProxyFactory);
 }
diff --git a/services/core/java/com/android/server/notification/ZenModeEventLogger.java b/services/core/java/com/android/server/notification/ZenModeEventLogger.java
index ec5d96d..4a82057 100644
--- a/services/core/java/com/android/server/notification/ZenModeEventLogger.java
+++ b/services/core/java/com/android/server/notification/ZenModeEventLogger.java
@@ -106,11 +106,11 @@
     /**
      * Potentially log a zen mode change if the provided config and policy changes warrant it.
      *
-     * @param prevInfo    ZenModeInfo (zen mode setting, config, policy) prior to this change
-     * @param newInfo     ZenModeInfo after this change takes effect
-     * @param callingUid  the calling UID associated with the change; may be used to attribute the
-     *                    change to a particular package or determine if this is a user action
-     * @param origin      The origin of the Zen change.
+     * @param prevInfo   ZenModeInfo (zen mode setting, config, policy) prior to this change
+     * @param newInfo    ZenModeInfo after this change takes effect
+     * @param callingUid the calling UID associated with the change; may be used to attribute the
+     *                   change to a particular package or determine if this is a user action
+     * @param origin     The origin of the Zen change.
      */
     public final void maybeLogZenChange(ZenModeInfo prevInfo, ZenModeInfo newInfo, int callingUid,
             @ConfigChangeOrigin int origin) {
@@ -127,6 +127,9 @@
     /**
      * Reassign callingUid in mChangeState if we have more specific information that warrants it
      * (for instance, if the change is automatic and due to an automatic rule change).
+     *
+     * <p>When Flags.modesUi() is enabled, we reassign the calling UID to the package UID in all
+     * changes whose source is not system or system UI, as long as there is only one rule changed.
      */
     private void maybeReassignCallingUid() {
         int userId = Process.INVALID_UID;
@@ -145,12 +148,23 @@
             userId = mChangeState.mNewConfig.user;  // mNewConfig must not be null if enabler exists
         }
 
-        // The conditions where we should consider reassigning UID for an automatic rule change:
+        // The conditions where we should consider reassigning UID for an automatic rule change
+        // (pre-modes_ui):
         //   - we've determined it's not a user action
         //   - our current best guess is that the calling uid is system/sysui
+        // When Flags.modesUi() is true, we get the package UID for the changed rule, as long as:
+        //   - the change does not originate from the system based on change origin
+        //   - there is only one rule changed
         if (mChangeState.getChangedRuleType() == RULE_TYPE_AUTOMATIC) {
-            if (mChangeState.getIsUserAction() || !mChangeState.isFromSystemOrSystemUi()) {
-                return;
+            if (Flags.modesUi()) {
+                // ignore anything whose origin is system
+                if (mChangeState.isFromSystemOrSystemUi()) {
+                    return;
+                }
+            } else {
+                if (mChangeState.getIsUserAction() || !mChangeState.isFromSystemOrSystemUi()) {
+                    return;
+                }
             }
 
             // Only try to get the package UID if there's exactly one changed automatic rule. If
@@ -202,7 +216,8 @@
                 /* int32 package_uid = 7 */ mChangeState.getPackageUid(),
                 /* DNDPolicyProto current_policy = 8 */ mChangeState.getDNDPolicyProto(),
                 /* bool are_channels_bypassing = 9 */ mChangeState.getAreChannelsBypassing(),
-                /* ActiveRuleType active_rule_types = 10 */ mChangeState.getActiveRuleTypes());
+                /* ActiveRuleType active_rule_types = 10 */ mChangeState.getActiveRuleTypes(),
+                /* ChangeOrigin change_origin = 11 */ mChangeState.getChangeOrigin());
     }
 
     /**
@@ -235,7 +250,8 @@
         ZenModeConfig mPrevConfig, mNewConfig;
         NotificationManager.Policy mPrevPolicy, mNewPolicy;
         int mCallingUid = Process.INVALID_UID;
-        @ConfigChangeOrigin int mOrigin = ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;
+        @ConfigChangeOrigin
+        int mOrigin = ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;
 
         private void init(ZenModeInfo prevInfo, ZenModeInfo newInfo, int callingUid,
                 @ConfigChangeOrigin int origin) {
@@ -388,7 +404,8 @@
          * rules available.
          */
         @SuppressLint("WrongConstant")  // special case for log-only type on manual rule
-        @NonNull List<ZenRule> activeRulesList(ZenModeConfig config) {
+        @NonNull
+        List<ZenRule> activeRulesList(ZenModeConfig config) {
             ArrayList<ZenRule> rules = new ArrayList<>();
             if (config == null) {
                 return rules;
@@ -548,6 +565,17 @@
         }
 
         /**
+         * Get the config change origin associated with this change, which is stored in mOrigin.
+         * Only useable if modes_ui is true.
+         */
+        int getChangeOrigin() {
+            if (Flags.modesUi()) {
+                return mOrigin;
+            }
+            return 0;
+        }
+
+        /**
          * Convert the new policy to a DNDPolicyProto format for output in logs.
          *
          * <p>If {@code mNewZenMode} is {@code ZEN_MODE_OFF} (which can mean either no rules
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java
index ff1308c..1c8cb8f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java
@@ -137,4 +137,9 @@
         checkInRange(i);
         return mChanges.get(i).getActiveRuleTypes();
     }
+
+    public int getChangeOrigin(int i) throws IllegalArgumentException {
+        checkInRange(i);
+        return mChanges.get(i).getChangeOrigin();
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 7bb633e..4bbbc2b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -818,7 +818,7 @@
         // 1. Current ringer is normal
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         // Set zen to priority-only with all notification sounds muted (so ringer will be muted)
-        Policy totalSilence = new Policy(0,0,0);
+        Policy totalSilence = new Policy(0, 0, 0);
         mZenModeHelper.setNotificationPolicy(totalSilence, UPDATE_ORIGIN_APP, 1);
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 
@@ -873,7 +873,7 @@
 
         // even when ringer is muted (since all ringer sounds cannot bypass DND),
         // system stream is still affected by ringer mode
-        mZenModeHelper.setNotificationPolicy(new Policy(0,0,0), UPDATE_ORIGIN_APP, 1);
+        mZenModeHelper.setNotificationPolicy(new Policy(0, 0, 0), UPDATE_ORIGIN_APP, 1);
         mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, Uri.EMPTY,
                 UPDATE_ORIGIN_APP, "test", "caller", 1);
         ZenModeHelper.RingerModeDelegate ringerModeDelegateRingerNotMuted =
@@ -1065,9 +1065,10 @@
     @Test
     public void testParcelConfig() {
         mZenModeHelper.setNotificationPolicy(new Policy(PRIORITY_CATEGORY_EVENTS
-                | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS
-                | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED,
-                PRIORITY_SENDERS_STARRED, 0, CONVERSATION_SENDERS_ANYONE), UPDATE_ORIGIN_UNKNOWN,
+                        | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS
+                        | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED,
+                        PRIORITY_SENDERS_STARRED, 0, CONVERSATION_SENDERS_ANYONE),
+                UPDATE_ORIGIN_UNKNOWN,
                 1);
         mZenModeHelper.setManualZenRuleDeviceEffects(new ZenDeviceEffects.Builder()
                 .setShouldDimWallpaper(true)
@@ -1085,13 +1086,14 @@
     @Test
     public void testWriteXml() throws Exception {
         mZenModeHelper.setNotificationPolicy(new Policy(PRIORITY_CATEGORY_EVENTS
-                | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS
-                | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED,
-                PRIORITY_SENDERS_STARRED, SUPPRESSED_EFFECT_BADGE, CONVERSATION_SENDERS_ANYONE),
+                        | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS
+                        | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED,
+                        PRIORITY_SENDERS_STARRED, SUPPRESSED_EFFECT_BADGE,
+                        CONVERSATION_SENDERS_ANYONE),
                 UPDATE_ORIGIN_UNKNOWN, 1);
         mZenModeHelper.setManualZenRuleDeviceEffects(new ZenDeviceEffects.Builder()
-                        .setShouldDimWallpaper(true)
-                        .setShouldDisplayGrayscale(true)
+                .setShouldDimWallpaper(true)
+                .setShouldDisplayGrayscale(true)
                 .build(), UPDATE_ORIGIN_UNKNOWN, "test", 1);
         mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, Uri.EMPTY,
                 UPDATE_ORIGIN_UNKNOWN, "test", "me", 1);
@@ -2210,7 +2212,7 @@
         customDefaultRule.name = "Schedule Default Rule";
         customDefaultRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         ScheduleInfo scheduleInfo = new ScheduleInfo();
-        scheduleInfo.days = new int[] { Calendar.SUNDAY };
+        scheduleInfo.days = new int[]{Calendar.SUNDAY};
         scheduleInfo.startHour = 18;
         scheduleInfo.endHour = 19;
         customDefaultRule.conditionId = ZenModeConfig.toScheduleConditionId(scheduleInfo);
@@ -3027,7 +3029,7 @@
         // Turn zen mode on (to important_interruptions)
         // Need to additionally call the looper in order to finish the post-apply-config process
         mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
-                Flags.modesApi() ? UPDATE_ORIGIN_USER: UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null,
+                Flags.modesApi() ? UPDATE_ORIGIN_USER : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null,
                 Process.SYSTEM_UID);
 
         // Now turn zen mode off, but via a different package UID -- this should get registered as
@@ -3060,6 +3062,9 @@
         assertTrue(mZenModeEventLogger.getIsUserAction(0));
         assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(0));
         checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0));
+        // change origin should be populated only under modes_ui
+        assertThat(mZenModeEventLogger.getChangeOrigin(0)).isEqualTo(
+                (Flags.modesApi() && Flags.modesUi()) ? UPDATE_ORIGIN_USER : 0);
 
         // and from turning zen mode off:
         //   - event ID: DND_TURNED_OFF
@@ -3082,6 +3087,8 @@
         } else {
             checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
         }
+        assertThat(mZenModeEventLogger.getChangeOrigin(1)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);
     }
 
     @Test
@@ -3098,17 +3105,21 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+                UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);
 
         // Event 1: Mimic the rule coming on automatically by setting the Condition to STATE_TRUE
+        // Note that pre-modes_ui, this event serves as a test that automatic changes to an app's
+        // that look like they're coming from the system are attributed to the app, but when
+        // modes_ui is true, we opt to trust the provided change origin.
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
+                Flags.modesUi() ? UPDATE_ORIGIN_APP : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                CUSTOM_PKG_UID);
 
         // Event 2: "User" turns off the automatic rule (sets it to not enabled)
         zenRule.setEnabled(false);
         mZenModeHelper.updateAutomaticZenRule(id, zenRule,
-                Flags.modesApi() ? UPDATE_ORIGIN_USER: UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                Flags.modesApi() ? UPDATE_ORIGIN_USER : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
                 Process.SYSTEM_UID);
 
         AutomaticZenRule systemRule = new AutomaticZenRule("systemRule",
@@ -3118,7 +3129,7 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String systemId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), systemRule,
-                Flags.modesApi() ? UPDATE_ORIGIN_USER: UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test",
+                Flags.modesApi() ? UPDATE_ORIGIN_USER : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test",
                 Process.SYSTEM_UID);
 
         // Event 3: turn on the system rule
@@ -3128,7 +3139,7 @@
 
         // Event 4: "User" deletes the rule
         mZenModeHelper.removeAutomaticZenRule(systemId,
-                Flags.modesApi() ? UPDATE_ORIGIN_USER: UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                Flags.modesApi() ? UPDATE_ORIGIN_USER : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
                 Process.SYSTEM_UID);
         // In total, this represents 4 events
         assertEquals(4, mZenModeEventLogger.numLoggedChanges());
@@ -3151,9 +3162,13 @@
         assertFalse(mZenModeEventLogger.getIsUserAction(0));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
         checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0));
+        assertThat(mZenModeEventLogger.getChangeOrigin(0)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);
 
         // When the automatic rule is disabled, this should turn off zen mode and also count as a
         // user action. We don't care what the consolidated policy is when DND turns off.
+        // When modes_ui is true, this event should look like a user action attributed to the
+        // specific app.
         assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_OFF.getId(),
                 mZenModeEventLogger.getEventId(1));
         assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeEventLogger.getPrevZenMode(1));
@@ -3161,12 +3176,15 @@
         assertEquals(DNDProtoEnums.AUTOMATIC_RULE, mZenModeEventLogger.getChangedRuleType(1));
         assertEquals(0, mZenModeEventLogger.getNumRulesActive(1));
         assertTrue(mZenModeEventLogger.getIsUserAction(1));
-        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));
+        assertThat(mZenModeEventLogger.getPackageUid(1)).isEqualTo(
+                Flags.modesUi() ? CUSTOM_PKG_UID : Process.SYSTEM_UID);
         if (Flags.modesApi()) {
             assertThat(mZenModeEventLogger.getPolicyProto(1)).isNull();
         } else {
             checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
         }
+        assertThat(mZenModeEventLogger.getChangeOrigin(1)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);
 
         // When the system rule is enabled, this counts as an automatic action that comes from the
         // system and turns on DND
@@ -3176,6 +3194,8 @@
         assertEquals(1, mZenModeEventLogger.getNumRulesActive(2));
         assertFalse(mZenModeEventLogger.getIsUserAction(2));
         assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(2));
+        assertThat(mZenModeEventLogger.getChangeOrigin(2)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI : 0);
 
         // When the system rule is deleted, we consider this a user action that turns DND off
         // (again)
@@ -3185,6 +3205,8 @@
         assertEquals(0, mZenModeEventLogger.getNumRulesActive(3));
         assertTrue(mZenModeEventLogger.getIsUserAction(3));
         assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(3));
+        assertThat(mZenModeEventLogger.getChangeOrigin(3)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);
     }
 
     @Test
@@ -3238,6 +3260,8 @@
         assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
         assertTrue(mZenModeEventLogger.getIsUserAction(0));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
+        assertThat(mZenModeEventLogger.getChangeOrigin(0)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);
 
         // Automatic rule turned off automatically by app:
         //   - event ID: DND_TURNED_OFF
@@ -3249,6 +3273,8 @@
         assertEquals(0, mZenModeEventLogger.getNumRulesActive(1));
         assertFalse(mZenModeEventLogger.getIsUserAction(1));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1));
+        assertThat(mZenModeEventLogger.getChangeOrigin(1)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);
 
         // Automatic rule turned on automatically by app:
         //   - event ID: DND_TURNED_ON
@@ -3261,6 +3287,8 @@
         assertEquals(1, mZenModeEventLogger.getNumRulesActive(2));
         assertFalse(mZenModeEventLogger.getIsUserAction(2));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(2));
+        assertThat(mZenModeEventLogger.getChangeOrigin(2)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);
 
         // Automatic rule turned off automatically by the user:
         //   - event ID: DND_TURNED_ON
@@ -3272,6 +3300,8 @@
         assertEquals(0, mZenModeEventLogger.getNumRulesActive(3));
         assertTrue(mZenModeEventLogger.getIsUserAction(3));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(3));
+        assertThat(mZenModeEventLogger.getChangeOrigin(3)).isEqualTo(
+                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);
     }
 
     @Test
@@ -3335,7 +3365,7 @@
 
         AutomaticZenRule zenRule = new AutomaticZenRule("name",
                 null,
-                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                new ComponentName("android", "ScheduleConditionProvider"),
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
@@ -3345,7 +3375,7 @@
         // Rule 2, same as rule 1
         AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
                 null,
-                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                new ComponentName("android", "ScheduleConditionProvider"),
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
@@ -3395,7 +3425,7 @@
         assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeEventLogger.getNewZenMode(0));
         assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
         assertFalse(mZenModeEventLogger.getIsUserAction(0));
-        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
+        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(0));
         checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0));
 
         // Event 2: rule 2 turns on. This should not change anything about the policy, so the only
@@ -3404,7 +3434,7 @@
                 mZenModeEventLogger.getEventId(1));
         assertEquals(2, mZenModeEventLogger.getNumRulesActive(1));
         assertFalse(mZenModeEventLogger.getIsUserAction(1));
-        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1));
+        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));
         checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(1));
 
         // Event 3: rule 3 turns on. This should trigger a policy change, and be classified as such,
@@ -3482,9 +3512,11 @@
         // Turn on rule 1; call looks like it's from the system. Because setting a condition is
         // typically an automatic (non-user-initiated) action, expect the calling UID to be
         // re-evaluated to the one associated with CUSTOM_PKG_NAME.
+        // When modes_ui is true: we expect the change origin to be the source of truth.
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
+                Flags.modesUi() ? UPDATE_ORIGIN_APP : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                Process.SYSTEM_UID);
 
         // Second: turn on rule 2. This is a system-owned rule and the UID should not be modified
         // (nor even looked up; the mock PackageManager won't handle "android" as input).
@@ -3493,7 +3525,7 @@
                 UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Disable rule 1. Because this looks like a user action, the UID should not be modified
-        // from the system-provided one.
+        // from the system-provided one unless modes_ui is true.
         zenRule.setEnabled(false);
         mZenModeHelper.updateAutomaticZenRule(id, zenRule,
                 UPDATE_ORIGIN_USER, "", Process.SYSTEM_UID);
@@ -3504,6 +3536,7 @@
 
         // Change rule 2's condition, but from some other UID. Since it doesn't look like it's from
         // the system, we keep the UID info.
+        // Note that this probably shouldn't be able to occur in real scenarios.
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_FALSE),
                 UPDATE_ORIGIN_APP, 12345);
@@ -3528,11 +3561,13 @@
         assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));
 
         // Third event: disable rule 1. This looks like a user action so UID should be left alone.
+        // When modes_ui is true, we assign log this user action with the app that owns the rule.
         assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED.getId(),
                 mZenModeEventLogger.getEventId(2));
         assertEquals(DNDProtoEnums.AUTOMATIC_RULE, mZenModeEventLogger.getChangedRuleType(2));
         assertTrue(mZenModeEventLogger.getIsUserAction(2));
-        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(2));
+        assertThat(mZenModeEventLogger.getPackageUid(2)).isEqualTo(
+                Flags.modesUi() ? CUSTOM_PKG_UID : Process.SYSTEM_UID);
 
         // Fourth event: turns on manual mode. Doesn't change effective policy so this is just a
         // change in active rules. Confirm that the package UID is left unchanged.
@@ -6202,7 +6237,7 @@
     public void setManualZenRuleDeviceEffects_noPreexistingMode() {
         ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
                 .setShouldDimWallpaper(true)
-                        .build();
+                .build();
         mZenModeHelper.setManualZenRuleDeviceEffects(effects, UPDATE_ORIGIN_USER, "settings", 1000);
 
         assertThat(mZenModeHelper.getConfig().manualRule).isNotNull();
@@ -6339,21 +6374,21 @@
 
     private static final Correspondence<ZenRule, ZenRule> IGNORE_METADATA =
             Correspondence.transforming(zr -> {
-                Parcel p = Parcel.obtain();
-                try {
-                    zr.writeToParcel(p, 0);
-                    p.setDataPosition(0);
-                    ZenRule copy = new ZenRule(p);
-                    copy.creationTime = 0;
-                    copy.userModifiedFields = 0;
-                    copy.zenPolicyUserModifiedFields = 0;
-                    copy.zenDeviceEffectsUserModifiedFields = 0;
-                    return copy;
-                } finally {
-                    p.recycle();
-                }
-            },
-              "Ignoring timestamp and userModifiedFields");
+                        Parcel p = Parcel.obtain();
+                        try {
+                            zr.writeToParcel(p, 0);
+                            p.setDataPosition(0);
+                            ZenRule copy = new ZenRule(p);
+                            copy.creationTime = 0;
+                            copy.userModifiedFields = 0;
+                            copy.zenPolicyUserModifiedFields = 0;
+                            copy.zenDeviceEffectsUserModifiedFields = 0;
+                            return copy;
+                        } finally {
+                            p.recycle();
+                        }
+                    },
+                    "Ignoring timestamp and userModifiedFields");
 
     private ZenRule expectedImplicitRule(String ownerPkg, int zenMode, ZenPolicy policy,
             @Nullable Boolean conditionActive) {