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 } 235f2d3e8cb095348535e5ad3b9babccfa15bc31257Makoto Onuki 236f2d3e8cb095348535e5ad3b9babccfa15bc31257Makoto Onuki @Override 237f2d3e8cb095348535e5ad3b9babccfa15bc31257Makoto Onuki public boolean isSameProfileGroup(int userId, int otherUserId) { 238f2d3e8cb095348535e5ad3b9babccfa15bc31257Makoto Onuki return getUserInfo(userId).profileGroupId == getUserInfo(otherUserId).profileGroupId; 239f2d3e8cb095348535e5ad3b9babccfa15bc31257Makoto Onuki } 240b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 241b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 2429701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki /** 2439701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * A context wrapper that reports a different user id. 2449701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * 2459701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * TODO This should override getSystemService() and returns a UserManager that returns the 2469701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki * same, altered user ID too. 2479701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki */ 2489701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public static class AlteringUserContext extends ContextWrapper { 2499701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki private final int mUserId; 2509701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 2519701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public AlteringUserContext(Context base, int userId) { 2529701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki super(base); 2539701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki mUserId = userId; 2549701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2559701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 2569701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 2579701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public int getUserId() { 2589701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki return mUserId; 2599701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2609701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 2619701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 262e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private IsolatedContext mProviderContext; 263e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 264619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 265619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Create an "actor" using the given parent {@link Context} and the specific 266619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name. Internally, all {@link Context} method calls are passed to 267619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * a new instance of {@link RestrictionMockContext}, which stubs out the 268619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * security infrastructure. 269619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 270b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public ContactsActor(final Context overallContext, String packageName, 271bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov Class<? extends ContentProvider> providerClass, String authority) throws Exception { 272400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki 273400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki // Force permission check even when called by self. 274400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki ContactsPermissions.ALLOW_SELF_CALL = false; 275400e50c1efeb601f6162bd829fdf33e9dc5252f6Makoto Onuki 276619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey resolver = new MockContentResolver(); 27724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro context = new RestrictionMockContext(overallContext, packageName, resolver, 278f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki mGrantedPermissions, mGrantedUriPermissions) { 279f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki @Override 280f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki public Object getSystemService(String name) { 281f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki if (Context.COUNTRY_DETECTOR.equals(name)) { 282f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki return mMockCountryDetector; 283f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki } 284f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki if (Context.ACCOUNT_SERVICE.equals(name)) { 285f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki return mMockAccountManager; 286f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki } 287f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki if (Context.USER_SERVICE.equals(name)) { 288f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki return mockUserManager; 289f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki } 290f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki // Use overallContext here; super.getSystemService() somehow won't return 291f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki // DevicePolicyManager. 292f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki return overallContext.getSystemService(name); 293f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki } 294f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki 295f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki @Override 296f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki public String getSystemServiceName(Class<?> serviceClass) { 297f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki return overallContext.getSystemServiceName(serviceClass); 298f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki } 299f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki }; 300e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov this.packageName = packageName; 301619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 302212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // Let the Secure class initialize the settings provider, which is done when we first 303212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // tries to get any setting. Because our mock context/content resolver doesn't have the 304212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // settings provider, we need to do this with an actual context, before other classes 305212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // try to do this with a mock context. 306212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // (Otherwise ContactsProvider2.initialzie() will crash trying to get a setting with 307212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki // a mock context.) 308212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki android.provider.Settings.Secure.getString(overallContext.getContentResolver(), "dummy"); 309212975b9dbb3c164e11732b98266eb7361e27ac5Makoto Onuki 310bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(context, 311bee1a6b2e7cbea778195890e442c9e50f2a4e6d9Dmitri Plotnikov overallContext, FILENAME_PREFIX); 31235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki mProviderContext = new IsolatedContext(resolver, targetContextWrapper) { 31335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private final MockSharedPreferences mPrefs = new MockSharedPreferences(); 31489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov 31589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov @Override 316f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro public File getFilesDir() { 317f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // TODO: Need to figure out something more graceful than this. 318f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return new File("/data/data/com.android.providers.contacts.tests/files"); 319f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 320f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 321f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 32289b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov public Object getSystemService(String name) { 32389b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov if (Context.COUNTRY_DETECTOR.equals(name)) { 32489b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov return mMockCountryDetector; 32589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 326bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (Context.ACCOUNT_SERVICE.equals(name)) { 327bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return mMockAccountManager; 328bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 329b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki if (Context.USER_SERVICE.equals(name)) { 330b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mockUserManager; 331b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 332b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki // Use overallContext here; super.getSystemService() somehow won't return 333b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki // DevicePolicyManager. 334b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return overallContext.getSystemService(name); 33589b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov } 33635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 33735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki @Override 3386040ab71df843cbb9562ded8b819bfff1c0d9838Victor Chang public String getSystemServiceName(Class<?> serviceClass) { 3396040ab71df843cbb9562ded8b819bfff1c0d9838Victor Chang return overallContext.getSystemServiceName(serviceClass); 3406040ab71df843cbb9562ded8b819bfff1c0d9838Victor Chang } 3416040ab71df843cbb9562ded8b819bfff1c0d9838Victor Chang 3426040ab71df843cbb9562ded8b819bfff1c0d9838Victor Chang @Override 34335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki public SharedPreferences getSharedPreferences(String name, int mode) { 34435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki return mPrefs; 34535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 3469701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 3479701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki @Override 3489701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public int getUserId() { 3499701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki return mockUserManager.getUserHandle(); 3509701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 351dc653a5c1bed274512ce41e4a6129a65d2b0eeacMakoto Onuki 352dc653a5c1bed274512ce41e4a6129a65d2b0eeacMakoto Onuki @Override 353dc653a5c1bed274512ce41e4a6129a65d2b0eeacMakoto Onuki public void sendBroadcast(Intent intent, String receiverPermission) { 354dc653a5c1bed274512ce41e4a6129a65d2b0eeacMakoto Onuki // Ignore. 355dc653a5c1bed274512ce41e4a6129a65d2b0eeacMakoto Onuki } 35689b7c2b6e0003b17d08002f02d6aeec9f9788c8dDmitri Plotnikov }; 357bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 358bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mMockAccountManager = new MockAccountManager(mProviderContext); 359b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki mockUserManager = new MockUserManager(mProviderContext); 360e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov provider = addProvider(providerClass, authority); 361e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 362e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 363b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki public Context getProviderContext() { 364b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki return mProviderContext; 365b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki } 366b0828df351e8b261ab36c8af37929bf3d9d6a4f9Makoto Onuki 3679701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public <T extends ContentProvider> T addProvider(Class<T> providerClass, 368e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov String authority) throws Exception { 3699701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki return addProvider(providerClass, authority, mProviderContext); 3709701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki } 3719701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki 3729701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki public <T extends ContentProvider> T addProvider(Class<T> providerClass, 3739701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki String authority, Context providerContext) throws Exception { 3749701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki T provider = providerClass.newInstance(); 37572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ProviderInfo info = new ProviderInfo(); 37671142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki 37771142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki // Here, authority can have "user-id@". We want to use it for addProvider, but provider 37871142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki // info shouldn't have it. 37971142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki info.authority = stripOutUserIdFromAuthority(authority); 3809701936fadaf55ef773dd07015b35f99fd5f8a91Makoto Onuki provider.attachInfoForTesting(providerContext, info); 381c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki 382c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki // In case of LegacyTest, "authority" here is actually multiple authorities. 383c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki // Register all authority here. 384c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki for (String a : authority.split(";")) { 385c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki resolver.addProvider(a, provider); 386f3bd980c0ec03db2538e86cadee2c1559f02c85bMakoto Onuki resolver.addProvider("0@" + a, provider); 387c19d5519535bc05225eac5f7dfb830fda48497deMakoto Onuki } 388e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return provider; 389619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 390619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 39171142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki /** 39271142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki * Takes an provider authority. If it has "userid@", then remove it. 39371142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki */ 39471142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki private String stripOutUserIdFromAuthority(String authority) { 39571142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki final int pos = authority.indexOf('@'); 39671142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki return pos < 0 ? authority : authority.substring(pos + 1); 39771142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki } 39871142b333418ac7d589bd7522dad77b967f0bbe1Makoto Onuki 39924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void addPermissions(String... permissions) { 40024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions.addAll(Arrays.asList(permissions)); 40124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 40224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 40324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void removePermissions(String... permissions) { 40424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions.removeAll(Arrays.asList(permissions)); 40524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 40624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 407eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public void addUriPermissions(Uri... uris) { 408eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions.addAll(Arrays.asList(uris)); 409eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 410eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 411eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public void removeUriPermissions(Uri... uris) { 412eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions.removeAll(Arrays.asList(uris)); 413eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 414eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 415619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 416619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Mock {@link Context} that reports specific well-known values for testing 417619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * data protection. The creator can override the owner package name, and 418619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * force the {@link PackageManager} to always return a well-known package 419619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * list for any call to {@link PackageManager#getPackagesForUid(int)}. 420619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * <p> 421619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * For example, the creator could request that the {@link Context} lives in 422619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * package name "com.example.red", and also cause the {@link PackageManager} 423619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * to report that no UID contains that package name. 424619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 425619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static class RestrictionMockContext extends MockContext { 426b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov private final Context mOverallContext; 427b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov private final String mReportedPackageName; 42872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private final ContactsMockPackageManager mPackageManager; 429e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private final ContentResolver mResolver; 4301d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey private final Resources mRes; 43124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private final Set<String> mGrantedPermissions; 432eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee private final Set<Uri> mGrantedUriPermissions; 433619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 434619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 435619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Create a {@link Context} under the given package name. 436619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 437e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public RestrictionMockContext(Context overallContext, String reportedPackageName, 438eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee ContentResolver resolver, Set<String> grantedPermissions, 439eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee Set<Uri> grantedUriPermissions) { 440b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov mOverallContext = overallContext; 441619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mReportedPackageName = reportedPackageName; 442e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov mResolver = resolver; 44324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mGrantedPermissions = grantedPermissions; 444eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee mGrantedUriPermissions = grantedUriPermissions; 4451d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 44672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mPackageManager = new ContactsMockPackageManager(); 447619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(1000, PACKAGE_GREY); 448619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(2000, PACKAGE_RED); 449619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(3000, PACKAGE_GREEN); 450619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mPackageManager.addPackage(4000, PACKAGE_BLUE); 4511d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 4525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Resources resources = overallContext.getResources(); 4535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Configuration configuration = new Configuration(resources.getConfiguration()); 4545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov configuration.locale = Locale.US; 4555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov resources.updateConfiguration(configuration, resources.getDisplayMetrics()); 456ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann mRes = resources; 457619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 458619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 459619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 460619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public String getPackageName() { 461619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mReportedPackageName; 462619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 463619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 464619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey @Override 465619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey public PackageManager getPackageManager() { 466619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mPackageManager; 467619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 468b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov 469b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov @Override 470b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov public Resources getResources() { 4711d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return mRes; 472b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov } 473e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 474e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 475e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public ContentResolver getContentResolver() { 476e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return mResolver; 477e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 478d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 479d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov @Override 480d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public ApplicationInfo getApplicationInfo() { 481d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov ApplicationInfo ai = new ApplicationInfo(); 482d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov ai.packageName = "contactsTestPackage"; 483d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return ai; 484d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 48524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 48624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro // All permission checks are implemented to simply check against the granted permission set. 48724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 48824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 48924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkPermission(String permission, int pid, int uid) { 49024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return checkCallingPermission(permission); 49124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 49224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 49324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 49424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkCallingPermission(String permission) { 49524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (mGrantedPermissions.contains(permission)) { 49624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return PackageManager.PERMISSION_GRANTED; 49724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } else { 49824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return PackageManager.PERMISSION_DENIED; 49924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 50024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 50124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 50224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 503eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { 504eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return checkCallingUriPermission(uri, modeFlags); 505eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 506eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 507eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee @Override 508eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee public int checkCallingUriPermission(Uri uri, int modeFlags) { 509eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee if (mGrantedUriPermissions.contains(uri)) { 510eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return PackageManager.PERMISSION_GRANTED; 511eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } else { 512eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return PackageManager.PERMISSION_DENIED; 513eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 514eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 515eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 516eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee @Override 51724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public int checkCallingOrSelfPermission(String permission) { 51824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return checkCallingPermission(permission); 51924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 52024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 52124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 52224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforcePermission(String permission, int pid, int uid, String message) { 52324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceCallingPermission(permission, message); 52424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 52524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 52624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 52724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforceCallingPermission(String permission, String message) { 52824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!mGrantedPermissions.contains(permission)) { 52924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new SecurityException(message); 53024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 53124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 53224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 53324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro @Override 53424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro public void enforceCallingOrSelfPermission(String permission, String message) { 53524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro enforceCallingPermission(permission, message); 53624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 5370bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki 5380bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki @Override 5390bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki public void sendBroadcast(Intent intent) { 5400bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki mOverallContext.sendBroadcast(intent); 5410bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki } 5420bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki 5430bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki @Override 5440bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki public void sendBroadcast(Intent intent, String receiverPermission) { 5450bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki mOverallContext.sendBroadcast(intent, receiverPermission); 5460bdbe752c3c0cbbef2acb4eca74642aec9195d88Makoto Onuki } 547619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 548619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 54972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov static String sCallingPackage = null; 5501d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 5511d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey void ensureCallingPackage() { 5521d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey sCallingPackage = this.packageName; 5531d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 5541d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 555ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContact(String name) { 5561d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 557ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann long rawContactId = createRawContact(); 55847fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov createName(rawContactId, name); 55947fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov return rawContactId; 560ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 561ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 562ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContact() { 5631d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 564ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 565ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 56647fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov Uri rawContactUri = resolver.insert(RawContacts.CONTENT_URI, values); 56747fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov return ContentUris.parseId(rawContactUri); 568ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 569ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 570ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann public long createRawContactWithStatus(String name, String address, 5711d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey String status) { 572ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann final long rawContactId = createRawContact(name); 5731d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final long dataId = createEmail(rawContactId, address); 5741d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey createStatus(dataId, status); 5751d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return rawContactId; 5761d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 5771d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 578ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createName(long contactId, String name) { 5791d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 580ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 5815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, contactId); 582ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 583ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 584ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); 585ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(CommonDataKinds.StructuredName.FAMILY_NAME, name); 5866cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 5876cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactId), RawContacts.Data.CONTENT_DIRECTORY); 588ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 589ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 590ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 591ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 592ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createPhone(long contactId, String phoneNumber) { 5931d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 594ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 5955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, contactId); 596ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 597ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 5986bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 5993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(ContactsContract.CommonDataKinds.Phone.TYPE, 6003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov ContactsContract.CommonDataKinds.Phone.TYPE_HOME); 601ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber); 6026cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 6036cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactId), RawContacts.Data.CONTENT_DIRECTORY); 604ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 605ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 606ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 607ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6081d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public long createEmail(long contactId, String address) { 6091d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 6101d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final ContentValues values = new ContentValues(); 6111d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.RAW_CONTACT_ID, contactId); 6121d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.IS_PRIMARY, 1); 6131d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 6141d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 6151d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Email.TYPE, Email.TYPE_HOME); 6161d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(Email.DATA, address); 6171d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 6181d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey contactId), RawContacts.Data.CONTENT_DIRECTORY); 6191d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 6201d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return ContentUris.parseId(dataUri); 6211d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 6221d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 6231d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public long createStatus(long dataId, String status) { 6241d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 6251d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final ContentValues values = new ContentValues(); 6261d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(StatusUpdates.DATA_ID, dataId); 6271d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey values.put(StatusUpdates.STATUS, status); 6281d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri dataUri = resolver.insert(StatusUpdates.CONTENT_URI, values); 6291d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return ContentUris.parseId(dataUri); 6301d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 6311d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 632ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public void updateException(String packageProvider, String packageClient, boolean allowAccess) { 63367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey throw new UnsupportedOperationException("RestrictionExceptions are hard-coded"); 634ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 635ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 636d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public long getContactForRawContact(long rawContactId) { 6371d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 638d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri contactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); 639d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final Cursor cursor = resolver.query(contactUri, Projections.PROJ_RAW_CONTACTS, null, 640ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null, null); 641ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!cursor.moveToFirst()) { 642ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 643ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey throw new RuntimeException("Contact didn't have an aggregate"); 644ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 645d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final long aggId = cursor.getLong(Projections.COL_CONTACTS_ID); 646ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 647ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return aggId; 648ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 649ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 650d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public int getDataCountForContact(long contactId) { 6511d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 652d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Uri contactUri = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, 653d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov contactId), Contacts.Data.CONTENT_DIRECTORY); 654ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Cursor cursor = resolver.query(contactUri, Projections.PROJ_ID, null, null, 655ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null); 656ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int count = cursor.getCount(); 657ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 658ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return count; 659ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 660ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6611d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey public int getDataCountForRawContact(long rawContactId) { 6621d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 6631d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey Uri contactUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 6641d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey rawContactId), Contacts.Data.CONTENT_DIRECTORY); 6651d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final Cursor cursor = resolver.query(contactUri, Projections.PROJ_ID, null, null, 6661d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey null); 6671d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey final int count = cursor.getCount(); 6681d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey cursor.close(); 6691d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey return count; 6701d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey } 6711d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey 672ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public void setSuperPrimaryPhone(long dataId) { 6731d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 674ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 675ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_PRIMARY, 1); 676ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.IS_SUPER_PRIMARY, 1); 677ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri updateUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId); 678ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey resolver.update(updateUri, values, null, null); 679ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 680ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 681ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long createGroup(String groupName) { 6821d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 683ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 68467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.put(ContactsContract.Groups.RES_PACKAGE, packageName); 685ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(ContactsContract.Groups.TITLE, groupName); 686ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri groupUri = resolver.insert(ContactsContract.Groups.CONTENT_URI, values); 687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(groupUri); 688ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 689ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 6905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long createGroupMembership(long rawContactId, long groupId) { 6911d9c0e17216ff6df5f73fbc5e784b5965c5026bdJeff Sharkey ensureCallingPackage(); 692ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 6935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, rawContactId); 694ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(Data.MIMETYPE, CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE); 695ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupId); 6966cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Uri insertUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 6975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId), RawContacts.Data.CONTENT_DIRECTORY); 698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Uri dataUri = resolver.insert(insertUri, values); 699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return ContentUris.parseId(dataUri); 700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 701ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 70247fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov protected void setAggregationException(int type, long rawContactId1, long rawContactId2) { 70347fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov ContentValues values = new ContentValues(); 70447fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 70547fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 70647fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov values.put(AggregationExceptions.TYPE, type); 70747fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov resolver.update(AggregationExceptions.CONTENT_URI, values, null, null); 70847fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov } 70947fd3881dfd2a21de29e917b6114974ff0a67b1bDmitri Plotnikov 710bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void setAccounts(Account[] accounts) { 711bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mAccounts = accounts; 712bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 713bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 714ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 715ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Various internal database projections. 716ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 717ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private interface Projections { 718ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey static final String[] PROJ_ID = new String[] { 719ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey BaseColumns._ID, 720ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 721ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 722ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey static final int COL_ID = 0; 723ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 724d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov static final String[] PROJ_RAW_CONTACTS = new String[] { 725d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID 726ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 727ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 728d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov static final int COL_CONTACTS_ID = 0; 729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 730619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey} 731