Merge "Ensure notif-based bubbles don't occur once and for all!! & improve logging" into qt-dev
am: 6494b52f39
Change-Id: I4bb62d53512fd115be4b5b4facc5bc07809b4aed
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.bubbles;
|
package com.android.systemui.bubbles;
|
||||||
|
|
||||||
|
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
|
||||||
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
|
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
|
||||||
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
|
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
|
||||||
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
|
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
|
||||||
@@ -41,7 +42,9 @@ import android.app.ActivityTaskManager;
|
|||||||
import android.app.IActivityTaskManager;
|
import android.app.IActivityTaskManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ParceledListSlice;
|
import android.content.pm.ParceledListSlice;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -112,7 +115,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
public static final int MAX_BUBBLES = 5; // TODO: actually enforce this
|
public static final int MAX_BUBBLES = 5; // TODO: actually enforce this
|
||||||
|
|
||||||
// Enables some subset of notifs to automatically become bubbles
|
// Enables some subset of notifs to automatically become bubbles
|
||||||
private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
|
public static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
|
||||||
|
|
||||||
/** Flag to enable or disable the entire feature */
|
/** Flag to enable or disable the entire feature */
|
||||||
private static final String ENABLE_BUBBLES = "experiment_enable_bubbles";
|
private static final String ENABLE_BUBBLES = "experiment_enable_bubbles";
|
||||||
@@ -450,7 +453,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (!areBubblesEnabled(mContext)) {
|
if (!areBubblesEnabled(mContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
|
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
|
||||||
|
&& canLaunchInActivityView(mContext, entry)) {
|
||||||
updateShowInShadeForSuppressNotification(entry);
|
updateShowInShadeForSuppressNotification(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,7 +464,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (!areBubblesEnabled(mContext)) {
|
if (!areBubblesEnabled(mContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
|
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
|
||||||
|
&& canLaunchInActivityView(mContext, entry)) {
|
||||||
updateBubble(entry);
|
updateBubble(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,7 +475,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (!areBubblesEnabled(mContext)) {
|
if (!areBubblesEnabled(mContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry);
|
boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
|
||||||
|
&& canLaunchInActivityView(mContext, entry);
|
||||||
if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
|
if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
|
||||||
// It was previously a bubble but no longer a bubble -- lets remove it
|
// It was previously a bubble but no longer a bubble -- lets remove it
|
||||||
removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
|
removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
|
||||||
@@ -663,12 +669,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|| autoBubbleAll;
|
|| autoBubbleAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldAutoExpand(NotificationEntry entry) {
|
|
||||||
Notification.BubbleMetadata metadata = entry.getBubbleMetadata();
|
|
||||||
return metadata != null && metadata.getAutoExpandBubble()
|
|
||||||
&& isForegroundApp(mContext, entry.notification.getPackageName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateShowInShadeForSuppressNotification(NotificationEntry entry) {
|
private void updateShowInShadeForSuppressNotification(NotificationEntry entry) {
|
||||||
boolean suppressNotification = entry.getBubbleMetadata() != null
|
boolean suppressNotification = entry.getBubbleMetadata() != null
|
||||||
&& entry.getBubbleMetadata().isNotificationSuppressed()
|
&& entry.getBubbleMetadata().isNotificationSuppressed()
|
||||||
@@ -785,6 +785,48 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
(int) (defaultBounciness * 100)) / 100f;
|
(int) (defaultBounciness * 100)) / 100f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
|
||||||
|
*
|
||||||
|
* Keep checks in sync with NotificationManagerService#canLaunchInActivityView. Typically
|
||||||
|
* that should filter out any invalid bubbles, but should protect SysUI side just in case.
|
||||||
|
*
|
||||||
|
* @param context the context to use.
|
||||||
|
* @param entry the entry to bubble.
|
||||||
|
*/
|
||||||
|
static boolean canLaunchInActivityView(Context context, NotificationEntry entry) {
|
||||||
|
PendingIntent intent = entry.getBubbleMetadata() != null
|
||||||
|
? entry.getBubbleMetadata().getIntent()
|
||||||
|
: null;
|
||||||
|
if (intent == null) {
|
||||||
|
Log.w(TAG, "Unable to create bubble -- no intent");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ActivityInfo info =
|
||||||
|
intent.getIntent().resolveActivityInfo(context.getPackageManager(), 0);
|
||||||
|
if (info == null) {
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- couldn't find activity info for intent: "
|
||||||
|
+ intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ActivityInfo.isResizeableMode(info.resizeMode)) {
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- activity is not resizable for intent: "
|
||||||
|
+ intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
|
||||||
|
+ "for intent: " + intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
|
||||||
|
+ intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** PinnedStackListener that dispatches IME visibility updates to the stack. */
|
/** PinnedStackListener that dispatches IME visibility updates to the stack. */
|
||||||
private class BubblesImeListener extends IPinnedStackListener.Stub {
|
private class BubblesImeListener extends IPinnedStackListener.Stub {
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,10 @@
|
|||||||
|
|
||||||
package com.android.systemui.bubbles;
|
package com.android.systemui.bubbles;
|
||||||
|
|
||||||
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
|
|
||||||
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
|
|
||||||
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
|
|
||||||
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
|
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
|
|
||||||
|
import static com.android.systemui.bubbles.BubbleController.DEBUG_ENABLE_AUTO_BUBBLE;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
import android.app.ActivityView;
|
import android.app.ActivityView;
|
||||||
@@ -30,7 +28,6 @@ import android.app.Notification;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -357,7 +354,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
|
|||||||
}
|
}
|
||||||
setContentVisibility(false);
|
setContentVisibility(false);
|
||||||
mActivityView.setVisibility(VISIBLE);
|
mActivityView.setVisibility(VISIBLE);
|
||||||
} else {
|
} else if (DEBUG_ENABLE_AUTO_BUBBLE) {
|
||||||
// Hide activity view if we had it previously
|
// Hide activity view if we had it previously
|
||||||
mActivityView.setVisibility(GONE);
|
mActivityView.setVisibility(GONE);
|
||||||
mNotifRow = mEntry.getRow();
|
mNotifRow = mEntry.getRow();
|
||||||
@@ -552,58 +549,13 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
|
|||||||
@Nullable
|
@Nullable
|
||||||
private PendingIntent getBubbleIntent(NotificationEntry entry) {
|
private PendingIntent getBubbleIntent(NotificationEntry entry) {
|
||||||
Notification notif = entry.notification.getNotification();
|
Notification notif = entry.notification.getNotification();
|
||||||
String packageName = entry.notification.getPackageName();
|
|
||||||
Notification.BubbleMetadata data = notif.getBubbleMetadata();
|
Notification.BubbleMetadata data = notif.getBubbleMetadata();
|
||||||
if (data != null && canLaunchInActivityView(data.getIntent(), true /* enableLogging */,
|
if (BubbleController.canLaunchInActivityView(mContext, entry) && data != null) {
|
||||||
packageName)) {
|
|
||||||
return data.getIntent();
|
return data.getIntent();
|
||||||
} else if (BubbleController.shouldUseContentIntent(mContext)
|
|
||||||
&& canLaunchInActivityView(notif.contentIntent, false /* enableLogging */,
|
|
||||||
packageName)) {
|
|
||||||
return notif.contentIntent;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
|
|
||||||
*
|
|
||||||
* @param intent the pending intent of the bubble.
|
|
||||||
* @param enableLogging whether bubble developer error should be logged.
|
|
||||||
* @param packageName the notification package name for this bubble.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean canLaunchInActivityView(PendingIntent intent, boolean enableLogging,
|
|
||||||
String packageName) {
|
|
||||||
if (intent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ActivityInfo info =
|
|
||||||
intent.getIntent().resolveActivityInfo(mContext.getPackageManager(), 0);
|
|
||||||
if (info == null) {
|
|
||||||
if (enableLogging) {
|
|
||||||
StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
|
|
||||||
BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!ActivityInfo.isResizeableMode(info.resizeMode)) {
|
|
||||||
if (enableLogging) {
|
|
||||||
StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
|
|
||||||
BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
|
|
||||||
if (enableLogging) {
|
|
||||||
StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
|
|
||||||
BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener that is notified when a bubble is blocked.
|
* Listener that is notified when a bubble is blocked.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE;
|
|||||||
import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
|
import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
|
||||||
import static android.content.Context.BIND_AUTO_CREATE;
|
import static android.content.Context.BIND_AUTO_CREATE;
|
||||||
import static android.content.Context.BIND_FOREGROUND_SERVICE;
|
import static android.content.Context.BIND_FOREGROUND_SERVICE;
|
||||||
|
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
|
||||||
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
|
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
|
||||||
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
|
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
|
||||||
import static android.content.pm.PackageManager.MATCH_ALL;
|
import static android.content.pm.PackageManager.MATCH_ALL;
|
||||||
@@ -82,6 +83,9 @@ import static android.service.notification.NotificationListenerService.REASON_UN
|
|||||||
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
|
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
|
||||||
import static android.service.notification.NotificationListenerService.TRIM_FULL;
|
import static android.service.notification.NotificationListenerService.TRIM_FULL;
|
||||||
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
|
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
|
||||||
|
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
|
||||||
|
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
|
||||||
|
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
|
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
|
||||||
|
|
||||||
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
|
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
|
||||||
@@ -131,6 +135,7 @@ import android.content.ContentResolver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -197,6 +202,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
import android.util.StatsLog;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
import android.util.proto.ProtoOutputStream;
|
import android.util.proto.ProtoOutputStream;
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
@@ -4821,9 +4827,12 @@ public class NotificationManagerService extends SystemService {
|
|||||||
private boolean isNotificationAppropriateToBubble(NotificationRecord r, String pkg, int userId,
|
private boolean isNotificationAppropriateToBubble(NotificationRecord r, String pkg, int userId,
|
||||||
NotificationRecord oldRecord) {
|
NotificationRecord oldRecord) {
|
||||||
Notification notification = r.getNotification();
|
Notification notification = r.getNotification();
|
||||||
|
Notification.BubbleMetadata metadata = notification.getBubbleMetadata();
|
||||||
|
boolean intentCanBubble = metadata != null
|
||||||
|
&& canLaunchInActivityView(getContext(), metadata.getIntent(), pkg);
|
||||||
|
|
||||||
// Does the app want to bubble & is able to bubble
|
// Does the app want to bubble & is able to bubble
|
||||||
boolean canBubble = notification.getBubbleMetadata() != null
|
boolean canBubble = intentCanBubble
|
||||||
&& mPreferencesHelper.areBubblesAllowed(pkg, userId)
|
&& mPreferencesHelper.areBubblesAllowed(pkg, userId)
|
||||||
&& mPreferencesHelper.bubblesEnabled(r.sbn.getUser())
|
&& mPreferencesHelper.bubblesEnabled(r.sbn.getUser())
|
||||||
&& r.getChannel().canBubble()
|
&& r.getChannel().canBubble()
|
||||||
@@ -4869,6 +4878,63 @@ public class NotificationManagerService extends SystemService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
|
||||||
|
*
|
||||||
|
* @param context the context to use.
|
||||||
|
* @param pendingIntent the pending intent of the bubble.
|
||||||
|
* @param packageName the notification package name for this bubble.
|
||||||
|
*/
|
||||||
|
// Keep checks in sync with BubbleController#canLaunchInActivityView.
|
||||||
|
@VisibleForTesting
|
||||||
|
protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
|
||||||
|
String packageName) {
|
||||||
|
if (pendingIntent == null) {
|
||||||
|
Log.w(TAG, "Unable to create bubble -- no intent");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need escalated privileges to get the intent.
|
||||||
|
final long token = Binder.clearCallingIdentity();
|
||||||
|
Intent intent;
|
||||||
|
try {
|
||||||
|
intent = pendingIntent.getIntent();
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityInfo info = intent != null
|
||||||
|
? intent.resolveActivityInfo(context.getPackageManager(), 0)
|
||||||
|
: null;
|
||||||
|
if (info == null) {
|
||||||
|
StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
|
||||||
|
BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING);
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- couldn't find activity info for intent: "
|
||||||
|
+ intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ActivityInfo.isResizeableMode(info.resizeMode)) {
|
||||||
|
StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
|
||||||
|
BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE);
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- activity is not resizable for intent: "
|
||||||
|
+ intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
|
||||||
|
StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
|
||||||
|
BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS);
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
|
||||||
|
+ "for intent: " + intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
|
||||||
|
Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
|
||||||
|
+ intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void doChannelWarningToast(CharSequence toastText) {
|
private void doChannelWarningToast(CharSequence toastText) {
|
||||||
Binder.withCleanCallingIdentity(() -> {
|
Binder.withCleanCallingIdentity(() -> {
|
||||||
final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
|
final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
|
||||||
|
|||||||
@@ -30,12 +30,14 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
|
<uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
||||||
|
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
|
||||||
|
|
||||||
<application android:debuggable="true">
|
<application android:debuggable="true">
|
||||||
<uses-library android:name="android.test.runner" />
|
<uses-library android:name="android.test.runner" />
|
||||||
|
|
||||||
<provider android:name=".DummyProvider"
|
<provider android:name=".DummyProvider"
|
||||||
android:authorities="com.android.services.uitests" />
|
android:authorities="com.android.services.uitests" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<instrumentation
|
<instrumentation
|
||||||
|
|||||||
@@ -304,6 +304,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
void onGranted(ComponentName assistant, int userId, boolean granted);
|
void onGranted(ComponentName assistant, int userId, boolean granted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
|
||||||
|
String packageName) {
|
||||||
|
// Tests for this not being true are in CTS NotificationManagerTest
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestableToastCallback extends ITransientNotification.Stub {
|
private class TestableToastCallback extends ITransientNotification.Stub {
|
||||||
|
|||||||
Reference in New Issue
Block a user