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

Commit c3e12576 authored by Alex Kershaw's avatar Alex Kershaw
Browse files

Make DnD check work profile contacts

This ensures that starred contacts from the work profile are allowed
through DnD when that's the setting applied.

Fixes: 111506675
Test: Tested manually currently
Change-Id: I5b98179f267224ea3727018db8c83c49ca3f8307
parent 76b89b6d
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
@@ -2210,6 +2211,28 @@ public final class ContactsContract {
        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
            return openContactPhotoInputStream(cr, contactUri, false);
        }

        /**
         * Creates and returns a corp lookup URI from the given enterprise lookup URI by removing
         * {@link #ENTERPRISE_CONTACT_LOOKUP_PREFIX} from the key. Returns {@code null} if the given
         * URI is not an enterprise lookup URI.
         *
         * @hide
         */
        @Nullable
        public static Uri createCorpLookupUriFromEnterpriseLookupUri(
                @NonNull Uri enterpriseLookupUri) {
            final List<String> pathSegments = enterpriseLookupUri.getPathSegments();
            if (pathSegments == null || pathSegments.size() <= 2) {
                return null;
            }
            final String key = pathSegments.get(2);
            if (TextUtils.isEmpty(key) || !key.startsWith(ENTERPRISE_CONTACT_LOOKUP_PREFIX)) {
                return null;
            }
            final String actualKey = key.substring(ENTERPRISE_CONTACT_LOOKUP_PREFIX.length());
            return Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, actualKey);
        }
    }

    /**
+45 −10
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.notification;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.content.ContentProvider;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
@@ -28,6 +29,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.Settings;
@@ -38,6 +40,8 @@ import android.util.Log;
import android.util.LruCache;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;

import libcore.util.EmptyArray;

import java.util.ArrayList;
@@ -392,27 +396,58 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
        return searchContacts(context, numberUri);
    }

    private LookupResult searchContacts(Context context, Uri lookupUri) {
    @VisibleForTesting
    LookupResult searchContacts(Context context, Uri lookupUri) {
        LookupResult lookupResult = new LookupResult();
        Cursor c = null;
        try {
            c = context.getContentResolver().query(lookupUri, LOOKUP_PROJECTION, null, null, null);
        final Uri corpLookupUri =
                ContactsContract.Contacts.createCorpLookupUriFromEnterpriseLookupUri(lookupUri);
        if (corpLookupUri == null) {
            addContacts(lookupResult, context, lookupUri);
        } else {
            addWorkContacts(lookupResult, context, corpLookupUri);
        }
        return lookupResult;
    }

    private void addWorkContacts(LookupResult lookupResult, Context context, Uri corpLookupUri) {
        final int workUserId = findWorkUserId(context);
        if (workUserId == -1) {
            Slog.w(TAG, "Work profile user ID not found for work contact: " + corpLookupUri);
            return;
        }
        final Uri corpLookupUriWithUserId =
                ContentProvider.maybeAddUserId(corpLookupUri, workUserId);
        addContacts(lookupResult, context, corpLookupUriWithUserId);
    }

    /** Returns the user ID of the managed profile or -1 if none is found. */
    private int findWorkUserId(Context context) {
        final UserManager userManager = context.getSystemService(UserManager.class);
        final int[] profileIds =
                userManager.getProfileIds(context.getUserId(), /* enabledOnly= */ true);
        for (int profileId : profileIds) {
            if (userManager.isManagedProfile(profileId)) {
                return profileId;
            }
        }
        return -1;
    }

    /** Modifies the given lookup result to add contacts found at the given URI. */
    private void addContacts(LookupResult lookupResult, Context context, Uri uri) {
        try (Cursor c = context.getContentResolver().query(
                uri, LOOKUP_PROJECTION, null, null, null)) {
            if (c == null) {
                Slog.w(TAG, "Null cursor from contacts query.");
                return lookupResult;
                return;
            }
            while (c.moveToNext()) {
                lookupResult.mergeContact(c);
            }
        } catch (Throwable t) {
            Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
        } finally {
            if (c != null) {
                c.close();
        }
    }
        return lookupResult;
    }

    private static class LookupResult {
        private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000;  // 1hr
+71 −0
Original line number Diff line number Diff line
@@ -16,11 +16,23 @@
package com.android.server.notification;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Notification;
import android.app.Person;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableString;

@@ -30,6 +42,7 @@ import com.android.server.UiServiceTestCase;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

import java.util.ArrayList;
import java.util.Arrays;
@@ -169,6 +182,64 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
        assertStringArrayEquals("testPeopleArrayList", expected, result);
    }

    @Test
    public void testSearchContacts_workContact_queriesWorkContactProvider()
            throws Exception {
        final int personalUserId = 0;
        final int workUserId = 12;
        final int contactId = 12345;
        final Context mockContext = mock(Context.class);
        when(mockContext.getUserId()).thenReturn(personalUserId);
        final UserManager mockUserManager = mock(UserManager.class);
        when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
        when(mockUserManager.getProfileIds(personalUserId, /* enabledOnly= */ true))
                .thenReturn(new int[] {personalUserId, workUserId});
        when(mockUserManager.isManagedProfile(workUserId)).thenReturn(true);
        final ContentResolver mockContentResolver = mock(ContentResolver.class);
        when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
        final Uri lookupUri = Uri.withAppendedPath(
                ContactsContract.Contacts.CONTENT_LOOKUP_URI,
                ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX + contactId);

        new ValidateNotificationPeople().searchContacts(mockContext, lookupUri);

        ArgumentCaptor<Uri> queryUri = ArgumentCaptor.forClass(Uri.class);
        verify(mockContentResolver).query(
                queryUri.capture(),
                any(),
                /* selection= */ isNull(),
                /* selectionArgs= */ isNull(),
                /* sortOrder= */ isNull());
        assertEquals(workUserId, ContentProvider.getUserIdFromUri(queryUri.getValue()));
    }

    @Test
    public void testSearchContacts_personalContact_queriesPersonalContactProvider()
            throws Exception {
        final int personalUserId = 0;
        final int workUserId = 12;
        final int contactId = 12345;
        final Context mockContext = mock(Context.class);
        when(mockContext.getUserId()).thenReturn(personalUserId);
        final UserManager mockUserManager = mock(UserManager.class);
        when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
        final ContentResolver mockContentResolver = mock(ContentResolver.class);
        when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
        final Uri lookupUri = Uri.withAppendedPath(
                ContactsContract.Contacts.CONTENT_LOOKUP_URI, String.valueOf(contactId));

        new ValidateNotificationPeople().searchContacts(mockContext, lookupUri);

        ArgumentCaptor<Uri> queryUri = ArgumentCaptor.forClass(Uri.class);
        verify(mockContentResolver).query(
                queryUri.capture(),
                any(),
                /* selection= */ isNull(),
                /* selectionArgs= */ isNull(),
                /* sortOrder= */ isNull());
        assertFalse(ContentProvider.uriHasUserId(queryUri.getValue()));
    }

    private void assertStringArrayEquals(String message, String[] expected, String[] result) {
        String expectedString = Arrays.toString(expected);
        String resultString = Arrays.toString(result);