Merge "Listen to the shortcut add/update/delete changes from PeopleService"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user