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

Commit 62f05520 authored by Maurice Lam's avatar Maurice Lam
Browse files

Show error dialog if activity is blocked from streaming

Bug: 203834118
Test: Tested with a virtual device with disallowed activities
Change-Id: I2edf93e3527c261756b52e6ec477e91afc2dd833
parent 4795ed77
Loading
Loading
Loading
Loading
+38 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.app;

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
@@ -35,6 +36,9 @@ public class BlockedAppActivity extends AlertActivity {
    private static final String TAG = "BlockedAppActivity";
    private static final String PACKAGE_NAME = "com.android.internal.app";
    private static final String EXTRA_BLOCKED_PACKAGE = PACKAGE_NAME + ".extra.BLOCKED_PACKAGE";
    private static final String EXTRA_BLOCKED_ACTIVITY_INFO =
            PACKAGE_NAME + ".extra.BLOCKED_ACTIVITY_INFO";
    private static final String EXTRA_STREAMED_DEVICE = PACKAGE_NAME + ".extra.STREAMED_DEVICE";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
@@ -48,17 +52,30 @@ public class BlockedAppActivity extends AlertActivity {
            return;
        }

        CharSequence appLabel = null;
        String packageName = intent.getStringExtra(EXTRA_BLOCKED_PACKAGE);
        if (TextUtils.isEmpty(packageName)) {
            Slog.wtf(TAG, "Invalid package: " + packageName);
        ActivityInfo activityInfo = intent.getParcelableExtra(EXTRA_BLOCKED_ACTIVITY_INFO);
        if (activityInfo != null) {
            appLabel = activityInfo.loadLabel(getPackageManager());
        } else if (!TextUtils.isEmpty(packageName)) {
            appLabel = getAppLabel(userId, packageName);
        }

        if (TextUtils.isEmpty(appLabel)) {
            Slog.wtf(TAG, "Invalid package: " + packageName + " or activity info: " + activityInfo);
            finish();
            return;
        }

        CharSequence appLabel = getAppLabel(userId, packageName);

        CharSequence streamedDeviceName = intent.getCharSequenceExtra(EXTRA_STREAMED_DEVICE);
        if (!TextUtils.isEmpty(streamedDeviceName)) {
            mAlertParams.mTitle = getString(R.string.app_streaming_blocked_title, appLabel);
            mAlertParams.mMessage =
                    getString(R.string.app_streaming_blocked_message, streamedDeviceName);
        } else {
            mAlertParams.mTitle = getString(R.string.app_blocked_title);
            mAlertParams.mMessage = getString(R.string.app_blocked_message, appLabel);
        }
        mAlertParams.mPositiveButtonText = getString(android.R.string.ok);
        setupAlert();
    }
@@ -83,4 +100,19 @@ public class BlockedAppActivity extends AlertActivity {
                .putExtra(Intent.EXTRA_USER_ID, userId)
                .putExtra(EXTRA_BLOCKED_PACKAGE, packageName);
    }

    /**
     * Creates an intent that launches {@link BlockedAppActivity} when app streaming is blocked.
     *
     * Using this method and providing a non-empty {@code streamedDeviceName} will cause the dialog
     * to use streaming-specific error messages.
     */
    public static Intent createStreamingBlockedIntent(int userId, ActivityInfo activityInfo,
            CharSequence streamedDeviceName) {
        return new Intent()
                .setClassName("android", BlockedAppActivity.class.getName())
                .putExtra(Intent.EXTRA_USER_ID, userId)
                .putExtra(EXTRA_BLOCKED_ACTIVITY_INFO, activityInfo)
                .putExtra(EXTRA_STREAMED_DEVICE, streamedDeviceName);
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -5467,6 +5467,15 @@
        <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> is not available right now.
    </string>

    <!-- Title of the dialog shown when an app is blocked from being streamed to a remote device. [CHAR LIMIT=NONE] -->
    <string name="app_streaming_blocked_title"><xliff:g id="activity" example="Permission dialog">%1$s</xliff:g> unavailable</string>
    <!-- Message shown when an app is blocked from being streamed to a remote device. [CHAR LIMIT=NONE] -->
    <string name="app_streaming_blocked_message" product="tv">This can’t be accessed on your <xliff:g id="device" example="Chromebook">%1$s</xliff:g> at this time. Try on your Android TV device instead.</string>
    <!-- Message shown when an app is blocked from being streamed to a remote device. [CHAR LIMIT=NONE] -->
    <string name="app_streaming_blocked_message" product="tablet">This can’t be accessed on your <xliff:g id="device" example="Chromebook">%1$s</xliff:g> at this time. Try on your tablet instead.</string>
    <!-- Message shown when an app is blocked from being streamed to a remote device. [CHAR LIMIT=NONE] -->
    <string name="app_streaming_blocked_message" product="default">This can’t be accessed on your <xliff:g id="device" example="Chromebook">%1$s</xliff:g> at this time. Try on your phone instead.</string>

    <!-- Message displayed in dialog when app is too old to run on this verison of android. [CHAR LIMIT=NONE] -->
    <string name="deprecated_target_sdk_message">This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer.</string>
    <!-- Title for button to see application detail in app store which it came from - it may allow user to update to newer version. [CHAR LIMIT=50] -->
+3 −0
Original line number Diff line number Diff line
@@ -3265,6 +3265,9 @@
  <java-symbol type="string" name="app_blocked_title" />
  <java-symbol type="string" name="app_blocked_message" />

  <java-symbol type="string" name="app_streaming_blocked_title" />
  <java-symbol type="string" name="app_streaming_blocked_message" />

  <!-- Used internally for assistant to launch activity transitions -->
  <java-symbol type="id" name="cross_task_transition" />

+11 −2
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.window.DisplayWindowPolicyController;

import java.util.List;
import java.util.Set;
import java.util.function.Consumer;


/**
@@ -61,6 +62,7 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
    private final ArraySet<ComponentName> mAllowedActivities;
    @Nullable
    private final ArraySet<ComponentName> mBlockedActivities;
    private Consumer<ActivityInfo> mActivityBlockedCallback;

    @NonNull
    final ArraySet<Integer> mRunningUids = new ArraySet<>();
@@ -81,10 +83,12 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
            @NonNull ArraySet<UserHandle> allowedUsers,
            @Nullable Set<ComponentName> allowedActivities,
            @Nullable Set<ComponentName> blockedActivities,
            @NonNull ActivityListener activityListener) {
            @NonNull ActivityListener activityListener,
            @NonNull Consumer<ActivityInfo> activityBlockedCallback) {
        mAllowedUsers = allowedUsers;
        mAllowedActivities = allowedActivities == null ? null : new ArraySet<>(allowedActivities);
        mBlockedActivities = blockedActivities == null ? null : new ArraySet<>(blockedActivities);
        mActivityBlockedCallback = activityBlockedCallback;
        setInterestedWindowFlags(windowFlags, systemWindowFlags);
        mActivityListener = activityListener;
    }
@@ -96,6 +100,7 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
        for (int i = 0; i < activityCount; i++) {
            final ActivityInfo aInfo = activities.get(i);
            if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
                mActivityBlockedCallback.accept(aInfo);
                return false;
            }
        }
@@ -105,7 +110,11 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
    @Override
    public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
            int systemWindowFlags) {
        return canContainActivity(activityInfo, windowFlags, systemWindowFlags);
        if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) {
            mActivityBlockedCallback.accept(activityInfo);
            return false;
        }
        return true;
    }

    @Override
+15 −1
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.PointF;
import android.hardware.display.DisplayManager;
@@ -57,6 +59,7 @@ import android.util.SparseArray;
import android.window.DisplayWindowPolicyController;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.BlockedAppActivity;
import com.android.server.LocalServices;

import java.io.FileDescriptor;
@@ -418,7 +421,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                            getAllowedUserHandles(),
                            mParams.getAllowedActivities(),
                            mParams.getBlockedActivities(),
                            createListenerAdapter(displayId));
                            createListenerAdapter(displayId),
                            activityInfo -> onActivityBlocked(displayId, activityInfo));
            mWindowPolicyControllers.put(displayId, dwpc);
            return dwpc;
        }
@@ -441,6 +445,16 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        }
    }

    private void onActivityBlocked(int displayId, ActivityInfo activityInfo) {
        Intent intent = BlockedAppActivity.createStreamingBlockedIntent(
                UserHandle.getUserId(activityInfo.applicationInfo.uid), activityInfo,
                mAssociationInfo.getDisplayName());
        mContext.startActivityAsUser(
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
                ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(),
                mContext.getUser());
    }

    private ArraySet<UserHandle> getAllowedUserHandles() {
        ArraySet<UserHandle> result = new ArraySet<>();
        DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);