Loading libs/WindowManager/Shell/res/layout/open_by_default_settings_dialog.xml +1 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ tools:text="Gmail" /> <TextView android:id="@+id/dialog_subheader" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12sp" Loading libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt +100 −52 Original line number Diff line number Diff line Loading @@ -20,25 +20,31 @@ import android.app.ActivityManager.RunningTaskInfo import android.content.Context import android.content.pm.PackageManager.NameNotFoundException import android.content.pm.verify.domain.DomainVerificationManager import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.PixelFormat import android.graphics.Rect import android.os.Binder import android.util.Slog import android.view.IWindow import android.view.LayoutInflater import android.view.SurfaceControl import android.view.SurfaceControlViewHost import android.view.WindowManager import android.view.WindowManager.LayoutParams import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL import android.view.WindowlessWindowManager import android.view.accessibility.AccessibilityEvent import android.widget.ImageView import android.widget.RadioButton import android.widget.TextView import android.window.TaskConstants import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.compatui.DialogAnimationController import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer import com.android.wm.shell.transition.Transitions import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import java.util.function.Supplier import kotlinx.coroutines.CoroutineScope Loading @@ -54,6 +60,7 @@ import kotlinx.coroutines.launch internal class OpenByDefaultDialog( private val context: Context, private val userContext: Context, private val transitions: Transitions, private val taskInfo: RunningTaskInfo, private val taskSurface: SurfaceControl, private val displayController: DisplayController, Loading @@ -65,14 +72,15 @@ internal class OpenByDefaultDialog( ) { private lateinit var dialog: OpenByDefaultDialogView private lateinit var viewHost: SurfaceControlViewHost private lateinit var dialogSurfaceControl: SurfaceControl private var dialogContainer: AdditionalViewHostViewContainer? = null private lateinit var dialogWindowManager: DialogWindowManager private lateinit var appIconView: ImageView private lateinit var appNameView: TextView private lateinit var openInAppButton: RadioButton private lateinit var openInBrowserButton: RadioButton private val animationController = DialogAnimationController<OpenByDefaultDialogView>(context, "OpenByDefaultDialog") private val domainVerificationManager = userContext.getSystemService(DomainVerificationManager::class.java)!! private val packageName = taskInfo.baseActivity?.packageName!! Loading @@ -91,9 +99,6 @@ internal class OpenByDefaultDialog( /** Creates an open by default settings dialog. */ fun createDialog() { val t = SurfaceControl.Transaction() val taskBounds = taskInfo.configuration.windowConfiguration.bounds dialog = LayoutInflater.from(context) .inflate( R.layout.open_by_default_settings_dialog, Loading @@ -102,47 +107,48 @@ internal class OpenByDefaultDialog( appIconView = dialog.requireViewById(R.id.application_icon) appNameView = dialog.requireViewById(R.id.application_name) // TODO: ag/34061541 - once landed, can refactor with simpler fix transitions.runOnIdle(this::createDialogWindow) dialog.setDismissOnClickListener { closeMenu() } dialog.setConfirmButtonClickListener { setDefaultLinkHandlingSetting() closeMenu() } listener.onDialogCreated() } private fun createDialogWindow() { val display = displayController.getDisplay(taskInfo.displayId) val builder: SurfaceControl.Builder = SurfaceControl.Builder() dialogSurfaceControl = builder .setName("Open by Default Dialog of Task=" + taskInfo.taskId) .setContainerLayer() .setParent(taskSurface) .setCallsite("OpenByDefaultDialog#createDialog") .build() t.setPosition(dialogSurfaceControl, 0f, 0f) .setWindowCrop(dialogSurfaceControl, taskBounds.width(), taskBounds.height()) .setLayer(dialogSurfaceControl, TaskConstants.TASK_CHILD_LAYER_SETTINGS_DIALOG) .show(dialogSurfaceControl) val lp = WindowManager.LayoutParams( val taskBounds = taskInfo.configuration.windowConfiguration.bounds val lp = LayoutParams( taskBounds.width(), taskBounds.height(), TYPE_APPLICATION_PANEL, FLAG_NOT_FOCUSABLE or FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT) lp.title = "Open by default settings dialog of task=" + taskInfo.taskId lp.setTrustedOverlay() val windowManager = WindowlessWindowManager( taskInfo.configuration, dialogSurfaceControl, null /* hostInputToken */ ) viewHost = SurfaceControlViewHost(context, display, windowManager, "Dialog").apply { setView(dialog, lp) rootSurfaceControl.applyTransactionOnDraw(t) PixelFormat.TRANSLUCENT ).apply { token = Binder() title = "Open by default settings dialog of task=${taskInfo.taskId}" setTrustedOverlay() } dialogContainer = AdditionalViewHostViewContainer( dialogSurfaceControl, viewHost, surfaceControlTransactionSupplier) dialog.setDismissOnClickListener{ closeMenu() dialogWindowManager = DialogWindowManager(taskInfo.configuration) viewHost = SurfaceControlViewHost(context, display, dialogWindowManager, "Dialog").apply { setView(dialog, lp) } dialog.setConfirmButtonClickListener { setDefaultLinkHandlingSetting() closeMenu() animationController.startEnterAnimation(dialog, this::onAnimationEnded) } listener.onDialogCreated() private fun onAnimationEnded() { dialog.post { dialog.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) val subHeader: TextView = dialog.requireViewById(R.id.dialog_subheader) subHeader.requestFocus() subHeader.requestAccessibilityFocus() } } private fun initializeRadioButtons() { Loading @@ -163,22 +169,22 @@ internal class OpenByDefaultDialog( } catch (e: NameNotFoundException) { Slog.e( TAG, "Failed to change link handling policy due to the package name is not found: " + e "Failed to change link handling policy due to the package name is not found: $e" ) } } private fun closeMenu() { loadAppInfoJob?.cancel() dialogContainer?.releaseView() dialogContainer = null animationController.startExitAnimation(dialog) { // Release the host and manager after the exit animation viewHost.release() dialogWindowManager.release() listener.onDialogDismissed() } } private fun bindAppInfo( appIconBitmap: Bitmap, appName: CharSequence ) { private fun bindAppInfo(appIconBitmap: Bitmap, appName: CharSequence) { appIconView.setImageBitmap(appIconBitmap) appNameView.text = appName } Loading @@ -186,16 +192,58 @@ internal class OpenByDefaultDialog( /** * Relayout the dialog to the new task bounds. */ fun relayout( taskInfo: RunningTaskInfo, ) { val t = surfaceControlTransactionSupplier.get() fun relayout(taskInfo: RunningTaskInfo) { val taskBounds = taskInfo.configuration.windowConfiguration.bounds t.setWindowCrop(dialogSurfaceControl, taskBounds.width(), taskBounds.height()) viewHost.rootSurfaceControl.applyTransactionOnDraw(t) dialogWindowManager.relayout(taskBounds) viewHost.relayout(taskBounds.width(), taskBounds.height()) } /** * Handles showing, positioning and tearing down the dialog surface */ private inner class DialogWindowManager(config: Configuration) : WindowlessWindowManager(config, null, null) { private var leash: SurfaceControl? = null override fun getParentSurface( window: IWindow, attrs: LayoutParams ): SurfaceControl { val builder = SurfaceControl.Builder() .setContainerLayer() .setName("OpenByDefaultDialogLeash") .setParent(taskSurface) .setCallsite("OpenByDefaultDialog.getParentSurface") val newLeash = builder.build() leash = newLeash val t = surfaceControlTransactionSupplier.get() val taskBounds = taskInfo.configuration.windowConfiguration.bounds t.setPosition(newLeash, 0f, 0f) .setWindowCrop(newLeash, taskBounds.width(), taskBounds.height()) .setLayer(newLeash, TaskConstants.TASK_CHILD_LAYER_SETTINGS_DIALOG) .show(newLeash) .apply() return newLeash } fun relayout(taskBounds: Rect) { leash?.let { surfaceControlTransactionSupplier.get() .setWindowCrop(it, taskBounds.width(), taskBounds.height()) .apply() } } fun release() { leash?.let { surfaceControlTransactionSupplier.get().remove(it).apply() } leash = null } } /** * Defines interface for classes that can listen to lifecycle events of open by default settings * dialog. Loading libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialogView.kt +7 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.view.View import android.widget.Button import androidx.constraintlayout.widget.ConstraintLayout import com.android.wm.shell.R import com.android.wm.shell.compatui.DialogContainerSupplier /** View for open by default settings dialog for an application which allows the user to change * where links will open by default, in the default browser or in the application. */ Loading @@ -30,7 +31,7 @@ class OpenByDefaultDialogView @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) { ) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes), DialogContainerSupplier { private lateinit var dialogContainer: View private lateinit var backgroundDim: Drawable Loading @@ -50,8 +51,13 @@ class OpenByDefaultDialogView @JvmOverloads constructor( dismissButton.setOnClickListener(callback) } override fun getDialogContainerView(): View = dialogContainer override fun getBackgroundDimDrawable(): Drawable = backgroundDim override fun onFinishInflate() { super.onFinishInflate() accessibilityPaneTitle = context.getString(R.string.open_by_default_settings_text) dialogContainer = requireViewById(R.id.open_by_default_dialog_container) backgroundDim = background.mutate() backgroundDim.alpha = 128 Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DefaultWindowDecoration.kt +2 −0 Original line number Diff line number Diff line Loading @@ -890,6 +890,7 @@ class DefaultWindowDecoration @JvmOverloads constructor( taskResourceLoader, splitScreenController, desktopUserRepositories, transitions, taskSurface, checkNotNull(decorationContainerSurface) { "Expected non-null decoration container surface" Loading Loading @@ -922,6 +923,7 @@ class DefaultWindowDecoration @JvmOverloads constructor( windowDecorViewHostSupplier, context, userContext, transitions, displayController, taskResourceLoader, splitScreenController, Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +1 −0 Original line number Diff line number Diff line Loading @@ -1281,6 +1281,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mOpenByDefaultDialog = new OpenByDefaultDialog( mContext, mUserContext, mTransitions, mTaskInfo, mTaskSurface, mDisplayController, Loading Loading
libs/WindowManager/Shell/res/layout/open_by_default_settings_dialog.xml +1 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ tools:text="Gmail" /> <TextView android:id="@+id/dialog_subheader" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12sp" Loading
libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt +100 −52 Original line number Diff line number Diff line Loading @@ -20,25 +20,31 @@ import android.app.ActivityManager.RunningTaskInfo import android.content.Context import android.content.pm.PackageManager.NameNotFoundException import android.content.pm.verify.domain.DomainVerificationManager import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.PixelFormat import android.graphics.Rect import android.os.Binder import android.util.Slog import android.view.IWindow import android.view.LayoutInflater import android.view.SurfaceControl import android.view.SurfaceControlViewHost import android.view.WindowManager import android.view.WindowManager.LayoutParams import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL import android.view.WindowlessWindowManager import android.view.accessibility.AccessibilityEvent import android.widget.ImageView import android.widget.RadioButton import android.widget.TextView import android.window.TaskConstants import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.compatui.DialogAnimationController import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer import com.android.wm.shell.transition.Transitions import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import java.util.function.Supplier import kotlinx.coroutines.CoroutineScope Loading @@ -54,6 +60,7 @@ import kotlinx.coroutines.launch internal class OpenByDefaultDialog( private val context: Context, private val userContext: Context, private val transitions: Transitions, private val taskInfo: RunningTaskInfo, private val taskSurface: SurfaceControl, private val displayController: DisplayController, Loading @@ -65,14 +72,15 @@ internal class OpenByDefaultDialog( ) { private lateinit var dialog: OpenByDefaultDialogView private lateinit var viewHost: SurfaceControlViewHost private lateinit var dialogSurfaceControl: SurfaceControl private var dialogContainer: AdditionalViewHostViewContainer? = null private lateinit var dialogWindowManager: DialogWindowManager private lateinit var appIconView: ImageView private lateinit var appNameView: TextView private lateinit var openInAppButton: RadioButton private lateinit var openInBrowserButton: RadioButton private val animationController = DialogAnimationController<OpenByDefaultDialogView>(context, "OpenByDefaultDialog") private val domainVerificationManager = userContext.getSystemService(DomainVerificationManager::class.java)!! private val packageName = taskInfo.baseActivity?.packageName!! Loading @@ -91,9 +99,6 @@ internal class OpenByDefaultDialog( /** Creates an open by default settings dialog. */ fun createDialog() { val t = SurfaceControl.Transaction() val taskBounds = taskInfo.configuration.windowConfiguration.bounds dialog = LayoutInflater.from(context) .inflate( R.layout.open_by_default_settings_dialog, Loading @@ -102,47 +107,48 @@ internal class OpenByDefaultDialog( appIconView = dialog.requireViewById(R.id.application_icon) appNameView = dialog.requireViewById(R.id.application_name) // TODO: ag/34061541 - once landed, can refactor with simpler fix transitions.runOnIdle(this::createDialogWindow) dialog.setDismissOnClickListener { closeMenu() } dialog.setConfirmButtonClickListener { setDefaultLinkHandlingSetting() closeMenu() } listener.onDialogCreated() } private fun createDialogWindow() { val display = displayController.getDisplay(taskInfo.displayId) val builder: SurfaceControl.Builder = SurfaceControl.Builder() dialogSurfaceControl = builder .setName("Open by Default Dialog of Task=" + taskInfo.taskId) .setContainerLayer() .setParent(taskSurface) .setCallsite("OpenByDefaultDialog#createDialog") .build() t.setPosition(dialogSurfaceControl, 0f, 0f) .setWindowCrop(dialogSurfaceControl, taskBounds.width(), taskBounds.height()) .setLayer(dialogSurfaceControl, TaskConstants.TASK_CHILD_LAYER_SETTINGS_DIALOG) .show(dialogSurfaceControl) val lp = WindowManager.LayoutParams( val taskBounds = taskInfo.configuration.windowConfiguration.bounds val lp = LayoutParams( taskBounds.width(), taskBounds.height(), TYPE_APPLICATION_PANEL, FLAG_NOT_FOCUSABLE or FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT) lp.title = "Open by default settings dialog of task=" + taskInfo.taskId lp.setTrustedOverlay() val windowManager = WindowlessWindowManager( taskInfo.configuration, dialogSurfaceControl, null /* hostInputToken */ ) viewHost = SurfaceControlViewHost(context, display, windowManager, "Dialog").apply { setView(dialog, lp) rootSurfaceControl.applyTransactionOnDraw(t) PixelFormat.TRANSLUCENT ).apply { token = Binder() title = "Open by default settings dialog of task=${taskInfo.taskId}" setTrustedOverlay() } dialogContainer = AdditionalViewHostViewContainer( dialogSurfaceControl, viewHost, surfaceControlTransactionSupplier) dialog.setDismissOnClickListener{ closeMenu() dialogWindowManager = DialogWindowManager(taskInfo.configuration) viewHost = SurfaceControlViewHost(context, display, dialogWindowManager, "Dialog").apply { setView(dialog, lp) } dialog.setConfirmButtonClickListener { setDefaultLinkHandlingSetting() closeMenu() animationController.startEnterAnimation(dialog, this::onAnimationEnded) } listener.onDialogCreated() private fun onAnimationEnded() { dialog.post { dialog.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) val subHeader: TextView = dialog.requireViewById(R.id.dialog_subheader) subHeader.requestFocus() subHeader.requestAccessibilityFocus() } } private fun initializeRadioButtons() { Loading @@ -163,22 +169,22 @@ internal class OpenByDefaultDialog( } catch (e: NameNotFoundException) { Slog.e( TAG, "Failed to change link handling policy due to the package name is not found: " + e "Failed to change link handling policy due to the package name is not found: $e" ) } } private fun closeMenu() { loadAppInfoJob?.cancel() dialogContainer?.releaseView() dialogContainer = null animationController.startExitAnimation(dialog) { // Release the host and manager after the exit animation viewHost.release() dialogWindowManager.release() listener.onDialogDismissed() } } private fun bindAppInfo( appIconBitmap: Bitmap, appName: CharSequence ) { private fun bindAppInfo(appIconBitmap: Bitmap, appName: CharSequence) { appIconView.setImageBitmap(appIconBitmap) appNameView.text = appName } Loading @@ -186,16 +192,58 @@ internal class OpenByDefaultDialog( /** * Relayout the dialog to the new task bounds. */ fun relayout( taskInfo: RunningTaskInfo, ) { val t = surfaceControlTransactionSupplier.get() fun relayout(taskInfo: RunningTaskInfo) { val taskBounds = taskInfo.configuration.windowConfiguration.bounds t.setWindowCrop(dialogSurfaceControl, taskBounds.width(), taskBounds.height()) viewHost.rootSurfaceControl.applyTransactionOnDraw(t) dialogWindowManager.relayout(taskBounds) viewHost.relayout(taskBounds.width(), taskBounds.height()) } /** * Handles showing, positioning and tearing down the dialog surface */ private inner class DialogWindowManager(config: Configuration) : WindowlessWindowManager(config, null, null) { private var leash: SurfaceControl? = null override fun getParentSurface( window: IWindow, attrs: LayoutParams ): SurfaceControl { val builder = SurfaceControl.Builder() .setContainerLayer() .setName("OpenByDefaultDialogLeash") .setParent(taskSurface) .setCallsite("OpenByDefaultDialog.getParentSurface") val newLeash = builder.build() leash = newLeash val t = surfaceControlTransactionSupplier.get() val taskBounds = taskInfo.configuration.windowConfiguration.bounds t.setPosition(newLeash, 0f, 0f) .setWindowCrop(newLeash, taskBounds.width(), taskBounds.height()) .setLayer(newLeash, TaskConstants.TASK_CHILD_LAYER_SETTINGS_DIALOG) .show(newLeash) .apply() return newLeash } fun relayout(taskBounds: Rect) { leash?.let { surfaceControlTransactionSupplier.get() .setWindowCrop(it, taskBounds.width(), taskBounds.height()) .apply() } } fun release() { leash?.let { surfaceControlTransactionSupplier.get().remove(it).apply() } leash = null } } /** * Defines interface for classes that can listen to lifecycle events of open by default settings * dialog. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialogView.kt +7 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.view.View import android.widget.Button import androidx.constraintlayout.widget.ConstraintLayout import com.android.wm.shell.R import com.android.wm.shell.compatui.DialogContainerSupplier /** View for open by default settings dialog for an application which allows the user to change * where links will open by default, in the default browser or in the application. */ Loading @@ -30,7 +31,7 @@ class OpenByDefaultDialogView @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) { ) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes), DialogContainerSupplier { private lateinit var dialogContainer: View private lateinit var backgroundDim: Drawable Loading @@ -50,8 +51,13 @@ class OpenByDefaultDialogView @JvmOverloads constructor( dismissButton.setOnClickListener(callback) } override fun getDialogContainerView(): View = dialogContainer override fun getBackgroundDimDrawable(): Drawable = backgroundDim override fun onFinishInflate() { super.onFinishInflate() accessibilityPaneTitle = context.getString(R.string.open_by_default_settings_text) dialogContainer = requireViewById(R.id.open_by_default_dialog_container) backgroundDim = background.mutate() backgroundDim.alpha = 128 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DefaultWindowDecoration.kt +2 −0 Original line number Diff line number Diff line Loading @@ -890,6 +890,7 @@ class DefaultWindowDecoration @JvmOverloads constructor( taskResourceLoader, splitScreenController, desktopUserRepositories, transitions, taskSurface, checkNotNull(decorationContainerSurface) { "Expected non-null decoration container surface" Loading Loading @@ -922,6 +923,7 @@ class DefaultWindowDecoration @JvmOverloads constructor( windowDecorViewHostSupplier, context, userContext, transitions, displayController, taskResourceLoader, splitScreenController, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +1 −0 Original line number Diff line number Diff line Loading @@ -1281,6 +1281,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mOpenByDefaultDialog = new OpenByDefaultDialog( mContext, mUserContext, mTransitions, mTaskInfo, mTaskSurface, mDisplayController, Loading