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

Commit 39e62e94 authored by Anthony Alridge's avatar Anthony Alridge
Browse files

Use mini-resolver instead of alert dialog for dialer work telephony

We previously showed an alert dialog when redirecting the user to the
work profile due to telephony being unavailable. This resulted in some
inconsistent UIs, with the user sometimes seing the mini-resolver,
sometimes seeing this dialog depending on what journey they use
to make a phone call. This CL introduces consistency for the call
case by redirecting to the intent forwarder when the user
attempts to make a call in the primary profile, with telephony only
available in the work profile.

The previous dialog is modified to handle the error case when there
is no dialer app to switch to in work, directing the user to install
an app instead.

A follow-up CL will address the case of ensuring messages show the
mini-resolver.

Tested manually, screenshots show that the mini-resolver is shown
for both text and call in contacts app (previously calls would show
the dialog).

Bug: 271819927
Test: Manually, see screenshots in bug
Change-Id: I98df65ab0a4a8acea41f2dc9581a07452f324539
parent b7a3e01b
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -1851,9 +1851,54 @@ public final class DevicePolicyResources {
            public static final String WORK_PROFILE_TELEPHONY_PAUSED_TURN_ON_BUTTON =
                    PREFIX + "TURN_ON_WORK_PROFILE_BUTTON_TEXT";

            /**
             * Information section shown on a dialog when the user is unable to place a call in
             * the personal profile due to admin restrictions, and must choose whether to place
             * the call from the work profile or cancel.
             */
            public static final String MINIRESOLVER_WORK_TELEPHONY_CALL_BLOCKED_INFORMATION =
                    PREFIX + "MINIRESOLVER_WORK_TELEPHONY_INFORMATION";

            /**
             * Information section shown on a dialog when the user is unable to send a text in
             * the personal profile due to admin restrictions, and must choose whether to place
             * the call from the work profile or cancel.
             */
            public static final String MINIRESOLVER_WORK_TELEPHONY_TEXT_BLOCKED_INFORMATION =
                    PREFIX + "MINIRESOLVER_WORK_TELEPHONY_INFORMATION";


            /**
             * Button for a dialog shown when the user is unable to place a call in the personal
             * profile due to admin restrictions, and must choose whether to place the call from
             * the work profile or cancel.
             */
            public static final String MINIRESOLVER_CALL_FROM_WORK =
                    PREFIX + "MINIRESOLVER_CALL_FROM_WORK";

            /**
             * Button for a dialog shown when the user has no apps capable of handling an intent
             * in the personal profile, and must choose whether to open the intent in a
             * cross-profile app in the work profile, or cancel.
             */
            public static final String MINIRESOLVER_SWITCH_TO_WORK =
                    PREFIX + "MINIRESOLVER_SWITCH_TO_WORK";

            /**
             * Title for a dialog shown when the user has no apps capable of handling an intent
             * in the personal profile, and must choose whether to open the intent in a
             * cross-profile app in the work profile, or open in the same profile browser. Accepts
             * the app name as a param.
             */
            public static final String MINIRESOLVER_OPEN_IN_WORK =
                    PREFIX + "MINIRESOLVER_OPEN_IN_WORK";

            /**
             * Title for a dialog shown when the user has no apps capable of handling an intent
             * in the personal profile, and must choose whether to open the intent in a
             * cross-profile app in the personal profile, or open in the same profile browser.
             * Accepts the app name as a param.
             */
            public static final String MINIRESOLVER_OPEN_IN_PERSONAL =
                    PREFIX + "MINIRESOLVER_OPEN_IN_PERSONAL";

+92 −4
Original line number Diff line number Diff line
@@ -19,7 +19,11 @@ package com.android.internal.app;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.app.admin.DevicePolicyResources.Strings.Core.FORWARD_INTENT_TO_PERSONAL;
import static android.app.admin.DevicePolicyResources.Strings.Core.FORWARD_INTENT_TO_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.MINIRESOLVER_CALL_FROM_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.MINIRESOLVER_OPEN_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.MINIRESOLVER_SWITCH_TO_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.MINIRESOLVER_WORK_TELEPHONY_CALL_BLOCKED_INFORMATION;
import static android.app.admin.DevicePolicyResources.Strings.Core.MINIRESOLVER_WORK_TELEPHONY_TEXT_BLOCKED_INFORMATION;
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

@@ -32,6 +36,7 @@ import android.app.Activity;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.app.admin.ManagedSubscriptionsPolicy;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -41,6 +46,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.metrics.LogMaker;
import android.os.Build;
import android.os.Bundle;
@@ -48,6 +54,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.util.Slog;
import android.view.View;
import android.widget.Button;
@@ -203,35 +210,116 @@ public class IntentForwarderActivity extends Activity {

        findViewById(R.id.title_container).setElevation(0);

        ImageView icon = findViewById(R.id.icon);
        PackageManager packageManagerForTargetUser =
                createContextAsUser(UserHandle.of(targetUserId), /* flags= */ 0)
                        .getPackageManager();
        icon.setImageDrawable(target.loadIcon(packageManagerForTargetUser));

        ImageView icon = findViewById(R.id.icon);
        icon.setImageDrawable(
                getAppIcon(target, launchIntent, targetUserId, packageManagerForTargetUser));

        View buttonContainer = findViewById(R.id.button_bar_container);
        buttonContainer.setPadding(0, 0, 0, buttonContainer.getPaddingBottom());

        ((TextView) findViewById(R.id.open_cross_profile)).setText(
                getOpenInWorkMessage(target.loadLabel(packageManagerForTargetUser)));
                getOpenInWorkMessage(launchIntent, target.loadLabel(packageManagerForTargetUser)));

        // The mini-resolver's negative button is reused in this flow to cancel the intent
        ((Button) findViewById(R.id.use_same_profile_browser)).setText(R.string.cancel);
        findViewById(R.id.use_same_profile_browser).setOnClickListener(v -> finish());

        ((Button) findViewById(R.id.button_open)).setText(getOpenInWorkButtonString(launchIntent));
        findViewById(R.id.button_open).setOnClickListener(v -> {
            startActivityAsCaller(launchIntent, targetUserId);
            finish();
        });


        View telephonyInfo = findViewById(R.id.miniresolver_info_section);
        DevicePolicyManager devicePolicyManager =
                getSystemService(DevicePolicyManager.class);
        // Additional information section is work telephony specific. Therefore, it is only shown
        // for telephony related intents, when all sim subscriptions are in the work profile.
        if ((isDialerIntent(launchIntent) || isTextMessageIntent(launchIntent))
                && devicePolicyManager.getManagedSubscriptionsPolicy().getPolicyType()
                    == ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS) {
            telephonyInfo.setVisibility(View.VISIBLE);
            ((TextView) findViewById(R.id.miniresolver_info_section_text))
                    .setText(getWorkTelephonyInfoSectionMessage(launchIntent));
        } else {
            telephonyInfo.setVisibility(View.GONE);
        }
    }

    private Drawable getAppIcon(
            ResolveInfo target,
            Intent launchIntent,
            int targetUserId,
            PackageManager packageManagerForTargetUser) {
        if (isDialerIntent(launchIntent)) {
            // The icon for the call intent will be a generic phone icon as the target will be
            // the telecom call handler. From the user's perspective, they are being directed
            // to the dialer app, so use the icon from that app instead.
            TelecomManager telecomManager =
                    getApplicationContext().getSystemService(TelecomManager.class);
            String defaultDialerPackageName =
                    telecomManager.getDefaultDialerPackage(UserHandle.of(targetUserId));
            try {
                return packageManagerForTargetUser
                        .getApplicationInfo(defaultDialerPackageName, /* flags= */ 0)
                        .loadIcon(packageManagerForTargetUser);
            } catch (PackageManager.NameNotFoundException e) {
                // Allow to fall-through to the icon from the target if we can't find the default
                // dialer icon.
                Slog.w(TAG, "Cannot load icon for default dialer package");
            }
        }
        return target.loadIcon(packageManagerForTargetUser);
    }

    private int getOpenInWorkButtonString(Intent launchIntent) {
        if (isDialerIntent(launchIntent)) {
            return R.string.miniresolver_call;
        }
        if (isTextMessageIntent(launchIntent)) {
            return R.string.miniresolver_switch;
        }
        return R.string.whichViewApplicationLabel;
    }

    private String getOpenInWorkMessage(CharSequence targetLabel) {
    private String getOpenInWorkMessage(Intent launchIntent, CharSequence targetLabel) {
        if (isDialerIntent(launchIntent)) {
            return getSystemService(DevicePolicyManager.class).getResources().getString(
                MINIRESOLVER_CALL_FROM_WORK,
                () -> getString(R.string.miniresolver_call_in_work));
        }
        if (isTextMessageIntent(launchIntent)) {
            return getSystemService(DevicePolicyManager.class).getResources().getString(
                    MINIRESOLVER_SWITCH_TO_WORK,
                    () -> getString(R.string.miniresolver_switch_to_work));
        }
        return getSystemService(DevicePolicyManager.class).getResources().getString(
                MINIRESOLVER_OPEN_WORK,
                () -> getString(R.string.miniresolver_open_work, targetLabel),
                targetLabel);
    }

    private String getWorkTelephonyInfoSectionMessage(Intent launchIntent) {
        if (isDialerIntent(launchIntent)) {
            return getSystemService(DevicePolicyManager.class).getResources().getString(
                MINIRESOLVER_WORK_TELEPHONY_CALL_BLOCKED_INFORMATION,
                () -> getString(R.string.miniresolver_call_information));
        }
        if (isTextMessageIntent(launchIntent)) {
            return getSystemService(DevicePolicyManager.class).getResources().getString(
                MINIRESOLVER_WORK_TELEPHONY_TEXT_BLOCKED_INFORMATION,
                () -> getString(R.string.miniresolver_sms_information));
        }
        return "";
    }



    private String getForwardToPersonalMessage() {
        return getSystemService(DevicePolicyManager.class).getResources().getString(
                FORWARD_INTENT_TO_PERSONAL,
+32 −1
Original line number Diff line number Diff line
@@ -63,6 +63,37 @@
            android:textColor="?android:textColorPrimary"
        />
    </RelativeLayout>
    <!-- Additional information section, currently only shown when redirecting to Telephony apps -->
    <LinearLayout
      android:id="@+id/miniresolver_info_section"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:paddingHorizontal="24dp"
      android:paddingBottom="48dp"
      android:visibility="gone"
      android:background="?attr/colorBackground"
      android:orientation="horizontal">

      <ImageView
          android:id="@+id/miniresolver_info_section_icon"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:paddingEnd="8dp"
          android:src="@drawable/ic_info_outline_24"
          android:tint="?android:textColorSecondary"
      />

      <TextView
          android:id="@+id/miniresolver_info_section_text"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentEnd="true"
          android:paddingEnd="8dp"
          android:textSize="14sp"
          android:textAllCaps="false"
          android:textColor="?android:textColorSecondary"
          />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/button_bar_container"
@@ -83,7 +114,7 @@
            android:orientation="horizontal"
            android:layoutDirection="locale"
            android:measureWithLargestChild="true"
            android:paddingHorizontal="16dp"
            android:layout_marginHorizontal="24dp"
            android:paddingBottom="2dp"
            android:elevation="@dimen/resolver_elevation">

+16 −2
Original line number Diff line number Diff line
@@ -861,10 +861,10 @@
    <!-- "Switch" is a verb; it means to change user profile by tapping another user profile name. -->
    <string name="managed_profile_label">Switch to work profile</string>

    <!-- "Switch" is a verb; it means to change user profile by tapping another user profile name. -->
    <!-- "Switch" is a verb; it means to change user profile by switching to an app in the personal profile. -->
    <string name="user_owner_app_label">Switch to personal <xliff:g id="app_name" example="Gmail">%1$s</xliff:g></string>

    <!-- "Switch" is a verb; it means to change user profile by tapping another user profile name. -->
    <!-- "Switch" is a verb; it means to change user profile by switching to an app in the work profile. -->
    <string name="managed_profile_app_label">Switch to work <xliff:g id="app_name" example="Gmail">%1$s</xliff:g></string>

    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
@@ -5918,10 +5918,24 @@
    <string name="miniresolver_open_in_personal">Open in personal <xliff:g id="app" example="YouTube">%s</xliff:g>?</string>
    <!-- Dialog title. User must choose between opening content in a cross-profile app or same-profile browser. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_open_in_work">Open in work <xliff:g id="app" example="YouTube">%s</xliff:g>?</string>
    <!-- Dialog title. User must place the phone call in the other profile, or cancel. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_call_in_work">Call from work app?</string>
    <!-- Dialog title. User much choose between opening content in a cross-profile app or cancelling. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_switch_to_work">Switch to work app?</string>
    <!-- Dialog text.  Shown when the user is unable to make a phone call from a personal app due to restrictions set
         by their organization, and so must switch to a work app or cancel. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_call_information">Your organization only allows you to make calls from work apps</string>
    <!-- Dialog text.  Shown when the user is unable to send a text message from a personal app due to restrictions set
         by their organization, and so must switch to a work app or cancel. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_sms_information">Your organization only allows you to send messages from work apps</string>
    <!-- Button option. Open the link in the personal browser. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_use_personal_browser">Use personal browser</string>
    <!-- Button option. Open the link in the work browser. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_use_work_browser">Use work browser</string>
    <!-- Button option. Action to place a phone call. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_call">Call</string>
    <!-- Button option. Action to open an app in the work profile. [CHAR LIMIT=NONE] -->
    <string name="miniresolver_switch">Switch</string>

    <!-- Icc depersonalization related strings -->
    <!-- Label text for PIN entry widget on SIM Network Depersonalization panel [CHAR LIMIT=none] -->
+8 −0
Original line number Diff line number Diff line
@@ -1579,6 +1579,14 @@
  <java-symbol type="string" name="miniresolver_open_work" />
  <java-symbol type="string" name="miniresolver_use_personal_browser" />
  <java-symbol type="string" name="miniresolver_use_work_browser" />
  <java-symbol type="string" name="miniresolver_call_in_work" />
  <java-symbol type="string" name="miniresolver_switch_to_work" />
  <java-symbol type="string" name="miniresolver_call" />
  <java-symbol type="string" name="miniresolver_switch" />
  <java-symbol type="string" name="miniresolver_call_information" />
  <java-symbol type="string" name="miniresolver_sms_information" />
  <java-symbol type="id" name="miniresolver_info_section" />
  <java-symbol type="id" name="miniresolver_info_section_text" />
  <java-symbol type="id" name="button_open" />
  <java-symbol type="id" name="use_same_profile_browser" />

Loading