diff options
5 files changed, 76 insertions, 9 deletions
diff --git a/core/java/com/android/internal/app/BlockedAppActivity.java b/core/java/com/android/internal/app/BlockedAppActivity.java index fbdbbfb06b78..65526eba3e54 100644 --- a/core/java/com/android/internal/app/BlockedAppActivity.java +++ b/core/java/com/android/internal/app/BlockedAppActivity.java @@ -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); - - mAlertParams.mTitle = getString(R.string.app_blocked_title); - mAlertParams.mMessage = getString(R.string.app_blocked_message, appLabel); + 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); + } } diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 59ad302c8aee..996a13370426 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -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] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6ae2829124b7..4faee4382f4d 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -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" /> diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index 75acf81a4a3c..bb49ba059d23 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -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 diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 95b9e58a9dfd..98a5ec1c3681 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -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); |