140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan/*
240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * Copyright (C) 2012 The Android Open Source Project
340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan *
440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * Licensed under the Apache License, Version 2.0 (the "License");
540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * you may not use this file except in compliance with the License.
640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * You may obtain a copy of the License at
740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan *
840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan *      http://www.apache.org/licenses/LICENSE-2.0
940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan *
1040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * Unless required by applicable law or agreed to in writing, software
1140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * distributed under the License is distributed on an "AS IS" BASIS,
1240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * See the License for the specific language governing permissions and
1440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * limitations under the License.
1540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan */
1640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
1740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanpackage com.android.gallery3d.onetimeinitializer;
1840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
1940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport android.content.Context;
2040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport android.content.SharedPreferences;
2140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport android.os.Environment;
2240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport android.preference.PreferenceManager;
2340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport android.util.Log;
2440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
2540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.app.GalleryApp;
2640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.data.DataManager;
2740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.data.LocalAlbum;
2840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.data.MediaSet;
2940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.data.Path;
3040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.gadget.WidgetDatabaseHelper;
3140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry;
3240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.util.GalleryUtils;
3340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
3440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport java.io.File;
3540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport java.util.HashMap;
3640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport java.util.List;
3740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
3840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan/**
3940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * This one-timer migrates local-album gallery app widgets from pre-JB releases to JB (or later)
4040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * due to bucket ID (i.e., directory hash) change in JB (as the external storage path is changed
4140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan * from /mnt/sdcard to /storage/sdcard0).
4240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan */
4340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanpublic class GalleryWidgetMigrator {
4440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static final String TAG = "GalleryWidgetMigrator";
4540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static final String OLD_EXT_PATH = "/mnt/sdcard";
4640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static final String NEW_EXT_PATH =
4740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            Environment.getExternalStorageDirectory().getAbsolutePath();
4840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static final int RELATIVE_PATH_START = NEW_EXT_PATH.length();
4940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static final String KEY_MIGRATION_DONE = "gallery_widget_migration_done";
5040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
5140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    /**
5240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan     * Migrates local-album gallery widgets from pre-JB releases to JB (or later) due to bucket ID
5340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan     * (i.e., directory hash) change in JB.
5440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan     */
5540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    public static void migrateGalleryWidgets(Context context) {
5640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        // no migration needed if path of external storage is not changed
5740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        if (OLD_EXT_PATH.equals(NEW_EXT_PATH)) return;
5840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
5940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        // only need to migrate once; the "done" bit is saved to SharedPreferences
6040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
6140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        boolean isDone = prefs.getBoolean(KEY_MIGRATION_DONE, false);
6240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        if (isDone) return;
6340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
6440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        try {
6540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            migrateGalleryWidgetsInternal(context);
6640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            prefs.edit().putBoolean(KEY_MIGRATION_DONE, true).commit();
6740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        } catch (Throwable t) {
6840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            // exception may be thrown if external storage is not available(?)
6940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            Log.w(TAG, "migrateGalleryWidgets", t);
7040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        }
7140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    }
7240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
7340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static void migrateGalleryWidgetsInternal(Context context) {
7440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        GalleryApp galleryApp = (GalleryApp) context.getApplicationContext();
7540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        DataManager manager = galleryApp.getDataManager();
7640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        WidgetDatabaseHelper dbHelper = new WidgetDatabaseHelper(context);
7740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
7840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        // only need to migrate local-album entries of type TYPE_ALBUM
7940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        List<Entry> entries = dbHelper.getEntries(WidgetDatabaseHelper.TYPE_ALBUM);
8040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        if (entries != null) {
8140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            HashMap<Integer, Entry> localEntries = new HashMap<Integer, Entry>(entries.size());
8240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            for (Entry entry : entries) {
8340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                Path path = Path.fromString(entry.albumPath);
8440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                MediaSet mediaSet = (MediaSet) manager.getMediaObject(path);
8540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                if (mediaSet instanceof LocalAlbum) {
8640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    int bucketId = Integer.parseInt(path.getSuffix());
8740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    localEntries.put(bucketId, entry);
8840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                }
8940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            }
9040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            if (!localEntries.isEmpty()) migrateLocalEntries(localEntries, dbHelper);
9140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        }
9240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    }
9340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
9440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static void migrateLocalEntries(
9540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) {
9640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        File root = Environment.getExternalStorageDirectory();
9740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
9840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        // check the DCIM directory first; this should take care of 99% use cases
9940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        updatePath(new File(root, "DCIM"), entries, dbHelper);
10040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
10140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        // check other directories if DCIM doesn't cut it
10240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        if (!entries.isEmpty()) updatePath(root, entries, dbHelper);
10340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    }
10440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan
10540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    private static void updatePath(
10640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            File root, HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) {
10740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        File[] files = root.listFiles();
10840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        if (files != null) {
10940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            for (File file : files) {
11040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                if (file.isDirectory() && !entries.isEmpty()) {
11140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    String path = file.getAbsolutePath();
11240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    String oldPath = OLD_EXT_PATH + path.substring(RELATIVE_PATH_START);
11340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    int oldBucketId = GalleryUtils.getBucketId(oldPath);
11440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    Entry entry = entries.remove(oldBucketId);
11540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    if (entry != null) {
11640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                        int newBucketId = GalleryUtils.getBucketId(path);
11740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                        String newAlbumPath = Path.fromString(entry.albumPath)
11840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                                .getParent()
11940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                                .getChild(newBucketId)
12040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                                .toString();
12140234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                        Log.d(TAG, "migrate from " + entry.albumPath + " to " + newAlbumPath);
12240234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                        entry.albumPath = newAlbumPath;
12340234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                        dbHelper.updateEntry(entry);
12440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    }
12540234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                    updatePath(file, entries, dbHelper); // recursion
12640234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan                }
12740234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan            }
12840234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan        }
12940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan    }
13040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan}
131