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