Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f53bf675 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow users to switch from web to app" into main

parents 91e9a6b6 00f53750
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@
    </LinearLayout>

    <LinearLayout
        android:id="@+id/open_in_browser_pill"
        android:id="@+id/open_in_app_or_browser_pill"
        android:layout_width="match_parent"
        android:layout_height="@dimen/desktop_mode_handle_menu_open_in_browser_pill_height"
        android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin"
@@ -178,7 +178,7 @@
        android:background="@drawable/desktop_mode_decor_handle_menu_background">

        <Button
            android:id="@+id/open_in_browser_button"
            android:id="@+id/open_in_app_or_browser_button"
            android:layout_weight="1"
            android:contentDescription="@string/open_in_browser_text"
            android:text="@string/open_in_browser_text"
+2 −0
Original line number Diff line number Diff line
@@ -301,6 +301,8 @@
    <string name="screenshot_text">Screenshot</string>
    <!-- Accessibility text for the handle menu open in browser button [CHAR LIMIT=NONE] -->
    <string name="open_in_browser_text">Open in browser</string>
    <!-- Accessibility text for the handle menu open in app button [CHAR LIMIT=NONE] -->
    <string name="open_in_app_text">Open in App</string>
    <!-- Accessibility text for the handle menu new window button [CHAR LIMIT=NONE] -->
    <string name="new_window_text">New Window</string>
    <!-- Accessibility text for the handle menu new window button [CHAR LIMIT=NONE] -->
+17 −1
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ package com.android.wm.shell.apptoweb

import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_VIEW
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER
import android.content.pm.PackageManager
import android.content.pm.verify.domain.DomainVerificationManager
import android.content.pm.verify.domain.DomainVerificationUserState
@@ -31,7 +33,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup
private const val TAG = "AppToWebUtils"

private val GenericBrowserIntent = Intent()
    .setAction(Intent.ACTION_VIEW)
    .setAction(ACTION_VIEW)
    .addCategory(Intent.CATEGORY_BROWSABLE)
    .setData(Uri.parse("http:"))

@@ -66,6 +68,20 @@ fun getBrowserIntent(uri: Uri, packageManager: PackageManager): Intent? {
    return intent
}

/**
 * Returns intent if there is a non-browser application available to handle the uri. Otherwise,
 * returns null.
 */
fun getAppIntent(uri: Uri, packageManager: PackageManager): Intent? {
    val intent = Intent(ACTION_VIEW, uri).apply {
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER
    }
    // If there is no application available to handle intent, return null
    val component = intent.resolveActivity(packageManager) ?: return null
    intent.setComponent(component)
    return intent
}

/**
 * Returns the [DomainVerificationUserState] of the user associated with the given
 * [DomainVerificationManager] and the given package.
+15 −8
Original line number Diff line number Diff line
@@ -628,13 +628,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin

    @Nullable
    private Intent getBrowserLink() {
        // Do not show browser link in browser applications
        final ComponentName baseActivity = mTaskInfo.baseActivity;
        if (baseActivity != null && AppToWebUtils.isBrowserApp(mContext,
                baseActivity.getPackageName(), mUserContext.getUserId())) {
            return null;
        }

        final Uri browserLink;
        // If the captured link is available and has not expired, return the captured link.
        // Otherwise, return the generic link which is set to null if a generic link is unavailable.
@@ -651,6 +644,18 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin

    }

    @Nullable
    private Intent getAppLink() {
        return mWebUri == null ? null
                : AppToWebUtils.getAppIntent(mWebUri, mContext.getPackageManager());
    }

    private boolean isBrowserApp() {
        final ComponentName baseActivity = mTaskInfo.baseActivity;
        return baseActivity != null && AppToWebUtils.isBrowserApp(mContext,
                baseActivity.getPackageName(), mUserContext.getUserId());
    }

    UserHandle getUser() {
        return mUserContext.getUser();
    }
@@ -1368,6 +1373,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                .shouldShowChangeAspectRatioButton(mTaskInfo);
        final boolean inDesktopImmersive = mDesktopRepository
                .isTaskInFullImmersiveState(mTaskInfo.taskId);
        final boolean isBrowserApp = isBrowserApp();
        mHandleMenu = mHandleMenuFactory.create(
                this,
                mWindowManagerWrapper,
@@ -1379,7 +1385,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                supportsMultiInstance,
                shouldShowManageWindowsButton,
                shouldShowChangeAspectRatioButton,
                getBrowserLink(),
                isBrowserApp,
                isBrowserApp ? getAppLink() : getBrowserLink(),
                mResult.mCaptionWidth,
                mResult.mCaptionHeight,
                mResult.mCaptionX,
+43 −25
Original line number Diff line number Diff line
@@ -41,10 +41,12 @@ import android.widget.ImageView
import android.widget.TextView
import android.window.DesktopModeFlags
import android.window.SurfaceSyncGroup
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.compose.ui.graphics.toArgb
import androidx.core.view.isGone
import com.android.wm.shell.R
import com.android.wm.shell.apptoweb.isBrowserApp
import com.android.wm.shell.shared.split.SplitScreenConstants
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
@@ -73,7 +75,8 @@ class HandleMenu(
    private val shouldShowNewWindowButton: Boolean,
    private val shouldShowManageWindowsButton: Boolean,
    private val shouldShowChangeAspectRatioButton: Boolean,
    private val openInBrowserIntent: Intent?,
    private val isBrowserApp: Boolean,
    private val openInAppOrBrowserIntent: Intent?,
    private val captionWidth: Int,
    private val captionHeight: Int,
    captionX: Int,
@@ -111,7 +114,7 @@ class HandleMenu(
    private val globalMenuPosition: Point = Point()

    private val shouldShowBrowserPill: Boolean
        get() = openInBrowserIntent != null
        get() = openInAppOrBrowserIntent != null

    private val shouldShowMoreActionsPill: Boolean
        get() = SHOULD_SHOW_SCREENSHOT_BUTTON || shouldShowNewWindowButton ||
@@ -128,7 +131,7 @@ class HandleMenu(
        onNewWindowClickListener: () -> Unit,
        onManageWindowsClickListener: () -> Unit,
        onChangeAspectRatioClickListener: () -> Unit,
        openInBrowserClickListener: (Intent) -> Unit,
        openInAppOrBrowserClickListener: (Intent) -> Unit,
        onOpenByDefaultClickListener: () -> Unit,
        onCloseMenuClickListener: () -> Unit,
        onOutsideTouchListener: () -> Unit,
@@ -146,7 +149,7 @@ class HandleMenu(
            onNewWindowClickListener = onNewWindowClickListener,
            onManageWindowsClickListener = onManageWindowsClickListener,
            onChangeAspectRatioClickListener = onChangeAspectRatioClickListener,
            openInBrowserClickListener = openInBrowserClickListener,
            openInAppOrBrowserClickListener = openInAppOrBrowserClickListener,
            onOpenByDefaultClickListener = onOpenByDefaultClickListener,
            onCloseMenuClickListener = onCloseMenuClickListener,
            onOutsideTouchListener = onOutsideTouchListener,
@@ -167,7 +170,7 @@ class HandleMenu(
        onNewWindowClickListener: () -> Unit,
        onManageWindowsClickListener: () -> Unit,
        onChangeAspectRatioClickListener: () -> Unit,
        openInBrowserClickListener: (Intent) -> Unit,
        openInAppOrBrowserClickListener: (Intent) -> Unit,
        onOpenByDefaultClickListener: () -> Unit,
        onCloseMenuClickListener: () -> Unit,
        onOutsideTouchListener: () -> Unit,
@@ -181,7 +184,8 @@ class HandleMenu(
            shouldShowBrowserPill = shouldShowBrowserPill,
            shouldShowNewWindowButton = shouldShowNewWindowButton,
            shouldShowManageWindowsButton = shouldShowManageWindowsButton,
            shouldShowChangeAspectRatioButton = shouldShowChangeAspectRatioButton
            shouldShowChangeAspectRatioButton = shouldShowChangeAspectRatioButton,
            isBrowserApp = isBrowserApp
        ).apply {
            bind(taskInfo, appIconBitmap, appName, shouldShowMoreActionsPill)
            this.onToDesktopClickListener = onToDesktopClickListener
@@ -190,8 +194,8 @@ class HandleMenu(
            this.onNewWindowClickListener = onNewWindowClickListener
            this.onManageWindowsClickListener = onManageWindowsClickListener
            this.onChangeAspectRatioClickListener = onChangeAspectRatioClickListener
            this.onOpenInBrowserClickListener = {
                openInBrowserClickListener.invoke(openInBrowserIntent!!)
            this.onOpenInAppOrBrowserClickListener = {
                openInAppOrBrowserClickListener.invoke(openInAppOrBrowserIntent!!)
            }
            this.onOpenByDefaultClickListener = onOpenByDefaultClickListener
            this.onCloseMenuClickListener = onCloseMenuClickListener
@@ -436,14 +440,15 @@ class HandleMenu(
    /** The view within the Handle Menu, with options to change the windowing mode and more. */
    @SuppressLint("ClickableViewAccessibility")
    class HandleMenuView(
        context: Context,
        private val context: Context,
        menuWidth: Int,
        captionHeight: Int,
        private val shouldShowWindowingPill: Boolean,
        private val shouldShowBrowserPill: Boolean,
        private val shouldShowNewWindowButton: Boolean,
        private val shouldShowManageWindowsButton: Boolean,
        private val shouldShowChangeAspectRatioButton: Boolean
        private val shouldShowChangeAspectRatioButton: Boolean,
        private val isBrowserApp: Boolean
    ) {
        val rootView = LayoutInflater.from(context)
            .inflate(R.layout.desktop_mode_window_decor_handle_menu, null /* root */) as View
@@ -473,11 +478,12 @@ class HandleMenu(
        private val changeAspectRatioBtn = moreActionsPill
            .requireViewById<Button>(R.id.change_aspect_ratio_button)

        // Open in Browser Pill.
        private val openInBrowserPill = rootView.requireViewById<View>(R.id.open_in_browser_pill)
        private val browserBtn = openInBrowserPill.requireViewById<Button>(
            R.id.open_in_browser_button)
        private val openByDefaultBtn = openInBrowserPill.requireViewById<ImageButton>(
        // Open in Browser/App Pill.
        private val openInAppOrBrowserPill = rootView.requireViewById<View>(
            R.id.open_in_app_or_browser_pill)
        private val openInAppOrBrowserBtn = openInAppOrBrowserPill.requireViewById<Button>(
            R.id.open_in_app_or_browser_button)
        private val openByDefaultBtn = openInAppOrBrowserPill.requireViewById<ImageButton>(
            R.id.open_by_default_button)
        private val decorThemeUtil = DecorThemeUtil(context)
        private val animator = HandleMenuAnimator(rootView, menuWidth, captionHeight.toFloat())
@@ -491,7 +497,7 @@ class HandleMenu(
        var onNewWindowClickListener: (() -> Unit)? = null
        var onManageWindowsClickListener: (() -> Unit)? = null
        var onChangeAspectRatioClickListener: (() -> Unit)? = null
        var onOpenInBrowserClickListener: (() -> Unit)? = null
        var onOpenInAppOrBrowserClickListener: (() -> Unit)? = null
        var onOpenByDefaultClickListener: (() -> Unit)? = null
        var onCloseMenuClickListener: (() -> Unit)? = null
        var onOutsideTouchListener: (() -> Unit)? = null
@@ -500,7 +506,7 @@ class HandleMenu(
            fullscreenBtn.setOnClickListener { onToFullscreenClickListener?.invoke() }
            splitscreenBtn.setOnClickListener { onToSplitScreenClickListener?.invoke() }
            desktopBtn.setOnClickListener { onToDesktopClickListener?.invoke() }
            browserBtn.setOnClickListener { onOpenInBrowserClickListener?.invoke() }
            openInAppOrBrowserBtn.setOnClickListener { onOpenInAppOrBrowserClickListener?.invoke() }
            openByDefaultBtn.setOnClickListener {
                onOpenByDefaultClickListener?.invoke()
            }
@@ -536,10 +542,10 @@ class HandleMenu(
            if (shouldShowMoreActionsPill) {
                bindMoreActionsPill(style)
            }
            bindOpenInBrowserPill(style)
            bindOpenInAppOrBrowserPill(style)
        }

        /** Animates the menu opening. */
        /** Animates the menu openInAppOrBrowserg. */
        fun animateOpenMenu() {
            if (taskInfo.isFullscreen || taskInfo.isMultiWindow) {
                animator.animateCaptionHandleExpandToOpen()
@@ -661,13 +667,20 @@ class HandleMenu(
            }
        }

        private fun bindOpenInBrowserPill(style: MenuStyle) {
            openInBrowserPill.apply {
        private fun bindOpenInAppOrBrowserPill(style: MenuStyle) {
            openInAppOrBrowserPill.apply {
                isGone = !shouldShowBrowserPill
                background.setTint(style.backgroundColor)
            }

            browserBtn.apply {
            val btnText = if (isBrowserApp) {
                getString(R.string.open_in_app_text)
            } else {
                getString(R.string.open_in_browser_text)
            }
            openInAppOrBrowserBtn.apply {
                text = btnText
                contentDescription = btnText
                setTextColor(style.textColor)
                compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
            }
@@ -675,6 +688,8 @@ class HandleMenu(
            openByDefaultBtn.imageTintList = ColorStateList.valueOf(style.textColor)
        }

        private fun getString(@StringRes resId: Int): String = context.resources.getString(resId)

        private data class MenuStyle(
            @ColorInt val backgroundColor: Int,
            @ColorInt val textColor: Int,
@@ -709,7 +724,8 @@ interface HandleMenuFactory {
        shouldShowNewWindowButton: Boolean,
        shouldShowManageWindowsButton: Boolean,
        shouldShowChangeAspectRatioButton: Boolean,
        openInBrowserIntent: Intent?,
        isBrowserApp: Boolean,
        openInAppOrBrowserIntent: Intent?,
        captionWidth: Int,
        captionHeight: Int,
        captionX: Int,
@@ -730,7 +746,8 @@ object DefaultHandleMenuFactory : HandleMenuFactory {
        shouldShowNewWindowButton: Boolean,
        shouldShowManageWindowsButton: Boolean,
        shouldShowChangeAspectRatioButton: Boolean,
        openInBrowserIntent: Intent?,
        isBrowserApp: Boolean,
        openInAppOrBrowserIntent: Intent?,
        captionWidth: Int,
        captionHeight: Int,
        captionX: Int,
@@ -747,7 +764,8 @@ object DefaultHandleMenuFactory : HandleMenuFactory {
            shouldShowNewWindowButton,
            shouldShowManageWindowsButton,
            shouldShowChangeAspectRatioButton,
            openInBrowserIntent,
            isBrowserApp,
            openInAppOrBrowserIntent,
            captionWidth,
            captionHeight,
            captionX,
Loading