ContactsActor.java revision c19d5519535bc05225eac5f7dfb830fda48497de
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 19bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.Account; 20bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AccountManager; 21bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AccountManagerCallback; 22bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AccountManagerFuture; 23bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.AuthenticatorException; 24bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.OnAccountsUpdateListener; 25bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.accounts.OperationCanceledException; 26b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport android.app.admin.DevicePolicyManager; 27bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikovimport android.content.ContentProvider; 28e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.ContentResolver; 29ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.content.ContentUris; 30ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.content.ContentValues; 31619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.Context; 329701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onukiimport android.content.ContextWrapper; 330bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onukiimport android.content.Intent; 3435997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.content.SharedPreferences; 35619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo; 36619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager; 3772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.pm.ProviderInfo; 38b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport android.content.pm.UserInfo; 395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.content.res.Configuration; 40b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.content.res.Resources; 41ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.Cursor; 4289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.location.Country; 4389b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.location.CountryDetector; 4489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.location.CountryListener; 45ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.net.Uri; 46b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport android.os.Bundle; 47bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 48b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport android.os.IUserManager; 4989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.os.Looper; 50b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport android.os.UserHandle; 51b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport android.os.UserManager; 52ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.BaseColumns; 53619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.provider.ContactsContract; 5447fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 55ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds; 5689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 5789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 58e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 59ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Data; 60e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 611d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkeyimport android.provider.ContactsContract.StatusUpdates; 62619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.IsolatedContext; 63619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.RenamingDelegatingContext; 64619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.mock.MockContentResolver; 65619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.test.mock.MockContext; 669701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onukiimport android.util.Log; 67619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 68400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onukiimport com.android.providers.contacts.util.ContactsPermissions; 6938210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.util.MockSharedPreferences; 703a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee 7138210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.google.android.collect.Sets; 7238210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki 73f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport java.io.File; 74bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport java.io.IOException; 75b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport java.util.ArrayList; 7624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport java.util.Arrays; 77b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onukiimport java.util.List; 785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport java.util.Locale; 7924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoroimport java.util.Set; 80619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 81619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey/** 82619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Helper class that encapsulates an "actor" which is owned by a specific 83619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name. It correctly maintains a wrapped {@link Context} and an 84619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * attached {@link MockContentResolver}. Multiple actors can be used to test 85619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * security scenarios between multiple packages. 86619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 87619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeypublic class ContactsActor { 88619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final String FILENAME_PREFIX = "test."; 89619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 90619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_GREY = "edu.example.grey"; 91619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_RED = "net.example.red"; 92619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_GREEN = "com.example.green"; 93619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public static final String PACKAGE_BLUE = "org.example.blue"; 94619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 95619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public Context context; 96619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public String packageName; 97619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public MockContentResolver resolver; 98bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov public ContentProvider provider; 9989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private Country mMockCountry = new Country("us", 0); 10089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 101bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Account[] mAccounts = new Account[0]; 102bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 10324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private Set<String> mGrantedPermissions = Sets.newHashSet(); 104eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee private final Set<Uri> mGrantedUriPermissions = Sets.newHashSet(); 10524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 10689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov private CountryDetector mMockCountryDetector = new CountryDetector(null){ 10789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 10889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public Country detectCountry() { 10989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov return mMockCountry; 11089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 11189b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 11289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 11389b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public void addCountryListener(CountryListener listener, Looper looper) { 11489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 11589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov }; 116619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 117bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private AccountManager mMockAccountManager; 118bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 119bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private class MockAccountManager extends AccountManager { 120bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public MockAccountManager(Context conteact) { 121bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov super(context, null, null); 122bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 123bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 124bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 125bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener, 126bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Handler handler, boolean updateImmediately) { 127bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // do nothing 128bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 129bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 130bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 131bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public Account[] getAccounts() { 132bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return mAccounts; 133bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 134bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 135bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 136bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures( 137bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String type, final String[] features, 138bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov AccountManagerCallback<Account[]> callback, Handler handler) { 139bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return null; 140bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 141bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 142bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 143bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public String blockingGetAuthToken(Account account, String authTokenType, 144bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean notifyAuthFailure) 145bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov throws OperationCanceledException, IOException, AuthenticatorException { 146bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return null; 147bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 148bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 149bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 150b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public MockUserManager mockUserManager; 151b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 152b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public static class MockUserManager extends UserManager { 153b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public static UserInfo createUserInfo(String name, int id, int groupId, int flags) { 154b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final UserInfo ui = new UserInfo(); 155b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki ui.name = name; 156b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki ui.id = id; 157b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki ui.profileGroupId = groupId; 158b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki ui.flags = flags | UserInfo.FLAG_INITIALIZED; 159b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return ui; 160b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 161b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 162b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public static final UserInfo PRIMARY_USER = createUserInfo("primary", 0, 0, 163b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN); 164b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public static final UserInfo CORP_USER = createUserInfo("corp", 10, 0, 165b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki UserInfo.FLAG_MANAGED_PROFILE); 166b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public static final UserInfo SECONDARY_USER = createUserInfo("2nd", 11, 11, 0); 167b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 168b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki /** "My" user. Set it to change the current user. */ 169b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public int myUser = 0; 170b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 171b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki private ArrayList<UserInfo> mUsers = new ArrayList<>(); 172b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 173b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public MockUserManager(Context context) { 174b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki super(context, /* IUserManager */ null); 175b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 176b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mUsers.add(PRIMARY_USER); // Add the primary user. 177b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 178b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 179b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki /** Replaces users. */ 180b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public void setUsers(UserInfo... users) { 181b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mUsers.clear(); 182b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki for (UserInfo ui : users) { 183b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mUsers.add(ui); 184b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 185b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 186b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 187b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 188b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public int getUserHandle() { 189b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return myUser; 190b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 191b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 192b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 193b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public UserInfo getUserInfo(int userHandle) { 194b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki for (UserInfo ui : mUsers) { 195b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (ui.id == userHandle) { 196b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return ui; 197b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 198b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 199b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return null; 200b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 201b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 202b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 203b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public UserInfo getProfileParent(int userHandle) { 204b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki final UserInfo child = getUserInfo(userHandle); 205b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (child == null) { 206b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return null; 207b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 208b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki for (UserInfo ui : mUsers) { 209b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (ui.id != userHandle && ui.id == child.profileGroupId) { 210b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return ui; 211b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 212b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 213b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return null; 214b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 215b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 216b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 217b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public List<UserInfo> getUsers() { 218b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mUsers; 219b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 220b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 221b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki @Override 222b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public Bundle getUserRestrictions(UserHandle userHandle) { 223b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return new Bundle(); 224b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 2253a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee 2263a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee @Override 2273a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee public boolean hasUserRestriction(String restrictionKey) { 2283a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee return false; 2293a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee } 2303a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee 2313a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee @Override 2323a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) { 2333a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee return false; 2343a219cc3f5045bdebfcd975bf857c6ff26886a22Yorke Lee } 235b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 236b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 2379701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki /** 2389701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * A context wrapper that reports a different user id. 2399701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * 2409701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * TODO This should override getSystemService() and returns a UserManager that returns the 2419701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * same, altered user ID too. 2429701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki */ 2439701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public static class AlteringUserContext extends ContextWrapper { 2449701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki private final int mUserId; 2459701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 2469701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public AlteringUserContext(Context base, int userId) { 2479701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki super(base); 2489701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mUserId = userId; 2499701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2509701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 2519701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 2529701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public int getUserId() { 2539701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki return mUserId; 2549701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2559701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2569701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 257e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private IsolatedContext mProviderContext; 258e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 259619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 260619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Create an "actor" using the given parent {@link Context} and the specific 261619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name. Internally, all {@link Context} method calls are passed to 262619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * a new instance of {@link RestrictionMockContext}, which stubs out the 263619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * security infrastructure. 264619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 265b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public ContactsActor(final Context overallContext, String packageName, 266bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov Class<? extends ContentProvider> providerClass, String authority) throws Exception { 267400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki 268400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki // Force permission check even when called by self. 269400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki ContactsPermissions.ALLOW_SELF_CALL = false; 270400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki 271619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey resolver = new MockContentResolver(); 27224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro context = new RestrictionMockContext(overallContext, packageName, resolver, 273eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedPermissions, mGrantedUriPermissions); 274e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov this.packageName = packageName; 275619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 276212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // Let the Secure class initialize the settings provider, which is done when we first 277212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // tries to get any setting. Because our mock context/content resolver doesn't have the 278212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // settings provider, we need to do this with an actual context, before other classes 279212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // try to do this with a mock context. 280212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // (Otherwise ContactsProvider2.initialzie() will crash trying to get a setting with 281212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // a mock context.) 282212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki android.provider.Settings.Secure.getString(overallContext.getContentResolver(), "dummy"); 283212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki 284bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(context, 285bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov overallContext, FILENAME_PREFIX); 28635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki mProviderContext = new IsolatedContext(resolver, targetContextWrapper) { 28735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private final MockSharedPreferences mPrefs = new MockSharedPreferences(); 28889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 28989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 290f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro public File getFilesDir() { 291f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // TODO: Need to figure out something more graceful than this. 292f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return new File("/data/data/com.android.providers.contacts.tests/files"); 293f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 294f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 295f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 29689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public Object getSystemService(String name) { 29789b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov if (Context.COUNTRY_DETECTOR.equals(name)) { 29889b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov return mMockCountryDetector; 29989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 300bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (Context.ACCOUNT_SERVICE.equals(name)) { 301bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return mMockAccountManager; 302bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 303b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (Context.USER_SERVICE.equals(name)) { 304b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mockUserManager; 305b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 306b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki // Use overallContext here; super.getSystemService() somehow won't return 307b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki // DevicePolicyManager. 308b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return overallContext.getSystemService(name); 30989b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 31035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 31135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki @Override 31235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki public SharedPreferences getSharedPreferences(String name, int mode) { 31335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki return mPrefs; 31435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 3159701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 3169701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 3179701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public int getUserId() { 3189701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki return mockUserManager.getUserHandle(); 3199701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 32089b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov }; 321bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 322bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mMockAccountManager = new MockAccountManager(mProviderContext); 323b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mockUserManager = new MockUserManager(mProviderContext); 324e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov provider = addProvider(providerClass, authority); 325e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 326e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 327b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public Context getProviderContext() { 328b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mProviderContext; 329b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 330b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 3319701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public <T extends ContentProvider> T addProvider(Class<T> providerClass, 332e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov String authority) throws Exception { 3339701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki return addProvider(providerClass, authority, mProviderContext); 3349701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 3359701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 3369701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public <T extends ContentProvider> T addProvider(Class<T> providerClass, 3379701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki String authority, Context providerContext) throws Exception { 3389701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki T provider = providerClass.newInstance(); 33972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ProviderInfo info = new ProviderInfo(); 34071142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki 34171142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki // Here, authority can have "user-id@". We want to use it for addProvider, but provider 34271142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki // info shouldn't have it. 34371142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki info.authority = stripOutUserIdFromAuthority(authority); 3449701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki provider.attachInfoForTesting(providerContext, info); 345bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov resolver.addProvider(authority, provider); 346c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki 347c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki // In case of LegacyTest, "authority" here is actually multiple authorities. 348c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki // Register all authority here. 349c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki for (String a : authority.split(";")) { 350c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki resolver.addProvider(a, provider); 351c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki } 352e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return provider; 353619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 354619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 35571142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki /** 35671142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki * Takes an provider authority. If it has "userid@", then remove it. 35771142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki */ 35871142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki private String stripOutUserIdFromAuthority(String authority) { 35971142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki final int pos = authority.indexOf('@'); 36071142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki return pos < 0 ? authority : authority.substring(pos + 1); 36171142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki } 36271142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki 36324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void addPermissions(String... permissions) { 36424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions.addAll(Arrays.asList(permissions)); 36524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 36624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 36724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void removePermissions(String... permissions) { 36824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions.removeAll(Arrays.asList(permissions)); 36924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 37024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 371eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public void addUriPermissions(Uri... uris) { 372eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions.addAll(Arrays.asList(uris)); 373eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 374eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 375eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public void removeUriPermissions(Uri... uris) { 376eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions.removeAll(Arrays.asList(uris)); 377eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 378eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 379619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 380619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Mock {@link Context} that reports specific well-known values for testing 381619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * data protection. The creator can override the owner package name, and 382619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * force the {@link PackageManager} to always return a well-known package 383619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * list for any call to {@link PackageManager#getPackagesForUid(int)}. 384619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * <p> 385619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * For example, the creator could request that the {@link Context} lives in 386619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name "com.example.red", and also cause the {@link PackageManager} 387619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * to report that no UID contains that package name. 388619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 389619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static class RestrictionMockContext extends MockContext { 390b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov private final Context mOverallContext; 391b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov private final String mReportedPackageName; 39272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private final ContactsMockPackageManager mPackageManager; 393e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private final ContentResolver mResolver; 3941d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey private final Resources mRes; 39524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private final Set<String> mGrantedPermissions; 396eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee private final Set<Uri> mGrantedUriPermissions; 397619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 398619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 399619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Create a {@link Context} under the given package name. 400619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 401e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public RestrictionMockContext(Context overallContext, String reportedPackageName, 402eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee ContentResolver resolver, Set<String> grantedPermissions, 403eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee Set<Uri> grantedUriPermissions) { 404b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov mOverallContext = overallContext; 405619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mReportedPackageName = reportedPackageName; 406e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov mResolver = resolver; 40724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions = grantedPermissions; 408eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions = grantedUriPermissions; 4091d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 41072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mPackageManager = new ContactsMockPackageManager(); 411619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(1000, PACKAGE_GREY); 412619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(2000, PACKAGE_RED); 413619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(3000, PACKAGE_GREEN); 414619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(4000, PACKAGE_BLUE); 4151d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 4165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Resources resources = overallContext.getResources(); 4175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Configuration configuration = new Configuration(resources.getConfiguration()); 4185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov configuration.locale = Locale.US; 4195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov resources.updateConfiguration(configuration, resources.getDisplayMetrics()); 420ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann mRes = resources; 421619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 422619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 423619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 424619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public String getPackageName() { 425619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mReportedPackageName; 426619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 427619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 428619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 429619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public PackageManager getPackageManager() { 430619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mPackageManager; 431619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 432b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov 433b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov @Override 434b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov public Resources getResources() { 4351d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return mRes; 436b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov } 437e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 438e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 439e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public ContentResolver getContentResolver() { 440e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return mResolver; 441e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 442d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 443d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov @Override 444d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public ApplicationInfo getApplicationInfo() { 445d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov ApplicationInfo ai = new ApplicationInfo(); 446d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov ai.packageName = "contactsTestPackage"; 447d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return ai; 448d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 44924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 45024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // All permission checks are implemented to simply check against the granted permission set. 45124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 45224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 45324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkPermission(String permission, int pid, int uid) { 45424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return checkCallingPermission(permission); 45524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 45624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 45724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 45824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkCallingPermission(String permission) { 45924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (mGrantedPermissions.contains(permission)) { 46024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return PackageManager.PERMISSION_GRANTED; 46124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } else { 46224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return PackageManager.PERMISSION_DENIED; 46324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 46424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 46524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 46624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 467eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { 468eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return checkCallingUriPermission(uri, modeFlags); 469eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 470eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 471eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee @Override 472eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public int checkCallingUriPermission(Uri uri, int modeFlags) { 473eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee if (mGrantedUriPermissions.contains(uri)) { 474eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return PackageManager.PERMISSION_GRANTED; 475eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } else { 476eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return PackageManager.PERMISSION_DENIED; 477eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 478eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 479eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 480eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee @Override 48124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkCallingOrSelfPermission(String permission) { 48224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return checkCallingPermission(permission); 48324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 48424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 48524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 48624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforcePermission(String permission, int pid, int uid, String message) { 48724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceCallingPermission(permission, message); 48824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 48924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 49024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 49124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforceCallingPermission(String permission, String message) { 49224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!mGrantedPermissions.contains(permission)) { 49324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new SecurityException(message); 49424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 49524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 49624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 49724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 49824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforceCallingOrSelfPermission(String permission, String message) { 49924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceCallingPermission(permission, message); 50024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 5010bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki 5020bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki @Override 5030bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki public void sendBroadcast(Intent intent) { 5040bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki mOverallContext.sendBroadcast(intent); 5050bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki } 5060bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki 5070bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki @Override 5080bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki public void sendBroadcast(Intent intent, String receiverPermission) { 5090bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki mOverallContext.sendBroadcast(intent, receiverPermission); 5100bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki } 511619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 512619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 51372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov static String sCallingPackage = null; 5141d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 5151d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey void ensureCallingPackage() { 5161d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey sCallingPackage = this.packageName; 5171d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 5181d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 519ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContact(String name) { 5201d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 521ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann long rawContactId = createRawContact(); 52247fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov createName(rawContactId, name); 52347fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov return rawContactId; 524ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 525ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 526ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContact() { 5271d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 528ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 529ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 53047fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov Uri rawContactUri = resolver.insert(RawContacts.CONTENT_URI, values); 53147fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov return ContentUris.parseId(rawContactUri); 532ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 533ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 534ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContactWithStatus(String name, String address, 5351d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey String status) { 536ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann final long rawContactId = createRawContact(name); 5371d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final long dataId = createEmail(rawContactId, address); 5381d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey createStatus(dataId, status); 5391d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return rawContactId; 5401d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 5411d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 542ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createName(long contactId, String name) { 5431d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 544ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 5455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, contactId); 546ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 547ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 548ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); 549ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(CommonDataKinds.StructuredName.FAMILY_NAME, name); 5506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 5516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactId), RawContacts.Data.CONTENT_DIRECTORY); 552ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 553ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 554ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 555ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 556ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createPhone(long contactId, String phoneNumber) { 5571d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 558ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 5595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, contactId); 560ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 561ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 5626bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 5633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(ContactsContract.CommonDataKinds.Phone.TYPE, 5643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov ContactsContract.CommonDataKinds.Phone.TYPE_HOME); 565ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber); 5666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 5676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactId), RawContacts.Data.CONTENT_DIRECTORY); 568ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 569ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 570ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 571ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5721d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public long createEmail(long contactId, String address) { 5731d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 5741d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final ContentValues values = new ContentValues(); 5751d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.RAW_CONTACT_ID, contactId); 5761d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.IS_PRIMARY, 1); 5771d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 5781d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 5791d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Email.TYPE, Email.TYPE_HOME); 5801d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Email.DATA, address); 5811d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 5821d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey contactId), RawContacts.Data.CONTENT_DIRECTORY); 5831d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 5841d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return ContentUris.parseId(dataUri); 5851d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 5861d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 5871d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public long createStatus(long dataId, String status) { 5881d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 5891d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final ContentValues values = new ContentValues(); 5901d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(StatusUpdates.DATA_ID, dataId); 5911d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(StatusUpdates.STATUS, status); 5921d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri dataUri = resolver.insert(StatusUpdates.CONTENT_URI, values); 5931d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return ContentUris.parseId(dataUri); 5941d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 5951d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 596ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public void updateException(String packageProvider, String packageClient, boolean allowAccess) { 59767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey throw new UnsupportedOperationException("RestrictionExceptions are hard-coded"); 598ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 599ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 600d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public long getContactForRawContact(long rawContactId) { 6011d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 602d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 603d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final Cursor cursor = resolver.query(contactUri, Projections.PROJ_RAW_CONTACTS, null, 604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null, null); 605ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!cursor.moveToFirst()) { 606ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 607ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey throw new RuntimeException("Contact didn't have an aggregate"); 608ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 609d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final long aggId = cursor.getLong(Projections.COL_CONTACTS_ID); 610ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 611ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return aggId; 612ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 613ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 614d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public int getDataCountForContact(long contactId) { 6151d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 616d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri contactUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 617d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov contactId), Contacts.Data.CONTENT_DIRECTORY); 618ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Cursor cursor = resolver.query(contactUri, Projections.PROJ_ID, null, null, 619ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null); 620ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int count = cursor.getCount(); 621ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 622ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return count; 623ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 624ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6251d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public int getDataCountForRawContact(long rawContactId) { 6261d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 6271d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri contactUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 6281d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey rawContactId), Contacts.Data.CONTENT_DIRECTORY); 6291d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final Cursor cursor = resolver.query(contactUri, Projections.PROJ_ID, null, null, 6301d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey null); 6311d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final int count = cursor.getCount(); 6321d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey cursor.close(); 6331d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return count; 6341d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 6351d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 636ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public void setSuperPrimaryPhone(long dataId) { 6371d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 638ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 639ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 640ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 641ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri updateUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId); 642ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey resolver.update(updateUri, values, null, null); 643ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 644ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 645ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createGroup(String groupName) { 6461d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 647ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 64867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.put(ContactsContract.Groups.RES_PACKAGE, packageName); 649ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(ContactsContract.Groups.TITLE, groupName); 650ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri groupUri = resolver.insert(ContactsContract.Groups.CONTENT_URI, values); 651ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(groupUri); 652ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 653ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long createGroupMembership(long rawContactId, long groupId) { 6551d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 656ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 6575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, rawContactId); 658ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.MIMETYPE, CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE); 659ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupId); 6606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 6615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId), RawContacts.Data.CONTENT_DIRECTORY); 662ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 663ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 664ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 665ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 66647fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov protected void setAggregationException(int type, long rawContactId1, long rawContactId2) { 66747fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov ContentValues values = new ContentValues(); 66847fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 66947fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 67047fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.TYPE, type); 67147fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov resolver.update(AggregationExceptions.CONTENT_URI, values, null, null); 67247fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov } 67347fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov 674bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void setAccounts(Account[] accounts) { 675bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mAccounts = accounts; 676bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 677bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 678ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 679ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Various internal database projections. 680ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 681ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private interface Projections { 682ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey static final String[] PROJ_ID = new String[] { 683ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey BaseColumns._ID, 684ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 685ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 686ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey static final int COL_ID = 0; 687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 688d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov static final String[] PROJ_RAW_CONTACTS = new String[] { 689d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID 690ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 691ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 692d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov static final int COL_CONTACTS_ID = 0; 693ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 694619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey} 695