1 /*
2  * Copyright (C) 2016 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.launcher3.provider;
18 
19 import android.content.ContentValues;
20 import android.content.Context;
21 import android.database.Cursor;
22 import android.database.sqlite.SQLiteDatabase;
23 import android.graphics.Point;
24 import android.util.Log;
25 
26 import com.android.launcher3.InvariantDeviceProfile;
27 import com.android.launcher3.LauncherSettings.Favorites;
28 import com.android.launcher3.Utilities;
29 import com.android.launcher3.Workspace;
30 import com.android.launcher3.model.GridSizeMigrationTask;
31 import com.android.launcher3.util.LongArrayMap;
32 
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 
36 /**
37  * An extension of {@link GridSizeMigrationTask} which migrates only one screen and
38  * deletes all carry-forward items.
39  */
40 public class LossyScreenMigrationTask extends GridSizeMigrationTask {
41 
42     private final SQLiteDatabase mDb;
43 
44     private final LongArrayMap<DbEntry> mOriginalItems;
45     private final LongArrayMap<DbEntry> mUpdates;
46 
LossyScreenMigrationTask( Context context, InvariantDeviceProfile idp, SQLiteDatabase db)47     protected LossyScreenMigrationTask(
48             Context context, InvariantDeviceProfile idp, SQLiteDatabase db) {
49         // Decrease the rows count by 1
50         super(context, idp, getValidPackages(context),
51                 new Point(idp.numColumns, idp.numRows + 1),
52                 new Point(idp.numColumns, idp.numRows));
53 
54         mDb = db;
55         mOriginalItems = new LongArrayMap<>();
56         mUpdates = new LongArrayMap<>();
57     }
58 
59     @Override
queryWorkspace(String[] columns, String where)60     protected Cursor queryWorkspace(String[] columns, String where) {
61         return mDb.query(Favorites.TABLE_NAME, columns, where, null, null, null, null);
62     }
63 
64     @Override
update(DbEntry item)65     protected void update(DbEntry item) {
66         mUpdates.put(item.id, item.copy());
67     }
68 
69     @Override
loadWorkspaceEntries(long screen)70     protected ArrayList<DbEntry> loadWorkspaceEntries(long screen) {
71         ArrayList<DbEntry> result = super.loadWorkspaceEntries(screen);
72         for (DbEntry entry : result) {
73             mOriginalItems.put(entry.id, entry.copy());
74 
75             // Shift all items by 1 in y direction and mark them for update.
76             entry.cellY++;
77             mUpdates.put(entry.id, entry.copy());
78         }
79 
80         return result;
81     }
82 
migrateScreen0()83     public void migrateScreen0() {
84         migrateScreen(Workspace.FIRST_SCREEN_ID);
85 
86         ContentValues tempValues = new ContentValues();
87         for (DbEntry update : mUpdates) {
88             DbEntry org = mOriginalItems.get(update.id);
89 
90             if (org.cellX != update.cellX || org.cellY != update.cellY
91                     || org.spanX != update.spanX || org.spanY != update.spanY) {
92                 tempValues.clear();
93                 update.addToContentValues(tempValues);
94                 mDb.update(Favorites.TABLE_NAME, tempValues, "_id = ?",
95                         new String[] {Long.toString(update.id)});
96             }
97         }
98 
99         // Delete any carry over items as we are only migration a single screen.
100         for (DbEntry entry : mCarryOver) {
101             mEntryToRemove.add(entry.id);
102         }
103 
104         if (!mEntryToRemove.isEmpty()) {
105             mDb.delete(Favorites.TABLE_NAME,
106                     Utilities.createDbSelectionQuery(Favorites._ID, mEntryToRemove), null);
107         }
108     }
109 }
110