Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbf1b376 authored by Danning Chen's avatar Danning Chen Committed by Android (Google) Code Review
Browse files

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

parents 57de2191 3fc66d03
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
}
+6 −1
Original line number Diff line number Diff line
@@ -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);
+43 −10
Original line number Diff line number Diff line
@@ -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);
        }
+65 −2
Original line number Diff line number Diff line
@@ -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;