Support the toast Window to show on the secondary display.

1) Looking for the specific display when add a toast window.

2) Modify the enqueueToast interface to support the toast with
   specific dispaly Id.
   2.1 Toast get the specific display id from context.
   2.1 Toast use the new interface with display id to communicate with
       the Notification manager servcie.

3) Support to add/remove toast window token according to the displayId.

Bug: 80001975
Test: atest WindowManagerSmokeTest ActivityManagerMultiDisplayTests
Test: atest android.widget.cts.ToastTest
Test: manual, use ActivityView & launch a toast testing app in virtual
      display
      1. Make a toast.
      2. Verify the toast if show on the virtual display

Change-Id: I3a95c291af647ed9c6e966b2a90924097df19b6a
This commit is contained in:
Jeff Chang
2018-08-09 16:31:59 +08:00
parent 5293635e21
commit 48ecef4bfb
7 changed files with 28 additions and 24 deletions

View File

@@ -671,7 +671,7 @@ Landroid/app/INotificationManager;->areNotificationsEnabledForPackage(Ljava/lang
Landroid/app/INotificationManager;->cancelAllNotifications(Ljava/lang/String;I)V
Landroid/app/INotificationManager;->cancelNotificationWithTag(Ljava/lang/String;Ljava/lang/String;II)V
Landroid/app/INotificationManager;->cancelToast(Ljava/lang/String;Landroid/app/ITransientNotification;)V
Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;I)V
Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
Landroid/app/INotificationManager;->getActiveNotifications(Ljava/lang/String;)[Landroid/service/notification/StatusBarNotification;
Landroid/app/INotificationManager;->getHistoricalNotifications(Ljava/lang/String;I)[Landroid/service/notification/StatusBarNotification;
Landroid/app/INotificationManager;->getZenMode()I

View File

@@ -534,7 +534,7 @@ Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landro
Landroid/app/INotificationManager;->cancelAllNotifications(Ljava/lang/String;I)V
Landroid/app/INotificationManager;->cancelNotificationWithTag(Ljava/lang/String;Ljava/lang/String;II)V
Landroid/app/INotificationManager;->cancelToast(Ljava/lang/String;Landroid/app/ITransientNotification;)V
Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;I)V
Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
Landroid/app/IProcessObserver$Stub;-><init>()V
Landroid/app/ISearchManager$Stub$Proxy;->getGlobalSearchActivity()Landroid/content/ComponentName;
Landroid/app/ISearchManager$Stub$Proxy;->getWebSearchActivity()Landroid/content/ComponentName;

View File

@@ -43,7 +43,7 @@ interface INotificationManager
void cancelAllNotifications(String pkg, int userId);
void clearData(String pkg, int uid, boolean fromApp);
void enqueueToast(String pkg, ITransientNotification callback, int duration);
void enqueueToast(String pkg, ITransientNotification callback, int duration, int displayId);
void cancelToast(String pkg, ITransientNotification callback);
void finishToken(String pkg, ITransientNotification callback);

View File

@@ -133,9 +133,10 @@ public class Toast {
String pkg = mContext.getOpPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
final int displayId = mContext.getDisplay().getDisplayId();
try {
service.enqueueToast(pkg, tn, mDuration);
service.enqueueToast(pkg, tn, mDuration, displayId);
} catch (RemoteException e) {
// Empty
}

View File

@@ -13303,7 +13303,7 @@ PLcom/android/server/notification/NotificationManagerService$10;->createNotifica
PLcom/android/server/notification/NotificationManagerService$10;->deleteNotificationChannel(Ljava/lang/String;Ljava/lang/String;)V
PLcom/android/server/notification/NotificationManagerService$10;->enforcePolicyAccess(ILjava/lang/String;)V
PLcom/android/server/notification/NotificationManagerService$10;->enforceSystemOrSystemUI(Ljava/lang/String;)V
PLcom/android/server/notification/NotificationManagerService$10;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;I)V
PLcom/android/server/notification/NotificationManagerService$10;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
PLcom/android/server/notification/NotificationManagerService$10;->finishToken(Ljava/lang/String;Landroid/app/ITransientNotification;)V
PLcom/android/server/notification/NotificationManagerService$10;->getAppActiveNotifications(Ljava/lang/String;I)Landroid/content/pm/ParceledListSlice;
PLcom/android/server/notification/NotificationManagerService$10;->getBackupPayload(I)[B

View File

@@ -628,15 +628,17 @@ public class NotificationManagerService extends SystemService {
final String pkg;
final ITransientNotification callback;
int duration;
int displayId;
Binder token;
ToastRecord(int pid, String pkg, ITransientNotification callback, int duration,
Binder token) {
Binder token, int displayId) {
this.pid = pid;
this.pkg = pkg;
this.callback = callback;
this.duration = duration;
this.token = token;
this.displayId = displayId;
}
void update(int duration) {
@@ -1986,11 +1988,12 @@ public class NotificationManagerService extends SystemService {
// ============================================================================
@Override
public void enqueueToast(String pkg, ITransientNotification callback, int duration)
public void enqueueToast(String pkg, ITransientNotification callback, int duration,
int displayId)
{
if (DBG) {
Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback
+ " duration=" + duration);
+ " duration=" + duration + " displayId=" + displayId);
}
if (pkg == null || callback == null) {
@@ -2042,8 +2045,9 @@ public class NotificationManagerService extends SystemService {
}
Binder token = new Binder();
mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, DEFAULT_DISPLAY);
record = new ToastRecord(callingPid, pkg, callback, duration, token);
mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, displayId);
record = new ToastRecord(callingPid, pkg, callback, duration, token,
displayId);
mToastQueue.add(record);
index = mToastQueue.size() - 1;
keepProcessAliveIfNeededLocked(callingPid);
@@ -2094,7 +2098,7 @@ public class NotificationManagerService extends SystemService {
int index = indexOfToastLocked(pkg, callback);
if (index >= 0) {
ToastRecord record = mToastQueue.get(index);
finishTokenLocked(record.token);
finishTokenLocked(record.token, record.displayId);
} else {
Slog.w(TAG, "Toast already killed. pkg=" + pkg
+ " callback=" + callback);
@@ -5128,13 +5132,13 @@ public class NotificationManagerService extends SystemService {
ToastRecord lastToast = mToastQueue.remove(index);
mWindowManagerInternal.removeWindowToken(lastToast.token, false /* removeWindows */,
DEFAULT_DISPLAY);
lastToast.displayId);
// We passed 'false' for 'removeWindows' so that the client has time to stop
// rendering (as hide above is a one-way message), otherwise we could crash
// a client which was actively using a surface made from the token. However
// we need to schedule a timeout to make sure the token is eventually killed
// one way or another.
scheduleKillTokenTimeout(lastToast.token);
scheduleKillTokenTimeout(lastToast);
keepProcessAliveIfNeededLocked(record.pid);
if (mToastQueue.size() > 0) {
@@ -5145,14 +5149,13 @@ public class NotificationManagerService extends SystemService {
}
}
void finishTokenLocked(IBinder t) {
void finishTokenLocked(IBinder t, int displayId) {
mHandler.removeCallbacksAndMessages(t);
// We pass 'true' for 'removeWindows' to let the WindowManager destroy any
// remaining surfaces as either the client has called finishToken indicating
// it has successfully removed the views, or the client has timed out
// at which point anything goes.
mWindowManagerInternal.removeWindowToken(t, true /* removeWindows */,
DEFAULT_DISPLAY);
mWindowManagerInternal.removeWindowToken(t, true /* removeWindows */, displayId);
}
@GuardedBy("mToastQueue")
@@ -5176,18 +5179,18 @@ public class NotificationManagerService extends SystemService {
}
@GuardedBy("mToastQueue")
private void scheduleKillTokenTimeout(IBinder token)
private void scheduleKillTokenTimeout(ToastRecord r)
{
mHandler.removeCallbacksAndMessages(token);
Message m = Message.obtain(mHandler, MESSAGE_FINISH_TOKEN_TIMEOUT, token);
mHandler.removeCallbacksAndMessages(r);
Message m = Message.obtain(mHandler, MESSAGE_FINISH_TOKEN_TIMEOUT, r);
mHandler.sendMessageDelayed(m, FINISH_TOKEN_TIMEOUT);
}
private void handleKillTokenTimeout(IBinder token)
private void handleKillTokenTimeout(ToastRecord record)
{
if (DBG) Slog.d(TAG, "Kill Token Timeout token=" + token);
if (DBG) Slog.d(TAG, "Kill Token Timeout token=" + record.token);
synchronized (mToastQueue) {
finishTokenLocked(token);
finishTokenLocked(record.token, record.displayId);
}
}
@@ -5381,7 +5384,7 @@ public class NotificationManagerService extends SystemService {
handleDurationReached((ToastRecord)msg.obj);
break;
case MESSAGE_FINISH_TOKEN_TIMEOUT:
handleKillTokenTimeout((IBinder)msg.obj);
handleKillTokenTimeout((ToastRecord)msg.obj);
break;
case MESSAGE_SAVE_POLICY_FILE:
handleSavePolicyFile();

View File

@@ -1367,7 +1367,7 @@ public class WindowManagerService extends IWindowManager.Stub
// UID, otherwise we allow unlimited duration. When a UID looses focus we
// schedule hiding all of its toast windows.
if (type == TYPE_TOAST) {
if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
if (!displayContent.canAddToastWindowForUid(callingUid)) {
Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}