1702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project/* //device/content/providers/media/src/com/android/providers/media/MediaScannerService.java 2702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** 3702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** Copyright 2007, The Android Open Source Project 4702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** 5702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 6702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** you may not use this file except in compliance with the License. 7702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** You may obtain a copy of the License at 8702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** 9702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 10702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** 11702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** Unless required by applicable law or agreed to in writing, software 12702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 13702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** See the License for the specific language governing permissions and 15702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project** limitations under the License. 16702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project*/ 17702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 18702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectpackage com.android.providers.media; 19702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 20702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.app.Service; 21702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.content.ContentValues; 22702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.content.Context; 23702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.content.Intent; 24702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.content.res.Configuration; 25702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.database.Cursor; 26702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.media.IMediaScannerListener; 27702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.media.IMediaScannerService; 28702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.media.MediaScanner; 29702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.net.Uri; 30702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.Bundle; 31702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.Environment; 32702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.FileUtils; 33702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.Handler; 34702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.IBinder; 35702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.Looper; 36702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.Message; 37702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.PowerManager; 38702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.Process; 39702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.os.SystemProperties; 40c47e4f2921312098eddc5fe49b080e0f2df60e81Mike Lockwoodimport android.os.storage.StorageManager; 41c47e4f2921312098eddc5fe49b080e0f2df60e81Mike Lockwoodimport android.os.storage.StorageVolume; 42702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.provider.MediaStore; 43702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport android.util.Log; 44702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 45702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport java.io.File; 4610621774fbce4bf5f3e0d829226683f76bf8fdd5Marco Nelissenimport java.util.Arrays; 47702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectimport java.util.Locale; 48702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 49702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Projectpublic class MediaScannerService extends Service implements Runnable 50702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project{ 51702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private static final String TAG = "MediaScannerService"; 52702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 53702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private volatile Looper mServiceLooper; 54702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private volatile ServiceHandler mServiceHandler; 55702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private PowerManager.WakeLock mWakeLock; 56d3709e80446eb8abc3bb9c60db0d5c9473930611Mike Lockwood private String[] mExternalStoragePaths; 57702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 58702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private void openDatabase(String volumeName) { 59702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project try { 60702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project ContentValues values = new ContentValues(); 61702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project values.put("name", volumeName); 62702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project getContentResolver().insert(Uri.parse("content://media/"), values); 63702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } catch (IllegalArgumentException ex) { 64702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Log.w(TAG, "failed to open media database"); 65702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 66702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 67702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 68702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private MediaScanner createMediaScanner() { 69702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project MediaScanner scanner = new MediaScanner(this); 70702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Locale locale = getResources().getConfiguration().locale; 71702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (locale != null) { 72702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project String language = locale.getLanguage(); 73702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project String country = locale.getCountry(); 74702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project String localeString = null; 75702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (language != null) { 76702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (country != null) { 77702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project scanner.setLocale(language + "_" + country); 78702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } else { 79702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project scanner.setLocale(language); 80702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 81702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 82702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 83702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 84702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project return scanner; 85702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 86702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 87702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private void scan(String[] directories, String volumeName) { 88815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen Uri uri = Uri.parse("file://" + directories[0]); 89702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project // don't sleep while scanning 90702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project mWakeLock.acquire(); 91702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 92702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project try { 93815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen ContentValues values = new ContentValues(); 94815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen values.put(MediaStore.MEDIA_SCANNER_VOLUME, volumeName); 95815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen Uri scanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values); 96702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 97815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_STARTED, uri)); 98815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen 99815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen try { 100815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen if (volumeName.equals(MediaProvider.EXTERNAL_VOLUME)) { 101815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen openDatabase(volumeName); 102815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen } 103702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 104815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen MediaScanner scanner = createMediaScanner(); 105815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen scanner.scanDirectories(directories, volumeName); 106815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen } catch (Exception e) { 107815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen Log.e(TAG, "exception in MediaScanner.scan()", e); 108815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen } 109815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen 110815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen getContentResolver().delete(scanUri, null, null); 111702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 112815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen } finally { 113815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED, uri)); 114815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen mWakeLock.release(); 115815d1fc6bd273236aa870ec00dad851febd6f504Marco Nelissen } 116702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 117702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 118702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project @Override 119702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public void onCreate() 120702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 121702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); 122702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 123c47e4f2921312098eddc5fe49b080e0f2df60e81Mike Lockwood StorageManager storageManager = (StorageManager)getSystemService(Context.STORAGE_SERVICE); 124c47e4f2921312098eddc5fe49b080e0f2df60e81Mike Lockwood mExternalStoragePaths = storageManager.getVolumePaths(); 1254f2186758ee1c6eaa702bf1511b233b26143b631Mike Lockwood 126702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project // Start up the thread running the service. Note that we create a 127702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project // separate thread because the service normally runs in the process's 128702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project // main thread, which we don't want to block. 129702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Thread thr = new Thread(null, this, "MediaScannerService"); 130702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project thr.start(); 131702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 132702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 133702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project @Override 134a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood public int onStartCommand(Intent intent, int flags, int startId) 135702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 136702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project while (mServiceHandler == null) { 137702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project synchronized (this) { 138702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project try { 139702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project wait(100); 140702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } catch (InterruptedException e) { 141702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 142702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 143702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 144702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 145a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood if (intent == null) { 146a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood Log.e(TAG, "Intent is null in onStartCommand: ", 147a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood new NullPointerException()); 148a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood return Service.START_NOT_STICKY; 149a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood } 150a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood 151702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Message msg = mServiceHandler.obtainMessage(); 152702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project msg.arg1 = startId; 153702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project msg.obj = intent.getExtras(); 154702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project mServiceHandler.sendMessage(msg); 155a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood 156a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood // Try again later if we are killed before we can finish scanning. 157a1a85d0c6ffebdd47e17d2a8f7cc60c94ccb9cc0Mike Lockwood return Service.START_REDELIVER_INTENT; 158702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 159702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 160702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project @Override 161702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public void onDestroy() 162702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 163702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project // Make sure thread has started before telling it to quit. 164702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project while (mServiceLooper == null) { 165702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project synchronized (this) { 166702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project try { 167702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project wait(100); 168702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } catch (InterruptedException e) { 169702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 170702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 171702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 172702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project mServiceLooper.quit(); 173702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 174702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 175702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public void run() 176702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 177c2527694fc19e7086b025a6d5c01af75dd5d80c9Mike Lockwood // reduce priority below other background threads to avoid interfering 178c2527694fc19e7086b025a6d5c01af75dd5d80c9Mike Lockwood // with other services at boot time. 179c2527694fc19e7086b025a6d5c01af75dd5d80c9Mike Lockwood Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND + 180c2527694fc19e7086b025a6d5c01af75dd5d80c9Mike Lockwood Process.THREAD_PRIORITY_LESS_FAVORABLE); 181702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Looper.prepare(); 182702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 183702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project mServiceLooper = Looper.myLooper(); 184702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project mServiceHandler = new ServiceHandler(); 185702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 186702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Looper.loop(); 187702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 188702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 189702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private Uri scanFile(String path, String mimeType) { 190d3709e80446eb8abc3bb9c60db0d5c9473930611Mike Lockwood String volumeName = MediaProvider.EXTERNAL_VOLUME; 191d3709e80446eb8abc3bb9c60db0d5c9473930611Mike Lockwood openDatabase(volumeName); 192702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project MediaScanner scanner = createMediaScanner(); 193704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood try { 194704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood // make sure the file path is in canonical form 195704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood String canonicalPath = new File(path).getCanonicalPath(); 196704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood return scanner.scanSingleFile(canonicalPath, volumeName, mimeType); 197704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood } catch (Exception e) { 198704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood Log.e(TAG, "bad path " + path + " in scanFile()", e); 199704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood return null; 200704fe6bc9da64c3d99db9b5a40705419aa091ce4Mike Lockwood } 201702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 202702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 203702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project @Override 204702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public IBinder onBind(Intent intent) 205702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 206702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project return mBinder; 207702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 208702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 209702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private final IMediaScannerService.Stub mBinder = 210702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project new IMediaScannerService.Stub() { 211702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public void requestScanFile(String path, String mimeType, IMediaScannerListener listener) 212702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 213e0095e763c73934e6d36be9c7722ccc3e790df77Joe Onorato if (false) { 214702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Log.d(TAG, "IMediaScannerService.scanFile: " + path + " mimeType: " + mimeType); 215702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 216702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Bundle args = new Bundle(); 217702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project args.putString("filepath", path); 218702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project args.putString("mimetype", mimeType); 219702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (listener != null) { 220702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project args.putIBinder("listener", listener.asBinder()); 221702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 222702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project startService(new Intent(MediaScannerService.this, 223702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project MediaScannerService.class).putExtras(args)); 224702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 225702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 226702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public void scanFile(String path, String mimeType) { 227702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project requestScanFile(path, mimeType, null); 228702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 229702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project }; 230702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 231702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project private final class ServiceHandler extends Handler 232702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 233702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project @Override 234702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project public void handleMessage(Message msg) 235702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project { 236702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Bundle arguments = (Bundle) msg.obj; 237702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project String filePath = arguments.getString("filepath"); 238702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 239702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project try { 240702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (filePath != null) { 241702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project IBinder binder = arguments.getIBinder("listener"); 242702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project IMediaScannerListener listener = 243702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project (binder == null ? null : IMediaScannerListener.Stub.asInterface(binder)); 244df21a16539a9ca247899e8d85042bcb17d9ce4c1Marco Nelissen Uri uri = null; 245df21a16539a9ca247899e8d85042bcb17d9ce4c1Marco Nelissen try { 246df21a16539a9ca247899e8d85042bcb17d9ce4c1Marco Nelissen uri = scanFile(filePath, arguments.getString("mimetype")); 247df21a16539a9ca247899e8d85042bcb17d9ce4c1Marco Nelissen } catch (Exception e) { 248df21a16539a9ca247899e8d85042bcb17d9ce4c1Marco Nelissen Log.e(TAG, "Exception scanning file", e); 249df21a16539a9ca247899e8d85042bcb17d9ce4c1Marco Nelissen } 250702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (listener != null) { 251702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project listener.scanCompleted(filePath, uri); 252702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 253702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } else { 254702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project String volume = arguments.getString("volume"); 255702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project String[] directories = null; 256702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 257702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (MediaProvider.INTERNAL_VOLUME.equals(volume)) { 258702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project // scan internal media storage 259702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project directories = new String[] { 260702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Environment.getRootDirectory() + "/media", 2611cf716968afd032e8261df3f6c4671c1f0c5f769Jeff Sharkey Environment.getOemDirectory() + "/media", 262702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project }; 263702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 264702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project else if (MediaProvider.EXTERNAL_VOLUME.equals(volume)) { 265d3709e80446eb8abc3bb9c60db0d5c9473930611Mike Lockwood // scan external storage volumes 266c47e4f2921312098eddc5fe49b080e0f2df60e81Mike Lockwood directories = mExternalStoragePaths; 267702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 268c47e4f2921312098eddc5fe49b080e0f2df60e81Mike Lockwood 269702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project if (directories != null) { 270e0095e763c73934e6d36be9c7722ccc3e790df77Joe Onorato if (false) Log.d(TAG, "start scanning volume " + volume + ": " 27110621774fbce4bf5f3e0d829226683f76bf8fdd5Marco Nelissen + Arrays.toString(directories)); 272702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project scan(directories, volume); 273e0095e763c73934e6d36be9c7722ccc3e790df77Joe Onorato if (false) Log.d(TAG, "done scanning volume " + volume); 274702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 275702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 276702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } catch (Exception e) { 277702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project Log.e(TAG, "Exception in handleMessage", e); 278702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 279702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 280702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project stopSelf(msg.arg1); 281702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project } 282702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project }; 283702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project} 284702152725052b7b3903ed647cf53f04724886a1bThe Android Open Source Project 285