1 /*
2  * Copyright (C) 2018 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 package com.android.launcher3.model;
17 
18 import static com.android.launcher3.LauncherSettings.Favorites.BACKUP_TABLE_NAME;
19 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
20 import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
21 
22 import android.content.ContentValues;
23 import android.content.Context;
24 import android.database.Cursor;
25 import android.database.sqlite.SQLiteDatabase;
26 import android.graphics.Point;
27 import android.os.Process;
28 import android.util.Log;
29 
30 import com.android.launcher3.LauncherSettings.Favorites;
31 import com.android.launcher3.LauncherSettings.Settings;
32 import com.android.launcher3.compat.UserManagerCompat;
33 
34 /**
35  * Helper class to backup and restore Favorites table into a separate table
36  * within the same data base.
37  */
38 public class GridBackupTable {
39     private static final String TAG = "GridBackupTable";
40 
41     private static final int ID_PROPERTY = -1;
42 
43     private static final String KEY_HOTSEAT_SIZE = Favorites.SCREEN;
44     private static final String KEY_GRID_X_SIZE = Favorites.SPANX;
45     private static final String KEY_GRID_Y_SIZE = Favorites.SPANY;
46     private static final String KEY_DB_VERSION = Favorites.RANK;
47 
48     private final Context mContext;
49     private final SQLiteDatabase mDb;
50 
51     private final int mOldHotseatSize;
52     private final int mOldGridX;
53     private final int mOldGridY;
54 
55     private int mRestoredHotseatSize;
56     private int mRestoredGridX;
57     private int mRestoredGridY;
58 
GridBackupTable(Context context, SQLiteDatabase db, int hotseatSize, int gridX, int gridY)59     public GridBackupTable(Context context, SQLiteDatabase db,
60             int hotseatSize, int gridX, int gridY) {
61         mContext = context;
62         mDb = db;
63 
64         mOldHotseatSize = hotseatSize;
65         mOldGridX = gridX;
66         mOldGridY = gridY;
67     }
68 
backupOrRestoreAsNeeded()69     public boolean backupOrRestoreAsNeeded() {
70         // Check if backup table exists
71         if (!tableExists(mDb, BACKUP_TABLE_NAME)) {
72             if (Settings.call(mContext.getContentResolver(), Settings.METHOD_WAS_EMPTY_DB_CREATED)
73                     .getBoolean(Settings.EXTRA_VALUE, false)) {
74                 // No need to copy if empty DB was created.
75                 return false;
76             }
77 
78             copyTable(Favorites.TABLE_NAME, BACKUP_TABLE_NAME);
79             encodeDBProperties();
80             return false;
81         }
82 
83         if (!loadDbProperties()) {
84             return false;
85         }
86         copyTable(BACKUP_TABLE_NAME, Favorites.TABLE_NAME);
87         Log.d(TAG, "Backup table found");
88         return true;
89     }
90 
getRestoreHotseatAndGridSize(Point outGridSize)91     public int getRestoreHotseatAndGridSize(Point outGridSize) {
92         outGridSize.set(mRestoredGridX, mRestoredGridY);
93         return mRestoredHotseatSize;
94     }
95 
copyTable(String from, String to)96     private void copyTable(String from, String to) {
97         long userSerial = UserManagerCompat.getInstance(mContext).getSerialNumberForUser(
98                 Process.myUserHandle());
99         dropTable(mDb, to);
100         Favorites.addTableToDb(mDb, userSerial, false, to);
101         mDb.execSQL("INSERT INTO " + to + " SELECT * FROM " + from + " where _id > " + ID_PROPERTY);
102     }
103 
encodeDBProperties()104     private void encodeDBProperties() {
105         ContentValues values = new ContentValues();
106         values.put(Favorites._ID, ID_PROPERTY);
107         values.put(KEY_DB_VERSION, mDb.getVersion());
108         values.put(KEY_GRID_X_SIZE, mOldGridX);
109         values.put(KEY_GRID_Y_SIZE, mOldGridY);
110         values.put(KEY_HOTSEAT_SIZE, mOldHotseatSize);
111         mDb.insert(BACKUP_TABLE_NAME, null, values);
112     }
113 
loadDbProperties()114     private boolean loadDbProperties() {
115         try (Cursor c = mDb.query(BACKUP_TABLE_NAME, new String[] {
116                         KEY_DB_VERSION,     // 0
117                         KEY_GRID_X_SIZE,    // 1
118                         KEY_GRID_Y_SIZE,    // 2
119                         KEY_HOTSEAT_SIZE},  // 3
120                 "_id=" + ID_PROPERTY, null, null, null, null)) {
121             if (!c.moveToNext()) {
122                 Log.e(TAG, "Meta data not found in backup table");
123                 return false;
124             }
125             if (mDb.getVersion() != c.getInt(0)) {
126                 return false;
127             }
128 
129             mRestoredGridX = c.getInt(1);
130             mRestoredGridY = c.getInt(2);
131             mRestoredHotseatSize = c.getInt(3);
132             return true;
133         }
134     }
135 }
136