aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIshneet Ahuja <ishneet@google.com>2023-10-05 11:21:58 +0000
committerIshneet Ahuja <ishneet@google.com>2023-10-25 14:47:53 +0000
commit2e2ccb63df8dc600bbd266db46f1a50f4af66983 (patch)
tree8dc661e710c7d523e0d9f68e2566e4f53e97299e
parent884f642eef0047523421abbb188cea870a8919e4 (diff)
downloadContactsProvider-2e2ccb63df8dc600bbd266db46f1a50f4af66983.tar.gz
CP2 handling of stopped state apps
This includes changes required for handling stopped state apps in CP2. Bug: 300253342 Test: atest ContactsProviderTests CtsContactsProviderTestCases, Manual testing by following go/cp2-stopped-state-apps-testing Change-Id: Iac8d186f9d442f8bfccf834fb52d407653622f38
-rw-r--r--Android.bp1
-rw-r--r--src/com/android/providers/contacts/ContactDirectoryManager.java15
-rw-r--r--src/com/android/providers/contacts/ContactsPackageMonitor.java1
-rw-r--r--src/com/android/providers/contacts/ContactsProvider2.java26
-rw-r--r--tests/Android.bp2
-rw-r--r--tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java17
-rw-r--r--tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java89
-rw-r--r--tests/src/com/android/providers/contacts/ContactsMockPackageManager.java7
8 files changed, 138 insertions, 20 deletions
diff --git a/Android.bp b/Android.bp
index 08fd9570..945b32c4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -18,6 +18,7 @@ android_app {
"android-common",
"com.android.vcard",
"guava",
+ "android.content.pm.flags-aconfig-java",
],
// The Jacoco tool analyzes code coverage when running unit tests on the
diff --git a/src/com/android/providers/contacts/ContactDirectoryManager.java b/src/com/android/providers/contacts/ContactDirectoryManager.java
index 09e3ff37..5dcf788c 100644
--- a/src/com/android/providers/contacts/ContactDirectoryManager.java
+++ b/src/com/android/providers/contacts/ContactDirectoryManager.java
@@ -19,6 +19,8 @@ package com.android.providers.contacts;
import android.annotation.NonNull;
import android.content.ContentValues;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -39,6 +41,7 @@ import android.util.Log;
import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
import com.android.providers.contacts.ContactsDatabaseHelper.DirectoryColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
import com.google.common.annotations.VisibleForTesting;
@@ -418,7 +421,8 @@ public class ContactDirectoryManager {
* Scans the specified package for content directories and updates the {@link Directory}
* table accordingly.
*/
- private List<DirectoryInfo> updateDirectoriesForPackage(
+ @VisibleForTesting
+ List<DirectoryInfo> updateDirectoriesForPackage(
PackageInfo packageInfo, boolean initialScan) {
if (DEBUG) {
Log.d(TAG, "updateDirectoriesForPackage packageName=" + packageInfo.packageName
@@ -427,6 +431,15 @@ public class ContactDirectoryManager {
ArrayList<DirectoryInfo> directories = Lists.newArrayList();
+ if (Flags.stayStopped()
+ && (packageInfo.applicationInfo != null
+ && ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0))) {
+ if (DEBUG) {
+ Log.d(TAG, "Package " + packageInfo.packageName + " is in stopped state");
+ }
+ return null;
+ }
+
ProviderInfo[] providers = packageInfo.providers;
if (providers != null) {
for (ProviderInfo provider : providers) {
diff --git a/src/com/android/providers/contacts/ContactsPackageMonitor.java b/src/com/android/providers/contacts/ContactsPackageMonitor.java
index 06565cd9..93c7df90 100644
--- a/src/com/android/providers/contacts/ContactsPackageMonitor.java
+++ b/src/com/android/providers/contacts/ContactsPackageMonitor.java
@@ -95,6 +95,7 @@ public class ContactsPackageMonitor {
private void registerReceiver() {
final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_UNSTOPPED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 25264598..7662b32b 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -46,6 +46,7 @@ import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.content.SyncAdapterType;
import android.content.UriMatcher;
+import android.content.pm.Flags;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
@@ -175,7 +176,6 @@ import com.android.providers.contacts.aggregation.AbstractContactAggregator.Aggr
import com.android.providers.contacts.aggregation.ContactAggregator;
import com.android.providers.contacts.aggregation.ContactAggregator2;
import com.android.providers.contacts.aggregation.ProfileAggregator;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.database.ContactsTableUtil;
import com.android.providers.contacts.database.DeletedContactsTableUtil;
import com.android.providers.contacts.database.MoreDatabaseUtils;
@@ -187,13 +187,10 @@ import com.android.providers.contacts.util.DbQueryUtils;
import com.android.providers.contacts.util.LogFields;
import com.android.providers.contacts.util.LogUtils;
import com.android.providers.contacts.util.NeededForTesting;
-import com.android.providers.contacts.util.PhoneAccountHandleMigrationUtils;
import com.android.providers.contacts.util.UserUtils;
import com.android.vcard.VCardComposer;
import com.android.vcard.VCardConfig;
-import libcore.io.IoUtils;
-
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -201,6 +198,8 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Ints;
+import libcore.io.IoUtils;
+
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -5937,6 +5936,22 @@ public class ContactsProvider2 extends AbstractContactsProvider
return null;
}
+ if (projection == null) {
+ projection = getDefaultProjection(uri);
+ }
+
+ // Handle directories in stopped state
+ try {
+ if (Flags.stayStopped()
+ && getContext().getPackageManager()
+ .isPackageStopped(directoryInfo.packageName)) {
+ return new MatrixCursor(projection, 0);
+ }
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Package name " + directoryInfo.packageName + " not found");
+ }
+
+
Builder builder = new Uri.Builder();
builder.scheme(ContentResolver.SCHEME_CONTENT);
builder.authority(directoryInfo.authority);
@@ -5960,9 +5975,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
Uri directoryUri = builder.build();
- if (projection == null) {
- projection = getDefaultProjection(uri);
- }
int galUid = -1;
try {
galUid = getContext().getPackageManager().getPackageUid(directoryInfo.packageName,
diff --git a/tests/Android.bp b/tests/Android.bp
index beb2d313..06d19540 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -9,6 +9,8 @@ android_test {
"ContactsProviderTestUtils",
"androidx.test.rules",
"mockito-target-minus-junit4",
+ "flag-junit",
+ "android.content.pm.flags-aconfig-java",
],
libs: [
"android.test.runner",
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index e8920530..9f433987 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -55,11 +55,13 @@ import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.Settings;
import android.provider.ContactsContract.StatusUpdates;
import android.provider.ContactsContract.StreamItems;
-import android.provider.VoicemailContract;
import android.telephony.SubscriptionManager;
import android.test.MoreAsserts;
import android.test.mock.MockContentResolver;
import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.testutil.CommonDatabaseUtils;
@@ -68,23 +70,23 @@ import com.android.providers.contacts.testutil.RawContactUtil;
import com.android.providers.contacts.testutil.TestUtil;
import com.android.providers.contacts.util.Hex;
import com.android.providers.contacts.util.MockClock;
+
import com.google.android.collect.Sets;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
/**
* A common superclass for {@link ContactsProvider2}-related tests.
*/
@@ -103,6 +105,7 @@ public abstract class BaseContactsProvider2Test extends PhotoLoadingTestCase {
static final String WRITE_VOICEMAIL_PERMISSION =
"com.android.voicemail.permission.WRITE_VOICEMAIL";
+ protected Context mContext;
protected static final String PACKAGE = "ContactsProvider2Test";
public static final String READ_ONLY_ACCOUNT_TYPE =
SynchronousContactsProvider2.READ_ONLY_ACCOUNT_TYPE;
@@ -136,9 +139,11 @@ public abstract class BaseContactsProvider2Test extends PhotoLoadingTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
MockitoAnnotations.initMocks(this);
- mTestContext = new ContextWithServiceOverrides(getContext());
+ mTestContext = new ContextWithServiceOverrides(mContext);
mTestContext.injectSystemService(SubscriptionManager.class, mSubscriptionManager);
mActor = new ContactsActor(
diff --git a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
index a4165ce5..e2434960 100644
--- a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
+++ b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
@@ -16,9 +16,12 @@
package com.android.providers.contacts;
+import static android.content.pm.Flags.FLAG_STAY_STOPPED;
+
import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -27,21 +30,29 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Bundle;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.ContactsContract;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.RawContacts;
import android.test.mock.MockContentProvider;
-import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
import com.google.android.collect.Lists;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.Arrays;
import java.util.Set;
@@ -52,8 +63,11 @@ import java.util.Set;
-w com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
*
*/
-@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private static final String TAG = "ContactDirectoryManagerTest";
private ContactsMockPackageManager mPackageManager;
@@ -114,8 +128,10 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
}
}
+ @Before
@Override
public void setUp() throws Exception {
+
super.setUp();
mProvider = (ContactsProvider2) getProvider();
@@ -129,9 +145,10 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
protected String getContextPackageName() {
// In this test, we need to use the real package name, because that'll be recorded in the
// directory table, and if it's wrong, the tests would get confused.
- return getContext().getPackageName();
+ return mContext.getPackageName();
}
+ @Test
public void testIsDirectoryProvider() {
ProviderInfo provider = new ProviderInfo();
@@ -158,6 +175,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
assertTrue(ContactDirectoryManager.isDirectoryProvider(provider));
}
+ @Test
public void testScanAllProviders() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(
@@ -209,13 +227,13 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
assertTrue(cursor.moveToPosition(3));
- assertDirectoryRow(cursor, getContext().getPackageName(),
+ assertDirectoryRow(cursor, mContext.getPackageName(),
"com.android.contacts", null, null,
null, -1 /* =any */, Directory.EXPORT_SUPPORT_NONE,
Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
assertTrue(cursor.moveToPosition(4));
- assertDirectoryRow(cursor, getContext().getPackageName(),
+ assertDirectoryRow(cursor, mContext.getPackageName(),
"com.android.contacts", null, null,
null, -1 /* =any */, Directory.EXPORT_SUPPORT_NONE,
Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
@@ -223,6 +241,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testScanAllProviders_scanCondition() throws Exception {
testScanAllProviders();
@@ -254,6 +273,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
}
+ @Test
public void testPackageInstalled() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
@@ -305,6 +325,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testPackageUninstalled() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(
@@ -351,6 +372,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testPackageReplaced() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(
@@ -409,6 +431,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
* Tests if the manager works correctly when the package name for a directory is changed
* (on system update).
*/
+ @Test
public void testPackageRenamed() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(
@@ -472,6 +495,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testAccountRemoval() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(
@@ -513,6 +537,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testNotifyDirectoryChange() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
@@ -547,6 +572,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testForwardingToDirectoryProvider() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
@@ -587,6 +613,7 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ @Test
public void testProjectionPopulated() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
@@ -625,8 +652,9 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
* Test {@link ContactDirectoryManager#getDirectoryProviderPackages} with the actual
* package manager, and see if it returns the google sync package.
*/
+ @Test
public void testGetDirectoryProviderPackages() {
- final PackageManager pm = getContext().getPackageManager();
+ final PackageManager pm = mContext.getPackageManager();
final String googleSync = "com.google.android.gms";
// Skip if the package is not installed.
@@ -650,6 +678,55 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
dirProviderPackages.contains(googleSync));
}
+ @Test
+ public void testUpdateDirectoriesForUnstoppedPackage() throws Exception {
+ mPackageManager.setInstalledPackages(
+ Lists.newArrayList(createProviderPackage("test.package1", "authority1")));
+
+ MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
+ MockContactDirectoryProvider.class, "authority1");
+ MatrixCursor response1 = provider1.createResponseCursor();
+ addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
+ Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
+ Directory.PHOTO_SUPPORT_NONE);
+
+ PackageInfo packageInfo = mPackageManager.getPackageInfo("test.package1",
+ PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA);
+
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.packageName = packageInfo.packageName;
+ packageInfo.applicationInfo = applicationInfo;
+ // Package is not in stopped state
+ packageInfo.applicationInfo.flags = 0;
+
+ assertEquals(mDirectoryManager.updateDirectoriesForPackage(packageInfo, true).size(), 1);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_STAY_STOPPED)
+ public void testUpdateDirectoriesForStoppedPackage() throws Exception {
+ mPackageManager.setInstalledPackages(
+ Lists.newArrayList(createProviderPackage("test.package1", "authority1")));
+
+ MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
+ MockContactDirectoryProvider.class, "authority1");
+ MatrixCursor response1 = provider1.createResponseCursor();
+ addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
+ Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
+ Directory.PHOTO_SUPPORT_NONE);
+
+ PackageInfo packageInfo = mPackageManager.getPackageInfo("test.package1",
+ PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA);
+
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.packageName = packageInfo.packageName;
+ packageInfo.applicationInfo = applicationInfo;
+ // Put the package in stopped state: set associated app flags to true
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
+
+ assertNull(mDirectoryManager.updateDirectoriesForPackage(packageInfo, true));
+ }
+
protected PackageInfo createProviderPackage(String packageName, String authority) {
return createPackage(packageName, authority, true);
}
diff --git a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
index 62f17eab..b96d6d52 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
@@ -161,4 +161,11 @@ public class ContactsMockPackageManager extends MockPackageManager {
public int getPackageUid(String packageName, int flags) throws NameNotFoundException {
return 123;
}
+
+ @Override
+ public boolean isPackageStopped(String packageName) throws NameNotFoundException {
+ PackageInfo packageInfo = getPackageInfo(packageName, 0);
+ return packageInfo.applicationInfo != null
+ && ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0);
+ }
}