blob: abb326ac4ca0e0c8eca544f6f1f20da19207681a [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.providers.media;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.provider.Column;
import android.util.Log;
import com.android.providers.media.util.ForegroundThread;
import com.android.providers.media.util.Metrics;
import java.io.File;
/**
* This will be launched during system boot, after the core system has
* been brought up but before any non-persistent processes have been
* started. It is launched in a special state, with no content provider
* or custom application class associated with the process running.
*
* It's job is to prime the contacts database. Either create it
* if it doesn't exist, or open it and force any necessary upgrades.
* All of this heavy lifting happens before the boot animation ends.
*/
public class MediaUpgradeReceiver extends BroadcastReceiver {
static final String TAG = "MediaUpgradeReceiver";
static final String PREF_DB_VERSION = "db_version";
@Override
public void onReceive(Context context, Intent intent) {
// We are now running with the system up, but no apps started,
// so can do whatever cleanup after an upgrade that we want.
ForegroundThread.getExecutor().execute(() -> {
// Run database migration on a separate thread so that main thread
// is available for handling other MediaService requests.
tryMigratingDatabases(context);
});
}
private void tryMigratingDatabases(Context context) {
// Lookup the last known database version
SharedPreferences prefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE);
int prefVersion = prefs.getInt(PREF_DB_VERSION, 0);
int dbVersion = DatabaseHelper.getDatabaseVersion(context);
if (prefVersion == dbVersion) {
return;
}
prefs.edit().putInt(PREF_DB_VERSION, dbVersion).commit();
try {
File dbDir = context.getDatabasePath("foo").getParentFile();
String[] files = dbDir.list();
if (files == null) return;
for (int i=0; i<files.length; i++) {
String file = files[i];
if (MediaProvider.isMediaDatabaseName(file)) {
long startTime = System.currentTimeMillis();
Log.i(TAG, "---> Start upgrade of media database " + file);
try {
DatabaseHelper helper = new DatabaseHelper(
context, file, MediaProvider.isInternalMediaDatabaseName(file),
false, false, Column.class, Metrics::logSchemaChange, null,
MediaProvider.MIGRATION_LISTENER, null);
helper.runWithTransaction((db) -> {
// Perform just enough to force database upgrade
return db.getVersion();
});
helper.close();
} catch (Throwable t) {
Log.wtf(TAG, "Error during upgrade of media db " + file, t);
} finally {
}
Log.i(TAG, "<--- Finished upgrade of media database " + file
+ " in " + (System.currentTimeMillis()-startTime) + "ms");
}
}
} catch (Throwable t) {
// Something has gone terribly wrong.
Log.wtf(TAG, "Error during upgrade attempt.", t);
}
}
}