1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16package com.android.providers.contacts; 17 18import com.android.providers.contacts.util.ContactsPermissions; 19 20import android.content.ContentValues; 21import android.content.Context; 22import android.content.Intent; 23import android.content.res.AssetFileDescriptor; 24import android.database.Cursor; 25import android.database.sqlite.SQLiteDatabase; 26import android.net.Uri; 27import android.os.CancellationSignal; 28import android.provider.ContactsContract.Intents; 29 30import java.io.FileDescriptor; 31import java.io.FileNotFoundException; 32import java.io.PrintWriter; 33import java.util.Locale; 34 35/** 36 * Simple content provider to handle directing profile-specific calls against a separate 37 * database from the rest of contacts. 38 */ 39public class ProfileProvider extends AbstractContactsProvider { 40 private static final String READ_CONTACTS_PERMISSION = "android.permission.READ_CONTACTS"; 41 42 // The Contacts provider handles most of the logic - this provider is only invoked when the 43 // URI belongs to a profile action, setting up the proper database. 44 private final ContactsProvider2 mDelegate; 45 46 public ProfileProvider(ContactsProvider2 delegate) { 47 mDelegate = delegate; 48 } 49 50 @Override 51 protected ProfileDatabaseHelper newDatabaseHelper(Context context) { 52 return ProfileDatabaseHelper.getInstance(context); 53 } 54 55 public ProfileDatabaseHelper getDatabaseHelper() { 56 return (ProfileDatabaseHelper) super.getDatabaseHelper(); 57 } 58 59 @Override 60 protected ThreadLocal<ContactsTransaction> getTransactionHolder() { 61 return mDelegate.getTransactionHolder(); 62 } 63 64 @Override 65 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 66 String sortOrder) { 67 return query(uri, projection, selection, selectionArgs, sortOrder, null); 68 } 69 70 @Override 71 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 72 String sortOrder, CancellationSignal cancellationSignal) { 73 incrementStats(mQueryStats); 74 try { 75 return mDelegate.queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1, 76 cancellationSignal); 77 } finally { 78 finishOperation(); 79 } 80 } 81 82 @Override 83 protected Uri insertInTransaction(Uri uri, ContentValues values) { 84 useProfileDbForTransaction(); 85 return mDelegate.insertInTransaction(uri, values); 86 } 87 88 @Override 89 protected int updateInTransaction(Uri uri, ContentValues values, String selection, 90 String[] selectionArgs) { 91 useProfileDbForTransaction(); 92 return mDelegate.updateInTransaction(uri, values, selection, selectionArgs); 93 } 94 95 @Override 96 protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 97 useProfileDbForTransaction(); 98 return mDelegate.deleteInTransaction(uri, selection, selectionArgs); 99 } 100 101 @Override 102 public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 103 return mDelegate.openAssetFileLocal(uri, mode); 104 } 105 106 private void useProfileDbForTransaction() { 107 ContactsTransaction transaction = getCurrentTransaction(); 108 SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); 109 transaction.startTransactionForDb(db, ContactsProvider2.PROFILE_DB_TAG, this); 110 } 111 112 @Override 113 protected void notifyChange() { 114 mDelegate.notifyChange(); 115 } 116 117 protected void notifyChange(boolean syncToNetwork, boolean syncToMetadataNetWork) { 118 mDelegate.notifyChange(syncToNetwork, syncToMetadataNetWork); 119 } 120 121 protected Locale getLocale() { 122 return mDelegate.getLocale(); 123 } 124 125 @Override 126 public void onBegin() { 127 mDelegate.onBeginTransactionInternal(true); 128 } 129 130 @Override 131 public void onCommit() { 132 mDelegate.onCommitTransactionInternal(true); 133 sendProfileChangedBroadcast(); 134 } 135 136 @Override 137 public void onRollback() { 138 mDelegate.onRollbackTransactionInternal(true); 139 } 140 141 @Override 142 protected boolean yield(ContactsTransaction transaction) { 143 return mDelegate.yield(transaction); 144 } 145 146 @Override 147 public String getType(Uri uri) { 148 return mDelegate.getType(uri); 149 } 150 151 /** Use only for debug logging */ 152 @Override 153 public String toString() { 154 return "ProfileProvider"; 155 } 156 157 private void sendProfileChangedBroadcast() { 158 final Intent intent = new Intent(Intents.ACTION_PROFILE_CHANGED); 159 mDelegate.getContext().sendBroadcast(intent, READ_CONTACTS_PERMISSION); 160 // TODO b/35323708 update user profile data here instead of notifying Settings 161 intent.setPackage("com.android.settings"); 162 mDelegate.getContext().sendBroadcast(intent, READ_CONTACTS_PERMISSION); 163 } 164 165 @Override 166 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 167 dump(pw, "Profile"); 168 } 169} 170