ContactsActor.java revision 212975b9dbb3c164e11732b98266eb7361e27ac5
1619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey/* 2619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Copyright (C) 2009 The Android Open Source Project 3619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * 4619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * you may not use this file except in compliance with the License. 6619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * You may obtain a copy of the License at 7619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * 8619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * 10619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * See the License for the specific language governing permissions and 14619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * limitations under the License. 15619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 16619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts; 18619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport com.google.android.collect.Sets; 2024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 21bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.Account; 22bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AccountManager; 23bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AccountManagerCallback; 24bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AccountManagerFuture; 25bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AuthenticatorException; 26bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.OnAccountsUpdateListener; 27bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.OperationCanceledException; 28bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikovimport android.content.ContentProvider; 29e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.ContentResolver; 30ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.content.ContentUris; 31ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.content.ContentValues; 32619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.Context; 33619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo; 34619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager; 3572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.pm.ProviderInfo; 365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.content.res.Configuration; 37b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.content.res.Resources; 38ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.Cursor; 3989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.location.Country; 4089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.location.CountryDetector; 4189b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.location.CountryListener; 42ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.net.Uri; 43bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 4489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.os.Looper; 45ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.BaseColumns; 46619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.provider.ContactsContract; 4747fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 48ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds; 4989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 5089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 51e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 52ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Data; 53e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 541d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkeyimport android.provider.ContactsContract.StatusUpdates; 55619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.IsolatedContext; 56619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.RenamingDelegatingContext; 57619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.mock.MockContentResolver; 58619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.mock.MockContext; 59619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 60f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport java.io.File; 61bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport java.io.IOException; 6224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport java.util.Arrays; 635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport java.util.Locale; 6424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport java.util.Set; 65619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 66619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey/** 67619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Helper class that encapsulates an "actor" which is owned by a specific 68619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name. It correctly maintains a wrapped {@link Context} and an 69619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * attached {@link MockContentResolver}. Multiple actors can be used to test 70619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * security scenarios between multiple packages. 71619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 72619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeypublic class ContactsActor { 73619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final String FILENAME_PREFIX = "test."; 74619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 75619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_GREY = "edu.example.grey"; 76619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_RED = "net.example.red"; 77619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_GREEN = "com.example.green"; 78619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_BLUE = "org.example.blue"; 79619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 80619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public Context context; 81619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public String packageName; 82619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public MockContentResolver resolver; 83bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov public ContentProvider provider; 8489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private Country mMockCountry = new Country("us", 0); 8589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 86bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Account[] mAccounts = new Account[0]; 87bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 8824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private Set<String> mGrantedPermissions = Sets.newHashSet(); 89eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee private final Set<Uri> mGrantedUriPermissions = Sets.newHashSet(); 9024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 9189b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private CountryDetector mMockCountryDetector = new CountryDetector(null){ 9289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 9389b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public Country detectCountry() { 9489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov return mMockCountry; 9589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 9689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 9789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 9889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public void addCountryListener(CountryListener listener, Looper looper) { 9989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 10089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov }; 101619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 102bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private AccountManager mMockAccountManager; 103bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 104bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private class MockAccountManager extends AccountManager { 105bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public MockAccountManager(Context conteact) { 106bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov super(context, null, null); 107bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 108bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 109bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 110bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener, 111bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Handler handler, boolean updateImmediately) { 112bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // do nothing 113bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 114bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 115bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 116bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public Account[] getAccounts() { 117bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return mAccounts; 118bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 119bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 120bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 121bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures( 122bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String type, final String[] features, 123bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov AccountManagerCallback<Account[]> callback, Handler handler) { 124bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return null; 125bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 126bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 127bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 128bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public String blockingGetAuthToken(Account account, String authTokenType, 129bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean notifyAuthFailure) 130bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov throws OperationCanceledException, IOException, AuthenticatorException { 131bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return null; 132bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 133bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 134bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 135e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private IsolatedContext mProviderContext; 136e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 137619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 138619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Create an "actor" using the given parent {@link Context} and the specific 139619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name. Internally, all {@link Context} method calls are passed to 140619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * a new instance of {@link RestrictionMockContext}, which stubs out the 141619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * security infrastructure. 142619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 143bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov public ContactsActor(Context overallContext, String packageName, 144bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov Class<? extends ContentProvider> providerClass, String authority) throws Exception { 145619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey resolver = new MockContentResolver(); 14624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro context = new RestrictionMockContext(overallContext, packageName, resolver, 147eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedPermissions, mGrantedUriPermissions); 148e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov this.packageName = packageName; 149619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 150212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // Let the Secure class initialize the settings provider, which is done when we first 151212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // tries to get any setting. Because our mock context/content resolver doesn't have the 152212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // settings provider, we need to do this with an actual context, before other classes 153212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // try to do this with a mock context. 154212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // (Otherwise ContactsProvider2.initialzie() will crash trying to get a setting with 155212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // a mock context.) 156212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki android.provider.Settings.Secure.getString(overallContext.getContentResolver(), "dummy"); 157212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki 158bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(context, 159bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov overallContext, FILENAME_PREFIX); 16089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov mProviderContext = new IsolatedContext(resolver, targetContextWrapper){ 16189b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 16289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 163f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro public File getFilesDir() { 164f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // TODO: Need to figure out something more graceful than this. 165f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return new File("/data/data/com.android.providers.contacts.tests/files"); 166f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 167f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 168f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 16989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public Object getSystemService(String name) { 17089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov if (Context.COUNTRY_DETECTOR.equals(name)) { 17189b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov return mMockCountryDetector; 17289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 173bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (Context.ACCOUNT_SERVICE.equals(name)) { 174bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return mMockAccountManager; 175bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 17689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov return super.getSystemService(name); 17789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 17889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov }; 179bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 180bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mMockAccountManager = new MockAccountManager(mProviderContext); 181e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov provider = addProvider(providerClass, authority); 182e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 183e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 184e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public void addAuthority(String authority) { 185e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov resolver.addProvider(authority, provider); 186e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 187619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 188e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public ContentProvider addProvider(Class<? extends ContentProvider> providerClass, 189e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov String authority) throws Exception { 190e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov ContentProvider provider = providerClass.newInstance(); 19172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ProviderInfo info = new ProviderInfo(); 19272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.authority = authority; 19372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov provider.attachInfo(mProviderContext, info); 194bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov resolver.addProvider(authority, provider); 195e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return provider; 196619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 197619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 19824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void addPermissions(String... permissions) { 19924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions.addAll(Arrays.asList(permissions)); 20024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 20124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 20224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void removePermissions(String... permissions) { 20324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions.removeAll(Arrays.asList(permissions)); 20424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 20524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 206eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public void addUriPermissions(Uri... uris) { 207eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions.addAll(Arrays.asList(uris)); 208eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 209eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 210eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public void removeUriPermissions(Uri... uris) { 211eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions.removeAll(Arrays.asList(uris)); 212eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 213eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 214619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 215619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Mock {@link Context} that reports specific well-known values for testing 216619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * data protection. The creator can override the owner package name, and 217619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * force the {@link PackageManager} to always return a well-known package 218619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * list for any call to {@link PackageManager#getPackagesForUid(int)}. 219619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * <p> 220619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * For example, the creator could request that the {@link Context} lives in 221619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name "com.example.red", and also cause the {@link PackageManager} 222619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * to report that no UID contains that package name. 223619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 224619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static class RestrictionMockContext extends MockContext { 225b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov private final Context mOverallContext; 226b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov private final String mReportedPackageName; 22772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private final ContactsMockPackageManager mPackageManager; 228e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private final ContentResolver mResolver; 2291d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey private final Resources mRes; 23024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private final Set<String> mGrantedPermissions; 231eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee private final Set<Uri> mGrantedUriPermissions; 232619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 233619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 234619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Create a {@link Context} under the given package name. 235619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 236e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public RestrictionMockContext(Context overallContext, String reportedPackageName, 237eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee ContentResolver resolver, Set<String> grantedPermissions, 238eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee Set<Uri> grantedUriPermissions) { 239b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov mOverallContext = overallContext; 240619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mReportedPackageName = reportedPackageName; 241e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov mResolver = resolver; 24224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions = grantedPermissions; 243eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions = grantedUriPermissions; 2441d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 24572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mPackageManager = new ContactsMockPackageManager(); 246619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(1000, PACKAGE_GREY); 247619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(2000, PACKAGE_RED); 248619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(3000, PACKAGE_GREEN); 249619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(4000, PACKAGE_BLUE); 2501d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 2515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Resources resources = overallContext.getResources(); 2525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Configuration configuration = new Configuration(resources.getConfiguration()); 2535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov configuration.locale = Locale.US; 2545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov resources.updateConfiguration(configuration, resources.getDisplayMetrics()); 255ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann mRes = resources; 256619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 257619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 258619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 259619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public String getPackageName() { 260619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mReportedPackageName; 261619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 262619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 263619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 264619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public PackageManager getPackageManager() { 265619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mPackageManager; 266619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 267b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov 268b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov @Override 269b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov public Resources getResources() { 2701d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return mRes; 271b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov } 272e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 273e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 274e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public ContentResolver getContentResolver() { 275e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return mResolver; 276e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 277d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 278d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov @Override 279d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public ApplicationInfo getApplicationInfo() { 280d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov ApplicationInfo ai = new ApplicationInfo(); 281d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov ai.packageName = "contactsTestPackage"; 282d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return ai; 283d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 28424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 28524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // All permission checks are implemented to simply check against the granted permission set. 28624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 28724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 28824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkPermission(String permission, int pid, int uid) { 28924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return checkCallingPermission(permission); 29024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 29124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 29224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 29324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkCallingPermission(String permission) { 29424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (mGrantedPermissions.contains(permission)) { 29524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return PackageManager.PERMISSION_GRANTED; 29624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } else { 29724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return PackageManager.PERMISSION_DENIED; 29824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 29924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 30024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 30124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 302eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { 303eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return checkCallingUriPermission(uri, modeFlags); 304eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 305eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 306eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee @Override 307eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public int checkCallingUriPermission(Uri uri, int modeFlags) { 308eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee if (mGrantedUriPermissions.contains(uri)) { 309eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return PackageManager.PERMISSION_GRANTED; 310eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } else { 311eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return PackageManager.PERMISSION_DENIED; 312eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 313eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 314eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 315eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee @Override 31624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkCallingOrSelfPermission(String permission) { 31724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return checkCallingPermission(permission); 31824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 31924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 32024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 32124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforcePermission(String permission, int pid, int uid, String message) { 32224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceCallingPermission(permission, message); 32324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 32424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 32524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 32624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforceCallingPermission(String permission, String message) { 32724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!mGrantedPermissions.contains(permission)) { 32824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new SecurityException(message); 32924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 33024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 33124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 33224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 33324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforceCallingOrSelfPermission(String permission, String message) { 33424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceCallingPermission(permission, message); 33524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 336619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 337619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 33872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov static String sCallingPackage = null; 3391d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 3401d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey void ensureCallingPackage() { 3411d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey sCallingPackage = this.packageName; 3421d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 3431d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 344ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContact(String name) { 3451d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 346ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann long rawContactId = createRawContact(); 34747fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov createName(rawContactId, name); 34847fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov return rawContactId; 349ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 350ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 351ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContact() { 3521d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 353ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 354ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 35547fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov Uri rawContactUri = resolver.insert(RawContacts.CONTENT_URI, values); 35647fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov return ContentUris.parseId(rawContactUri); 357ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 358ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 359ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContactWithStatus(String name, String address, 3601d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey String status) { 361ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann final long rawContactId = createRawContact(name); 3621d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final long dataId = createEmail(rawContactId, address); 3631d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey createStatus(dataId, status); 3641d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return rawContactId; 3651d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 3661d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 367ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createName(long contactId, String name) { 3681d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 369ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 3705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, contactId); 371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); 374ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(CommonDataKinds.StructuredName.FAMILY_NAME, name); 3756cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 3766cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactId), RawContacts.Data.CONTENT_DIRECTORY); 377ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 379ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 380ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 381ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createPhone(long contactId, String phoneNumber) { 3821d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 383ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 3845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, contactId); 385ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 386ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 3876bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 3883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(ContactsContract.CommonDataKinds.Phone.TYPE, 3893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov ContactsContract.CommonDataKinds.Phone.TYPE_HOME); 390ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber); 3916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 3926cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactId), RawContacts.Data.CONTENT_DIRECTORY); 393ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 394ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 395ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 396ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3971d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public long createEmail(long contactId, String address) { 3981d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 3991d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final ContentValues values = new ContentValues(); 4001d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.RAW_CONTACT_ID, contactId); 4011d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.IS_PRIMARY, 1); 4021d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 4031d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 4041d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Email.TYPE, Email.TYPE_HOME); 4051d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Email.DATA, address); 4061d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 4071d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey contactId), RawContacts.Data.CONTENT_DIRECTORY); 4081d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 4091d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return ContentUris.parseId(dataUri); 4101d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 4111d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 4121d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public long createStatus(long dataId, String status) { 4131d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 4141d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final ContentValues values = new ContentValues(); 4151d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(StatusUpdates.DATA_ID, dataId); 4161d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(StatusUpdates.STATUS, status); 4171d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri dataUri = resolver.insert(StatusUpdates.CONTENT_URI, values); 4181d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return ContentUris.parseId(dataUri); 4191d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 4201d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public void updateException(String packageProvider, String packageClient, boolean allowAccess) { 42267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey throw new UnsupportedOperationException("RestrictionExceptions are hard-coded"); 423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 425d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public long getContactForRawContact(long rawContactId) { 4261d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 427d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 428d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final Cursor cursor = resolver.query(contactUri, Projections.PROJ_RAW_CONTACTS, null, 429ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null, null); 430ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!cursor.moveToFirst()) { 431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 432ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey throw new RuntimeException("Contact didn't have an aggregate"); 433ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 434d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final long aggId = cursor.getLong(Projections.COL_CONTACTS_ID); 435ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 436ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return aggId; 437ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 439d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public int getDataCountForContact(long contactId) { 4401d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 441d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri contactUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 442d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov contactId), Contacts.Data.CONTENT_DIRECTORY); 443ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Cursor cursor = resolver.query(contactUri, Projections.PROJ_ID, null, null, 444ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null); 445ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int count = cursor.getCount(); 446ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 447ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return count; 448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4501d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public int getDataCountForRawContact(long rawContactId) { 4511d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 4521d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri contactUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 4531d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey rawContactId), Contacts.Data.CONTENT_DIRECTORY); 4541d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final Cursor cursor = resolver.query(contactUri, Projections.PROJ_ID, null, null, 4551d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey null); 4561d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final int count = cursor.getCount(); 4571d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey cursor.close(); 4581d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return count; 4591d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 4601d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 461ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public void setSuperPrimaryPhone(long dataId) { 4621d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 463ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 464ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 465ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 466ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri updateUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId); 467ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey resolver.update(updateUri, values, null, null); 468ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 469ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 470ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createGroup(String groupName) { 4711d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 472ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 47367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.put(ContactsContract.Groups.RES_PACKAGE, packageName); 474ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(ContactsContract.Groups.TITLE, groupName); 475ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri groupUri = resolver.insert(ContactsContract.Groups.CONTENT_URI, values); 476ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(groupUri); 477ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 478ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long createGroupMembership(long rawContactId, long groupId) { 4801d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 4825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, rawContactId); 483ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.MIMETYPE, CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE); 484ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupId); 4856cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 4865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId), RawContacts.Data.CONTENT_DIRECTORY); 487ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 488ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 489ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 490ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 49147fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov protected void setAggregationException(int type, long rawContactId1, long rawContactId2) { 49247fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov ContentValues values = new ContentValues(); 49347fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 49447fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 49547fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.TYPE, type); 49647fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov resolver.update(AggregationExceptions.CONTENT_URI, values, null, null); 49747fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov } 49847fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov 499bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void setAccounts(Account[] accounts) { 500bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mAccounts = accounts; 501bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 502bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 503ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 504ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Various internal database projections. 505ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 506ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private interface Projections { 507ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey static final String[] PROJ_ID = new String[] { 508ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey BaseColumns._ID, 509ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 510ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 511ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey static final int COL_ID = 0; 512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 513d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov static final String[] PROJ_RAW_CONTACTS = new String[] { 514d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID 515ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 516ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 517d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov static final int COL_CONTACTS_ID = 0; 518ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 519619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey} 520