ContactDirectoryManager.java revision 994c32a995a85937faf59e37a9fc88b526470d7d
172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov/* 272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * 472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * you may not use this file except in compliance with the License. 672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * You may obtain a copy of the License at 772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * 872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * 1072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 1172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 1272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * See the License for the specific language governing permissions and 1472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * limitations under the License 1572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 1672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovpackage com.android.providers.contacts; 1872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 2072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport com.google.android.collect.Lists; 2172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 2272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.ContentValues; 2372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.Context; 2472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.pm.PackageInfo; 2572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.pm.PackageManager; 2672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.pm.PackageManager.NameNotFoundException; 2772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.content.pm.ProviderInfo; 2872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.database.Cursor; 2972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.database.sqlite.SQLiteDatabase; 3072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.net.Uri; 3172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.Binder; 3272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.Bundle; 3372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.Handler; 3472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.HandlerThread; 3572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.Message; 3672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.Process; 3772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.os.SystemClock; 3872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.provider.ContactsContract.Directory; 3972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport android.util.Log; 4072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 4172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport java.util.ArrayList; 4272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovimport java.util.List; 4372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 4472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov/** 4572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Manages the contents of the {@link Directory} table. 4672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 4772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikovpublic class ContactDirectoryManager extends HandlerThread { 4872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 4972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private static final String TAG = "ContactDirectoryManager"; 5072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 5172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private static final int MESSAGE_SCAN_ALL_PROVIDERS = 0; 5272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private static final int MESSAGE_SCAN_PACKAGES_BY_UID = 1; 5372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 543d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov public static final String PROPERTY_DIRECTORY_SCAN_COMPLETE = "directoryScanComplete"; 553d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov public static final String CONTACT_DIRECTORY_META_DATA = "android.content.ContactDirectory"; 5672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 5772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public class DirectoryInfo { 5872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov long id; 5972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov String packageName; 6072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov String authority; 6172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov String accountName; 6272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov String accountType; 6372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov String displayName; 6472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int typeResourceId; 6572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int exportSupport = Directory.EXPORT_SUPPORT_NONE; 6672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int shortcutSupport = Directory.SHORTCUT_SUPPORT_NONE; 67994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov int photoSupport = Directory.PHOTO_SUPPORT_NONE; 6872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 6972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 7072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private final static class DirectoryQuery { 7172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final String[] PROJECTION = { 7272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.ACCOUNT_NAME, 7372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.ACCOUNT_TYPE, 7472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.DISPLAY_NAME, 7572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.TYPE_RESOURCE_ID, 7672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.EXPORT_SUPPORT, 7772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.SHORTCUT_SUPPORT, 78994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov Directory.PHOTO_SUPPORT, 7972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov }; 8072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 8172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final int ACCOUNT_NAME = 0; 8272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final int ACCOUNT_TYPE = 1; 8372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final int DISPLAY_NAME = 2; 8472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final int TYPE_RESOURCE_ID = 3; 8572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final int EXPORT_SUPPORT = 4; 8672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public static final int SHORTCUT_SUPPORT = 5; 87994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov public static final int PHOTO_SUPPORT = 6; 8872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 8972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 9072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private final ContactsProvider2 mContactsProvider; 9172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private Context mContext; 9272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private Handler mHandler; 9372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 9472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public ContactDirectoryManager(ContactsProvider2 contactsProvider) { 9572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov super("DirectoryManager", Process.THREAD_PRIORITY_BACKGROUND); 9672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov this.mContactsProvider = contactsProvider; 9772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov this.mContext = contactsProvider.getContext(); 9872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 9972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 10072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 10172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Launches an asynchronous scan of all packages. 10272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 10372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov @Override 10472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void start() { 10572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov super.start(); 1061b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov scheduleScanAllPackages(false); 10772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 10872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 10972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 11072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Launches an asynchronous scan of all packages owned by the current calling UID. 11172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 11272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void scheduleDirectoryUpdateForCaller() { 11372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov final int callingUid = Binder.getCallingUid(); 11472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (isAlive()) { 11572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Handler handler = getHandler(); 11672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov handler.sendMessage(handler.obtainMessage(MESSAGE_SCAN_PACKAGES_BY_UID, callingUid, 0)); 11772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } else { 11872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov scanPackagesByUid(callingUid); 11972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 12072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 12172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 12272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov protected Handler getHandler() { 12372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (mHandler == null) { 12472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mHandler = new Handler(getLooper()) { 12572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov @Override 12672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void handleMessage(Message msg) { 12772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ContactDirectoryManager.this.handleMessage(msg); 12872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 12972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov }; 13072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 13172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mHandler; 13272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 13372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 13472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov protected void handleMessage(Message msg) { 13572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov switch(msg.what) { 13672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case MESSAGE_SCAN_ALL_PROVIDERS: 13772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov scanAllPackagesIfNeeded(); 13872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov break; 13972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case MESSAGE_SCAN_PACKAGES_BY_UID: 14072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov scanPackagesByUid(msg.arg1); 14172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov break; 14272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 14372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 14472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 14572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 14672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Scans all packages owned by the specified calling UID looking for contact 14772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * directory providers. 14872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 14972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void scanPackagesByUid(int callingUid) { 15072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov final PackageManager pm = mContext.getPackageManager(); 15172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov final String[] callerPackages = pm.getPackagesForUid(callingUid); 15272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (callerPackages != null) { 15372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov for (int i = 0; i < callerPackages.length; i++) { 15472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov onPackageChanged(callerPackages[i]); 15572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 15672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 15772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 15872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 15972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 160afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov * Scans all packages for directory content providers. 16172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 16272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private void scanAllPackagesIfNeeded() { 16372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ContactsDatabaseHelper dbHelper = 16472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov (ContactsDatabaseHelper) mContactsProvider.getDatabaseHelper(); 16572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 16672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov String scanComplete = dbHelper.getProperty(PROPERTY_DIRECTORY_SCAN_COMPLETE, "0"); 16772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (!"0".equals(scanComplete)) { 16872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return; 16972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 17072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 17172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 17272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int count = scanAllPackages(); 17372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov dbHelper.setProperty(PROPERTY_DIRECTORY_SCAN_COMPLETE, "1"); 17472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 17572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Log.i(TAG, "Discovered " + count + " contact directories in " + (end - start) + "ms"); 17672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 17772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov // Announce the change to listeners of the contacts authority 17872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactsProvider.notifyChange(false); 17972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 18072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1811b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov public void scheduleScanAllPackages(boolean rescan) { 1821b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov if (rescan) { 1831b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov ContactsDatabaseHelper dbHelper = 1841b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov (ContactsDatabaseHelper) mContactsProvider.getDatabaseHelper(); 1851b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov dbHelper.setProperty(PROPERTY_DIRECTORY_SCAN_COMPLETE, "0"); 1861b2a89588e9593756c2627ce1683539f4ffa1e51Dmitri Plotnikov } 187cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov if (isAlive()) { 188cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov getHandler().sendEmptyMessage(MESSAGE_SCAN_ALL_PROVIDERS); 189cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov } else { 190cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov scanAllPackagesIfNeeded(); 191cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov } 1926255d756615cfa89fb3411d1840dbe08e1375ffeDmitri Plotnikov } 1936255d756615cfa89fb3411d1840dbe08e1375ffeDmitri Plotnikov 19472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 19572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int scanAllPackages() { 19672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int count = 0; 19772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov PackageManager pm = mContext.getPackageManager(); 19872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov List<PackageInfo> packages = pm.getInstalledPackages( 19972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA); 200cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov if (packages != null) { 201cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov for (PackageInfo packageInfo : packages) { 202cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov // Check all packages except the one containing ContactsProvider itself 203cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov if (!packageInfo.packageName.equals(mContext.getPackageName())) { 204cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov count += updateDirectoriesForPackage(packageInfo, true); 205cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov } 20672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 20772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 20872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return count; 20972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 21072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 21172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 21272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Scans the specified package for content directories. The package may have 21372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * already been removed, so packageName does not necessarily correspond to 21472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * an installed package. 21572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 21672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 21772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov PackageManager pm = mContext.getPackageManager(); 21872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov PackageInfo packageInfo = null; 21972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 22072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov try { 22172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov packageInfo = pm.getPackageInfo(packageName, 22272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA); 22372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } catch (NameNotFoundException e) { 22472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov // The package got removed 22572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov packageInfo = new PackageInfo(); 22672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov packageInfo.packageName = packageName; 22772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 22872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 22972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov updateDirectoriesForPackage(packageInfo, false); 23072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 23172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 23272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 23372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Scans the specified package for content directories and updates the {@link Directory} 23472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * table accordingly. 23572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 23672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private int updateDirectoriesForPackage(PackageInfo packageInfo, boolean initialScan) { 23772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ArrayList<DirectoryInfo> directories = Lists.newArrayList(); 23872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 23972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ProviderInfo[] providers = packageInfo.providers; 24072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (providers != null) { 24172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov for (ProviderInfo provider : providers) { 24272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Bundle metaData = provider.metaData; 24372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (metaData != null) { 24472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Object trueFalse = metaData.get(CONTACT_DIRECTORY_META_DATA); 24572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (trueFalse != null && Boolean.TRUE.equals(trueFalse)) { 24672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov queryDirectoriesForAuthority(directories, provider); 24772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 24872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 24972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 25072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 25172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 25272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (directories.size() == 0 && initialScan) { 25372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return 0; 25472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 25572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 25672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov SQLiteDatabase db = ((ContactsDatabaseHelper) mContactsProvider.getDatabaseHelper()) 25772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov .getWritableDatabase(); 25872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov db.beginTransaction(); 25972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov try { 26072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov updateDirectories(db, directories); 26172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov // Clear out directories that are no longer present 26272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov StringBuilder sb = new StringBuilder(Directory.PACKAGE_NAME + "=?"); 26372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (!directories.isEmpty()) { 26472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov sb.append(" AND " + Directory._ID + " NOT IN("); 26572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov for (DirectoryInfo info: directories) { 26672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov sb.append(info.id).append(","); 26772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 26872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov sb.setLength(sb.length() - 1); // Remove the extra comma 26972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov sb.append(")"); 27072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 27172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov db.delete(Tables.DIRECTORIES, sb.toString(), new String[] { packageInfo.packageName }); 27272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov db.setTransactionSuccessful(); 27372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } finally { 27472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov db.endTransaction(); 27572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 27672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 27772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactsProvider.resetDirectoryCache(); 27872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return directories.size(); 27972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 28072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 28172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 28272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Sends a {@link Directory#CONTENT_URI} request to a specific contact directory 28372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * provider and appends all discovered directories to the directoryInfo list. 28472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 28572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov protected void queryDirectoriesForAuthority( 28672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ArrayList<DirectoryInfo> directoryInfo, ProviderInfo provider) { 28772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Uri uri = new Uri.Builder().scheme("content") 28872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov .authority(provider.authority).appendPath("directories").build(); 28972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Cursor cursor = null; 29072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov try { 29172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov cursor = mContext.getContentResolver().query( 29272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov uri, DirectoryQuery.PROJECTION, null, null, null); 29372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (cursor == null) { 29472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Log.i(TAG, providerDescription(provider) + " returned a NULL cursor."); 29572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } else { 29672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov while (cursor.moveToNext()) { 29772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 29872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.packageName = provider.packageName; 29972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.authority = provider.authority; 30072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 30172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 30272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME); 30372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (!cursor.isNull(DirectoryQuery.TYPE_RESOURCE_ID)) { 30472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID); 30572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 30672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (!cursor.isNull(DirectoryQuery.EXPORT_SUPPORT)) { 30772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int exportSupport = cursor.getInt(DirectoryQuery.EXPORT_SUPPORT); 30872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov switch (exportSupport) { 30972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case Directory.EXPORT_SUPPORT_NONE: 31072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY: 31172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case Directory.EXPORT_SUPPORT_ANY_ACCOUNT: 31272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.exportSupport = exportSupport; 31372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov break; 31472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov default: 31572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Log.e(TAG, providerDescription(provider) 31672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov + " - invalid export support flag: " + exportSupport); 31772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 31872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 31972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (!cursor.isNull(DirectoryQuery.SHORTCUT_SUPPORT)) { 32072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov int shortcutSupport = cursor.getInt(DirectoryQuery.SHORTCUT_SUPPORT); 32172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov switch (shortcutSupport) { 32272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case Directory.SHORTCUT_SUPPORT_NONE: 32372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY: 32472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case Directory.SHORTCUT_SUPPORT_FULL: 32572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.shortcutSupport = shortcutSupport; 32672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov break; 32772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov default: 32872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Log.e(TAG, providerDescription(provider) 32972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov + " - invalid shortcut support flag: " + shortcutSupport); 33072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 33172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 332994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov if (!cursor.isNull(DirectoryQuery.PHOTO_SUPPORT)) { 333994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov int photoSupport = cursor.getInt(DirectoryQuery.PHOTO_SUPPORT); 334994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov switch (photoSupport) { 335994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov case Directory.PHOTO_SUPPORT_NONE: 336994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov case Directory.PHOTO_SUPPORT_THUMBNAIL_ONLY: 337994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov case Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY: 338994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov case Directory.PHOTO_SUPPORT_FULL: 339994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov info.photoSupport = photoSupport; 340994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov break; 341994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov default: 342994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov Log.e(TAG, providerDescription(provider) 343994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov + " - invalid photo support flag: " + photoSupport); 344994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov } 345994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov } 34672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov directoryInfo.add(info); 34772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 34872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 34972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } catch (Throwable t) { 35072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Log.e(TAG, providerDescription(provider) + " exception", t); 35172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } finally { 35272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (cursor != null) { 35372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov cursor.close(); 35472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 35572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 35672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 35772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 35872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /** 35972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * Updates the directories tables in the database to match the info received 36072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov * from directory providers. 36172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 36272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private void updateDirectories(SQLiteDatabase db, ArrayList<DirectoryInfo> directoryInfo) { 36372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 36472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov // Insert or replace existing directories. 36572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov // This happens so infrequently that we can use a less-then-optimal one-a-time approach 36672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov for (DirectoryInfo info : directoryInfo) { 36772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov ContentValues values = new ContentValues(); 36872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.PACKAGE_NAME, info.packageName); 36972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.DIRECTORY_AUTHORITY, info.authority); 37072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.ACCOUNT_NAME, info.accountName); 37172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.ACCOUNT_TYPE, info.accountType); 37272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.TYPE_RESOURCE_ID, info.typeResourceId); 37372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.DISPLAY_NAME, info.displayName); 37472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.EXPORT_SUPPORT, info.exportSupport); 37572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov values.put(Directory.SHORTCUT_SUPPORT, info.shortcutSupport); 376994c32a995a85937faf59e37a9fc88b526470d7dDmitri Plotnikov values.put(Directory.PHOTO_SUPPORT, info.photoSupport); 37772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 37872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, new String[] { Directory._ID }, 37972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Directory.PACKAGE_NAME + "=? AND " + Directory.DIRECTORY_AUTHORITY + "=? AND " 38072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov + Directory.ACCOUNT_NAME + "=? AND " + Directory.ACCOUNT_TYPE + "=?", 38172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov new String[] { 38272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.packageName, info.authority, info.accountName, info.accountType }, 38372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov null, null, null); 38472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov try { 38572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov long id; 38672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov if (cursor.moveToFirst()) { 38772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov id = cursor.getLong(0); 38872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov db.update(Tables.DIRECTORIES, values, Directory._ID + "=?", 38972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov new String[] { String.valueOf(id) }); 39072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } else { 39172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov id = db.insert(Tables.DIRECTORIES, null, values); 39272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 39372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov info.id = id; 39472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } finally { 39572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov cursor.close(); 39672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 39772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 39872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 39972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 40072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov protected String providerDescription(ProviderInfo provider) { 40172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return "Directory provider " + provider.packageName + "(" + provider.authority + ")"; 40272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 40372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov} 404