• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.providers.media;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.SharedPreferences;
23 import android.provider.Column;
24 import android.util.Log;
25 
26 import com.android.providers.media.util.ForegroundThread;
27 import com.android.providers.media.util.Metrics;
28 
29 import java.io.File;
30 
31 /**
32  * This will be launched during system boot, after the core system has
33  * been brought up but before any non-persistent processes have been
34  * started.  It is launched in a special state, with no content provider
35  * or custom application class associated with the process running.
36  *
37  * It's job is to prime the contacts database. Either create it
38  * if it doesn't exist, or open it and force any necessary upgrades.
39  * All of this heavy lifting happens before the boot animation ends.
40  */
41 public class MediaUpgradeReceiver extends BroadcastReceiver {
42     static final String TAG = "MediaUpgradeReceiver";
43     static final String PREF_DB_VERSION = "db_version";
44 
45     @Override
onReceive(Context context, Intent intent)46     public void onReceive(Context context, Intent intent) {
47         // We are now running with the system up, but no apps started,
48         // so can do whatever cleanup after an upgrade that we want.
49         ForegroundThread.getExecutor().execute(() -> {
50             // Run database migration on a separate thread so that main thread
51             // is available for handling other MediaService requests.
52             tryMigratingDatabases(context);
53         });
54     }
55 
tryMigratingDatabases(Context context)56     private void tryMigratingDatabases(Context context) {
57         // Lookup the last known database version
58         SharedPreferences prefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE);
59         int prefVersion = prefs.getInt(PREF_DB_VERSION, 0);
60         int dbVersion = DatabaseHelper.getDatabaseVersion(context);
61         if (prefVersion == dbVersion) {
62             return;
63         }
64         prefs.edit().putInt(PREF_DB_VERSION, dbVersion).commit();
65 
66         try {
67             File dbDir = context.getDatabasePath("foo").getParentFile();
68             String[] files = dbDir.list();
69             if (files == null) return;
70             for (int i=0; i<files.length; i++) {
71                 String file = files[i];
72                 if (MediaProvider.isMediaDatabaseName(file)) {
73                     long startTime = System.currentTimeMillis();
74                     Log.i(TAG, "---> Start upgrade of media database " + file);
75                     try {
76                         DatabaseHelper helper = new DatabaseHelper(
77                                 context, file, MediaProvider.isInternalMediaDatabaseName(file),
78                                 false, false, Column.class, Metrics::logSchemaChange, null,
79                                 MediaProvider.MIGRATION_LISTENER, null);
80                         helper.runWithTransaction((db) -> {
81                             // Perform just enough to force database upgrade
82                             return db.getVersion();
83                         });
84                         helper.close();
85                     } catch (Throwable t) {
86                         Log.wtf(TAG, "Error during upgrade of media db " + file, t);
87                     } finally {
88                     }
89                     Log.i(TAG, "<--- Finished upgrade of media database " + file
90                             + " in " + (System.currentTimeMillis()-startTime) + "ms");
91                 }
92             }
93         } catch (Throwable t) {
94             // Something has gone terribly wrong.
95             Log.wtf(TAG, "Error during upgrade attempt.", t);
96         }
97     }
98 }
99