Merge "Listen to the shortcut add/update/delete changes from PeopleService"

This commit is contained in:
Danning Chen
2020-02-21 00:55:54 +00:00
committed by Android (Google) Code Review
4 changed files with 116 additions and 13 deletions

View File

@@ -27,4 +27,6 @@ public interface NotificationManagerInternal {
String tag, int id, int userId);
void removeForegroundServiceFlagFromNotification(String pkg, int notificationId, int userId);
void onConversationRemoved(String pkg, int uid, String conversationId);
}

View File

@@ -5474,6 +5474,11 @@ public class NotificationManagerService extends SystemService {
});
}
@Override
public void onConversationRemoved(String pkg, int uid, String conversationId) {
onConversationRemovedInternal(pkg, uid, conversationId);
}
@GuardedBy("mNotificationLock")
private void removeForegroundServiceFlagLocked(NotificationRecord r) {
if (r == null) {
@@ -5676,7 +5681,7 @@ public class NotificationManagerService extends SystemService {
mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground));
}
public void onConversationRemoved(String pkg, int uid, String conversationId) {
private void onConversationRemovedInternal(String pkg, int uid, String conversationId) {
checkCallerIsSystem();
Preconditions.checkStringNotEmpty(pkg);
Preconditions.checkStringNotEmpty(conversationId);

View File

@@ -31,7 +31,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager.ShareShortcutInfo;
@@ -53,6 +55,7 @@ import android.service.notification.StatusBarNotification;
import android.telecom.TelecomManager;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -61,11 +64,13 @@ import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.telephony.SmsApplication;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
@@ -80,8 +85,8 @@ import java.util.function.Function;
*/
public class DataManager {
private static final int MY_UID = Process.myUid();
private static final int MY_PID = Process.myPid();
private static final String TAG = "DataManager";
private static final long QUERY_EVENTS_MAX_AGE_MS = DateUtils.DAY_IN_MILLIS;
private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
@@ -102,6 +107,7 @@ public class DataManager {
private ShortcutServiceInternal mShortcutServiceInternal;
private PackageManagerInternal mPackageManagerInternal;
private NotificationManagerInternal mNotificationManagerInternal;
private UserManager mUserManager;
public DataManager(Context context) {
@@ -120,9 +126,10 @@ public class DataManager {
public void initialize() {
mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class);
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mNotificationManagerInternal = LocalServices.getService(NotificationManagerInternal.class);
mUserManager = mContext.getSystemService(UserManager.class);
mShortcutServiceInternal.addListener(new ShortcutServiceListener());
mShortcutServiceInternal.addShortcutChangeCallback(new ShortcutServiceCallback());
IntentFilter shutdownIntentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
BroadcastReceiver shutdownBroadcastReceiver = new ShutdownBroadcastReceiver();
@@ -362,7 +369,7 @@ public class DataManager {
return mShortcutServiceInternal.getShortcuts(
UserHandle.USER_SYSTEM, mContext.getPackageName(),
/*changedSince=*/ 0, packageName, shortcutIds, /*locusIds=*/ null,
/*componentName=*/ null, queryFlags, userId, MY_PID, MY_UID);
/*componentName=*/ null, queryFlags, userId, Process.myPid(), Process.myUid());
}
private void forAllUnlockedUsers(Consumer<UserData> consumer) {
@@ -621,14 +628,12 @@ public class DataManager {
}
/** Listener for the shortcut data changes. */
private class ShortcutServiceListener implements
ShortcutServiceInternal.ShortcutChangeListener {
private class ShortcutServiceCallback implements LauncherApps.ShortcutChangeCallback {
@Override
public void onShortcutChanged(@NonNull String packageName, int userId) {
BackgroundThread.getExecutor().execute(() -> {
List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
/*shortcutIds=*/ null);
public void onShortcutsAddedOrUpdated(@NonNull String packageName,
@NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
mInjector.getBackgroundExecutor().execute(() -> {
for (ShortcutInfo shortcut : shortcuts) {
if (isPersonShortcut(shortcut)) {
addOrUpdateConversationInfo(shortcut);
@@ -636,6 +641,30 @@ public class DataManager {
}
});
}
@Override
public void onShortcutsRemoved(@NonNull String packageName,
@NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
mInjector.getBackgroundExecutor().execute(() -> {
int uid = Process.INVALID_UID;
try {
uid = mContext.getPackageManager().getPackageUidAsUser(
packageName, user.getIdentifier());
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Package not found: " + packageName, e);
}
PackageData packageData = getPackage(packageName, user.getIdentifier());
for (ShortcutInfo shortcutInfo : shortcuts) {
if (packageData != null) {
packageData.deleteDataForConversation(shortcutInfo.getId());
}
if (uid != Process.INVALID_UID) {
mNotificationManagerInternal.onConversationRemoved(
shortcutInfo.getPackage(), uid, shortcutInfo.getId());
}
}
});
}
}
/** Listener for the notifications and their settings changes. */
@@ -788,6 +817,10 @@ public class DataManager {
return Executors.newSingleThreadScheduledExecutor();
}
Executor getBackgroundExecutor() {
return BackgroundThread.getExecutor();
}
ContactsQueryHelper createContactsQueryHelper(Context context) {
return new ContactsQueryHelper(context);
}

View File

@@ -52,6 +52,8 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.LauncherApps.ShortcutChangeCallback;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
@@ -72,6 +74,7 @@ import android.util.Range;
import com.android.internal.app.ChooserActivity;
import com.android.internal.content.PackageMonitor;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import org.junit.After;
@@ -79,6 +82,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -87,6 +92,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -102,6 +108,7 @@ public final class DataManagerTest {
private static final String TEST_PKG_NAME = "pkg";
private static final String TEST_CLASS_NAME = "class";
private static final String TEST_SHORTCUT_ID = "sc";
private static final int TEST_PKG_UID = 35;
private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
private static final String PHONE_NUMBER = "+1234567890";
private static final String NOTIFICATION_CHANNEL_ID = "test : sc";
@@ -111,7 +118,9 @@ public final class DataManagerTest {
@Mock private ShortcutServiceInternal mShortcutServiceInternal;
@Mock private UsageStatsManagerInternal mUsageStatsManagerInternal;
@Mock private PackageManagerInternal mPackageManagerInternal;
@Mock private NotificationManagerInternal mNotificationManagerInternal;
@Mock private UserManager mUserManager;
@Mock private PackageManager mPackageManager;
@Mock private TelephonyManager mTelephonyManager;
@Mock private TelecomManager mTelecomManager;
@Mock private ContentResolver mContentResolver;
@@ -121,13 +130,16 @@ public final class DataManagerTest {
@Mock private StatusBarNotification mStatusBarNotification;
@Mock private Notification mNotification;
@Captor private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor;
private NotificationChannel mNotificationChannel;
private DataManager mDataManager;
private CancellationSignal mCancellationSignal;
private ShortcutChangeCallback mShortcutChangeCallback;
private TestInjector mInjector;
@Before
public void setUp() {
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
addLocalServiceMock(ShortcutServiceInternal.class, mShortcutServiceInternal);
@@ -143,8 +155,12 @@ public final class DataManagerTest {
return null;
}).when(mPackageManagerInternal).forEachInstalledPackage(any(Consumer.class), anyInt());
addLocalServiceMock(NotificationManagerInternal.class, mNotificationManagerInternal);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
when(mContext.getPackageName()).thenReturn("android");
when(mContext.getPackageManager()).thenReturn(mPackageManager);
Context originalContext = getInstrumentation().getTargetContext();
when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
@@ -175,7 +191,8 @@ public final class DataManagerTest {
when(mUserManager.getEnabledProfiles(USER_ID_SECONDARY))
.thenReturn(Collections.singletonList(buildUserInfo(USER_ID_SECONDARY)));
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mPackageManager.getPackageUidAsUser(TEST_PKG_NAME, USER_ID_PRIMARY))
.thenReturn(TEST_PKG_UID);
when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
when(mStatusBarNotification.getPackageName()).thenReturn(TEST_PKG_NAME);
@@ -192,6 +209,10 @@ public final class DataManagerTest {
mInjector = new TestInjector();
mDataManager = new DataManager(mContext, mInjector);
mDataManager.initialize();
verify(mShortcutServiceInternal).addShortcutChangeCallback(
mShortcutChangeCallbackCaptor.capture());
mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
}
@After
@@ -473,6 +494,43 @@ public final class DataManagerTest {
assertFalse(conversationInfo.isDemoted());
}
@Test
public void testShortcutAddedOrUpdated() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
buildPerson());
mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
Collections.singletonList(shortcut), UserHandle.of(USER_ID_PRIMARY));
List<ConversationInfo> conversations = getConversationsInPrimary();
assertEquals(1, conversations.size());
assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
}
@Test
public void testShortcutDeleted() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc1",
buildPerson());
ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc2",
buildPerson());
mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
Arrays.asList(shortcut1, shortcut2), UserHandle.of(USER_ID_PRIMARY));
mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME,
Collections.singletonList(shortcut1), UserHandle.of(USER_ID_PRIMARY));
List<ConversationInfo> conversations = getConversationsInPrimary();
assertEquals(1, conversations.size());
assertEquals("sc2", conversations.get(0).getShortcutId());
verify(mNotificationManagerInternal)
.onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, "sc1");
}
@Test
public void testCallLogContentObserver() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -764,6 +822,11 @@ public final class DataManagerTest {
return mExecutorService;
}
@Override
Executor getBackgroundExecutor() {
return Runnable::run;
}
@Override
ContactsQueryHelper createContactsQueryHelper(Context context) {
return mContactsQueryHelper;