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