1 /* 2 * Copyright (C) 2012 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.gallery3d.onetimeinitializer; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.os.Environment; 22 import android.preference.PreferenceManager; 23 import android.util.Log; 24 25 import com.android.gallery3d.app.GalleryApp; 26 import com.android.gallery3d.common.Utils; 27 import com.android.gallery3d.data.DataManager; 28 import com.android.gallery3d.data.LocalAlbum; 29 import com.android.gallery3d.data.MediaSet; 30 import com.android.gallery3d.data.Path; 31 import com.android.gallery3d.gadget.WidgetDatabaseHelper; 32 import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry; 33 import com.android.gallery3d.util.GalleryUtils; 34 35 import java.io.File; 36 import java.util.HashMap; 37 import java.util.List; 38 39 /** 40 * This one-timer migrates local-album gallery app widgets from pre-JB releases to JB (or later) 41 * due to bucket ID (i.e., directory hash) change in JB (as the external storage path is changed 42 * from /mnt/sdcard to /storage/sdcard0). 43 */ 44 public class GalleryWidgetMigrator { 45 private static final String TAG = "GalleryWidgetMigrator"; 46 private static final String OLD_EXT_PATH = "/mnt/sdcard"; 47 private static final String NEW_EXT_PATH = 48 Environment.getExternalStorageDirectory().getAbsolutePath(); 49 private static final int RELATIVE_PATH_START = NEW_EXT_PATH.length(); 50 private static final String KEY_MIGRATION_DONE = "gallery_widget_migration_done"; 51 52 /** 53 * Migrates local-album gallery widgets from pre-JB releases to JB (or later) due to bucket ID 54 * (i.e., directory hash) change in JB. 55 */ 56 public static void migrateGalleryWidgets(Context context) { 57 // no migration needed if path of external storage is not changed 58 if (OLD_EXT_PATH.equals(NEW_EXT_PATH)) return; 59 60 // only need to migrate once; the "done" bit is saved to SharedPreferences 61 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 62 boolean isDone = prefs.getBoolean(KEY_MIGRATION_DONE, false); 63 if (isDone) return; 64 65 try { 66 migrateGalleryWidgetsInternal(context); 67 prefs.edit().putBoolean(KEY_MIGRATION_DONE, true).commit(); 68 } catch (Throwable t) { 69 // exception may be thrown if external storage is not available(?) 70 Log.w(TAG, "migrateGalleryWidgets", t); 71 } 72 } 73 74 private static void migrateGalleryWidgetsInternal(Context context) { 75 GalleryApp galleryApp = (GalleryApp) context.getApplicationContext(); 76 DataManager manager = galleryApp.getDataManager(); 77 WidgetDatabaseHelper dbHelper = new WidgetDatabaseHelper(context); 78 79 // only need to migrate local-album entries of type TYPE_ALBUM 80 List<Entry> entries = dbHelper.getEntries(WidgetDatabaseHelper.TYPE_ALBUM); 81 if (entries != null) { 82 HashMap<Integer, Entry> localEntries = new HashMap<Integer, Entry>(entries.size()); 83 for (Entry entry : entries) { 84 Path path = Path.fromString(entry.albumPath); 85 MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); 86 if (mediaSet instanceof LocalAlbum) { 87 int bucketId = Integer.parseInt(path.getSuffix()); 88 localEntries.put(bucketId, entry); 89 } 90 } 91 if (!localEntries.isEmpty()) migrateLocalEntries(localEntries, dbHelper); 92 } 93 } 94 95 private static void migrateLocalEntries( 96 HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) { 97 File root = Environment.getExternalStorageDirectory(); 98 99 // check the DCIM directory first; this should take care of 99% use cases 100 updatePath(new File(root, "DCIM"), entries, dbHelper); 101 102 // check other directories if DCIM doesn't cut it 103 if (!entries.isEmpty()) updatePath(root, entries, dbHelper); 104 } 105 106 private static void updatePath( 107 File root, HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) { 108 File[] files = root.listFiles(); 109 if (files != null) { 110 for (File file : files) { 111 if (file.isDirectory() && !entries.isEmpty()) { 112 String path = file.getAbsolutePath(); 113 String oldPath = OLD_EXT_PATH + path.substring(RELATIVE_PATH_START); 114 int oldBucketId = GalleryUtils.getBucketId(oldPath); 115 Entry entry = entries.remove(oldBucketId); 116 if (entry != null) { 117 int newBucketId = GalleryUtils.getBucketId(path); 118 String newAlbumPath = Path.fromString(entry.albumPath) 119 .getParent() 120 .getChild(newBucketId) 121 .toString(); 122 Log.d(TAG, "migrate from " + entry.albumPath + " to " + newAlbumPath); 123 entry.albumPath = newAlbumPath; 124 dbHelper.updateEntry(entry); 125 } 126 updatePath(file, entries, dbHelper); // recursion 127 } 128 } 129 } 130 } 131 } 132