Merge "Lock all the things" into oc-dev

This commit is contained in:
Julia Reynolds
2017-04-18 19:13:05 +00:00
committed by Android (Google) Code Review
3 changed files with 191 additions and 21 deletions

View File

@@ -15,19 +15,25 @@
*/
package com.android.server.notification;
import android.util.Slog;
import java.util.Comparator;
/**
* Sorts notifications by their global sort key.
*/
public class GlobalSortKeyComparator implements Comparator<NotificationRecord> {
private final static String TAG = "GlobalSortComp";
@Override
public int compare(NotificationRecord left, NotificationRecord right) {
if (left.getGlobalSortKey() == null) {
throw new IllegalStateException("Missing left global sort key: " + left);
Slog.wtf(TAG, "Missing left global sort key: " + left);
return 1;
}
if (right.getGlobalSortKey() == null) {
throw new IllegalStateException("Missing right global sort key: " + right);
Slog.wtf(TAG, "Missing right global sort key: " + right);
return -1;
}
return left.getGlobalSortKey().compareTo(right.getGlobalSortKey());
}

View File

@@ -1874,10 +1874,9 @@ public class NotificationManagerService extends SystemService {
int userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), incomingUserId, true, false,
"getAppActiveNotifications", pkg);
final ArrayMap<String, StatusBarNotification> map
= new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
synchronized (mNotificationLock) {
final ArrayMap<String, StatusBarNotification> map
= new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
final int N = mNotificationList.size();
for (int i = 0; i < N; i++) {
StatusBarNotification sbn = sanitizeSbn(pkg, userId,
@@ -1900,11 +1899,10 @@ public class NotificationManagerService extends SystemService {
map.put(sbn.getKey(), sbn); // pending update overwrites existing post here
}
}
final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
list.addAll(map.values());
return new ParceledListSlice<StatusBarNotification>(list);
}
final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
list.addAll(map.values());
return new ParceledListSlice<StatusBarNotification>(list);
}
private StatusBarNotification sanitizeSbn(String pkg, int userId,
@@ -2036,8 +2034,10 @@ public class NotificationManagerService extends SystemService {
long identity = Binder.clearCallingIdentity();
try {
// allow bound services to disable themselves
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
info.getOwner().setComponentState(info.component, false);
synchronized (mNotificationLock) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
info.getOwner().setComponentState(info.component, false);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2101,8 +2101,10 @@ public class NotificationManagerService extends SystemService {
String key, String snoozeCriterionId) {
long identity = Binder.clearCallingIdentity();
try {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
snoozeNotificationInt(key, SNOOZE_UNTIL_UNSPECIFIED, snoozeCriterionId, info);
synchronized (mNotificationLock) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
snoozeNotificationInt(key, SNOOZE_UNTIL_UNSPECIFIED, snoozeCriterionId, info);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2118,8 +2120,10 @@ public class NotificationManagerService extends SystemService {
long duration) {
long identity = Binder.clearCallingIdentity();
try {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
snoozeNotificationInt(key, duration, null, info);
synchronized (mNotificationLock) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
snoozeNotificationInt(key, duration, null, info);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2134,9 +2138,11 @@ public class NotificationManagerService extends SystemService {
public void unsnoozeNotificationFromAssistant(INotificationListener token, String key) {
long identity = Binder.clearCallingIdentity();
try {
final ManagedServiceInfo info =
mNotificationAssistants.checkServiceTokenLocked(token);
unsnoozeNotificationInt(key, info);
synchronized (mNotificationLock) {
final ManagedServiceInfo info =
mNotificationAssistants.checkServiceTokenLocked(token);
unsnoozeNotificationInt(key, info);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2734,7 +2740,10 @@ public class NotificationManagerService extends SystemService {
}
private void verifyPrivilegedListener(INotificationListener token, UserHandle user) {
ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
ManagedServiceInfo info;
synchronized (mNotificationLock) {
info = mListeners.checkServiceTokenLocked(token);
}
if (!hasCompanionDevice(info)) {
throw new SecurityException(info + " does not have access");
}
@@ -3099,8 +3108,10 @@ public class NotificationManagerService extends SystemService {
@Override
public void run() {
synchronized (mNotificationLock) {
removeForegroundServiceFlagByListLocked(mEnqueuedNotifications, pkg, notificationId, userId);
removeForegroundServiceFlagByListLocked(mNotificationList, pkg, notificationId, userId);
removeForegroundServiceFlagByListLocked(
mEnqueuedNotifications, pkg, notificationId, userId);
removeForegroundServiceFlagByListLocked(
mNotificationList, pkg, notificationId, userId);
}
}
});

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2016 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.server.notification;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class GlobalSortKeyComparatorTest {
private final String PKG = "PKG";
private final int UID = 1111111;
private static final String TEST_CHANNEL_ID = "test_channel_id";
@Test
public void testComparator() throws Exception {
Notification n = new Notification.Builder(
InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
.build();
NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
left.setGlobalSortKey("first");
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
right.setGlobalSortKey("second");
NotificationRecord last = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
final List<NotificationRecord> expected = new ArrayList<>();
expected.add(left);
expected.add(right);
expected.add(last);
List<NotificationRecord> actual = new ArrayList<>();
actual.addAll(expected);
Collections.shuffle(actual);
Collections.sort(actual, new GlobalSortKeyComparator());
assertEquals(expected, actual);
}
@Test
public void testNoCrash_leftNull() throws Exception {
Notification n = new Notification.Builder(
InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
.build();
NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
right.setGlobalSortKey("not null");
final List<NotificationRecord> expected = new ArrayList<>();
expected.add(right);
expected.add(left);
List<NotificationRecord> actual = new ArrayList<>();
actual.addAll(expected);
Collections.shuffle(actual);
Collections.sort(actual, new GlobalSortKeyComparator());
assertEquals(expected, actual);
}
@Test
public void testNoCrash_rightNull() throws Exception {
Notification n = new Notification.Builder(
InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
.build();
NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
left.setGlobalSortKey("not null");
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
"", 1499), getDefaultChannel());
final List<NotificationRecord> expected = new ArrayList<>();
expected.add(left);
expected.add(right);
List<NotificationRecord> actual = new ArrayList<>();
actual.addAll(expected);
Collections.shuffle(actual);
Collections.sort(actual, new GlobalSortKeyComparator());
assertEquals(expected, actual);
}
private NotificationChannel getDefaultChannel() {
return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
NotificationManager.IMPORTANCE_LOW);
}
}