Merge "Roll forward "Show error dialog if activity is blocked from streaming""
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* A dialog shown to the user when they try to launch an app that is not allowed on a virtual
|
||||
* device. The intent to start this activity must be created with the static factory method provided
|
||||
* below.
|
||||
*/
|
||||
public class BlockedAppStreamingActivity extends AlertActivity {
|
||||
|
||||
private static final String TAG = "BlockedAppStreamingActivity";
|
||||
private static final String PACKAGE_NAME = "com.android.internal.app";
|
||||
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) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
CharSequence appLabel = null;
|
||||
ActivityInfo activityInfo = intent.getParcelableExtra(EXTRA_BLOCKED_ACTIVITY_INFO);
|
||||
if (activityInfo != null) {
|
||||
appLabel = activityInfo.loadLabel(getPackageManager());
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(appLabel)) {
|
||||
Slog.wtf(TAG, "Invalid activity info: " + activityInfo);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an intent that launches {@link BlockedAppStreamingActivity} when app streaming is
|
||||
* blocked.
|
||||
*/
|
||||
public static Intent createIntent(ActivityInfo activityInfo, CharSequence streamedDeviceName) {
|
||||
return new Intent()
|
||||
.setClassName("android", BlockedAppStreamingActivity.class.getName())
|
||||
.putExtra(EXTRA_BLOCKED_ACTIVITY_INFO, activityInfo)
|
||||
.putExtra(EXTRA_STREAMED_DEVICE, streamedDeviceName);
|
||||
}
|
||||
}
|
||||
@@ -6591,6 +6591,12 @@
|
||||
android:process=":ui">
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.android.internal.app.BlockedAppStreamingActivity"
|
||||
android:theme="@style/Theme.Dialog.Confirmation"
|
||||
android:excludeFromRecents="true"
|
||||
android:process=":ui">
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.android.internal.app.LaunchAfterAuthenticationActivity"
|
||||
android:theme="@style/Theme.Translucent.NoTitleBar"
|
||||
android:excludeFromRecents="true"
|
||||
|
||||
@@ -5469,6 +5469,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] -->
|
||||
|
||||
@@ -3288,6 +3288,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" />
|
||||
|
||||
|
||||
@@ -37,8 +37,11 @@ import android.util.Slog;
|
||||
import android.view.Display;
|
||||
import android.window.DisplayWindowPolicyController;
|
||||
|
||||
import com.android.internal.app.BlockedAppStreamingActivity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
@@ -48,6 +51,9 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
|
||||
|
||||
private static final String TAG = "VirtualDeviceManager";
|
||||
|
||||
private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT =
|
||||
new ComponentName("android", BlockedAppStreamingActivity.class.getName());
|
||||
|
||||
/**
|
||||
* If required, allow the secure activity to display on remote device since
|
||||
* {@link android.os.Build.VERSION_CODES#TIRAMISU}.
|
||||
@@ -61,6 +67,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 +88,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 +105,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 +115,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
|
||||
@@ -140,22 +154,23 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
|
||||
if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
|
||||
return false;
|
||||
}
|
||||
ComponentName activityComponent = activityInfo.getComponentName();
|
||||
if (BLOCKED_APP_STREAMING_COMPONENT.equals(activityComponent)) {
|
||||
// The error dialog alerting users that streaming is blocked is always allowed.
|
||||
return true;
|
||||
}
|
||||
final UserHandle activityUser =
|
||||
UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid);
|
||||
if (!mAllowedUsers.contains(activityUser)) {
|
||||
Slog.d(TAG, "Virtual device activity not allowed from user " + activityUser);
|
||||
return false;
|
||||
}
|
||||
if (mBlockedActivities != null
|
||||
&& mBlockedActivities.contains(activityInfo.getComponentName())) {
|
||||
Slog.d(TAG,
|
||||
"Virtual device blocking launch of " + activityInfo.getComponentName());
|
||||
if (mBlockedActivities != null && mBlockedActivities.contains(activityComponent)) {
|
||||
Slog.d(TAG, "Virtual device blocking launch of " + activityComponent);
|
||||
return false;
|
||||
}
|
||||
if (mAllowedActivities != null
|
||||
&& !mAllowedActivities.contains(activityInfo.getComponentName())) {
|
||||
Slog.d(TAG,
|
||||
activityInfo.getComponentName() + " is not in the allowed list.");
|
||||
if (mAllowedActivities != null && !mAllowedActivities.contains(activityComponent)) {
|
||||
Slog.d(TAG, activityComponent + " is not in the allowed list.");
|
||||
return false;
|
||||
}
|
||||
if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
|
||||
|
||||
@@ -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.window.DisplayWindowPolicyController;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.BlockedAppStreamingActivity;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -441,7 +444,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;
|
||||
}
|
||||
@@ -464,6 +468,15 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void onActivityBlocked(int displayId, ActivityInfo activityInfo) {
|
||||
Intent intent = BlockedAppStreamingActivity.createIntent(
|
||||
activityInfo, mAssociationInfo.getDisplayName());
|
||||
mContext.startActivityAsUser(
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
|
||||
ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(),
|
||||
mContext.getUser());
|
||||
}
|
||||
|
||||
private ArraySet<UserHandle> getAllowedUserHandles() {
|
||||
ArraySet<UserHandle> result = new ArraySet<>();
|
||||
DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
|
||||
|
||||
Reference in New Issue
Block a user