1 /* 2 * Copyright (C) 2008 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.launcher2; 18 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.graphics.Bitmap; 23 import android.os.UserHandle; 24 import android.os.UserManager; 25 import android.util.Log; 26 27 import java.io.ByteArrayOutputStream; 28 import java.io.IOException; 29 30 /** 31 * Represents an item in the launcher. 32 */ 33 class ItemInfo { 34 35 /** 36 * Intent extra to store the profile. Format: UserHandle 37 */ 38 static final String EXTRA_PROFILE = "profile"; 39 40 static final int NO_ID = -1; 41 42 /** 43 * The id in the settings database for this item 44 */ 45 long id = NO_ID; 46 47 /** 48 * One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION}, 49 * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT}, 50 * {@link LauncherSettings.Favorites#ITEM_TYPE_FOLDER}, or 51 * {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}. 52 */ 53 int itemType; 54 55 /** 56 * The id of the container that holds this item. For the desktop, this will be 57 * {@link LauncherSettings.Favorites#CONTAINER_DESKTOP}. For the all applications folder it 58 * will be {@link #NO_ID} (since it is not stored in the settings DB). For user folders 59 * it will be the id of the folder. 60 */ 61 long container = NO_ID; 62 63 /** 64 * Indicates the screen in which the shortcut appears. 65 */ 66 int screen = -1; 67 68 /** 69 * Indicates the X position of the associated cell. 70 */ 71 int cellX = -1; 72 73 /** 74 * Indicates the Y position of the associated cell. 75 */ 76 int cellY = -1; 77 78 /** 79 * Indicates the X cell span. 80 */ 81 int spanX = 1; 82 83 /** 84 * Indicates the Y cell span. 85 */ 86 int spanY = 1; 87 88 /** 89 * Indicates the minimum X cell span. 90 */ 91 int minSpanX = 1; 92 93 /** 94 * Indicates the minimum Y cell span. 95 */ 96 int minSpanY = 1; 97 98 /** 99 * Indicates that this item needs to be updated in the db 100 */ 101 boolean requiresDbUpdate = false; 102 103 /** 104 * Title of the item 105 */ 106 CharSequence title; 107 108 /** 109 * Content description for the item. 110 */ 111 CharSequence contentDescription; 112 113 /** 114 * The position of the item in a drag-and-drop operation. 115 */ 116 int[] dropPos = null; 117 118 UserHandle user; 119 ItemInfo()120 ItemInfo() { 121 user = android.os.Process.myUserHandle(); 122 } 123 ItemInfo(ItemInfo info)124 ItemInfo(ItemInfo info) { 125 id = info.id; 126 cellX = info.cellX; 127 cellY = info.cellY; 128 spanX = info.spanX; 129 spanY = info.spanY; 130 screen = info.screen; 131 itemType = info.itemType; 132 container = info.container; 133 user = info.user; 134 contentDescription = info.contentDescription; 135 // tempdebug: 136 LauncherModel.checkItemInfo(this); 137 } 138 139 /** Returns the package name that the intent will resolve to, or an empty string if 140 * none exists. */ getPackageName(Intent intent)141 static String getPackageName(Intent intent) { 142 if (intent != null) { 143 String packageName = intent.getPackage(); 144 if (packageName == null && intent.getComponent() != null) { 145 packageName = intent.getComponent().getPackageName(); 146 } 147 if (packageName != null) { 148 return packageName; 149 } 150 } 151 return ""; 152 } 153 updateUser(Intent intent)154 protected void updateUser(Intent intent) { 155 if (intent != null && intent.hasExtra(EXTRA_PROFILE)) { 156 user = (UserHandle) intent.getParcelableExtra(EXTRA_PROFILE); 157 } 158 } 159 160 /** 161 * Write the fields of this item to the DB 162 * 163 * @param context A context object to use for getting a UserManager 164 * instance. 165 * @param values 166 */ onAddToDatabase(Context context, ContentValues values)167 void onAddToDatabase(Context context, ContentValues values) { 168 values.put(LauncherSettings.BaseLauncherColumns.ITEM_TYPE, itemType); 169 values.put(LauncherSettings.Favorites.CONTAINER, container); 170 values.put(LauncherSettings.Favorites.SCREEN, screen); 171 values.put(LauncherSettings.Favorites.CELLX, cellX); 172 values.put(LauncherSettings.Favorites.CELLY, cellY); 173 values.put(LauncherSettings.Favorites.SPANX, spanX); 174 values.put(LauncherSettings.Favorites.SPANY, spanY); 175 long serialNumber = ((UserManager) context.getSystemService(Context.USER_SERVICE)) 176 .getSerialNumberForUser(user); 177 values.put(LauncherSettings.Favorites.PROFILE_ID, serialNumber); 178 } 179 updateValuesWithCoordinates(ContentValues values, int cellX, int cellY)180 void updateValuesWithCoordinates(ContentValues values, int cellX, int cellY) { 181 values.put(LauncherSettings.Favorites.CELLX, cellX); 182 values.put(LauncherSettings.Favorites.CELLY, cellY); 183 } 184 flattenBitmap(Bitmap bitmap)185 static byte[] flattenBitmap(Bitmap bitmap) { 186 // Try go guesstimate how much space the icon will take when serialized 187 // to avoid unnecessary allocations/copies during the write. 188 int size = bitmap.getWidth() * bitmap.getHeight() * 4; 189 ByteArrayOutputStream out = new ByteArrayOutputStream(size); 190 try { 191 bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); 192 out.flush(); 193 out.close(); 194 return out.toByteArray(); 195 } catch (IOException e) { 196 Log.w("Favorite", "Could not write icon"); 197 return null; 198 } 199 } 200 writeBitmap(ContentValues values, Bitmap bitmap)201 static void writeBitmap(ContentValues values, Bitmap bitmap) { 202 if (bitmap != null) { 203 byte[] data = flattenBitmap(bitmap); 204 values.put(LauncherSettings.Favorites.ICON, data); 205 } 206 } 207 208 /** 209 * It is very important that sub-classes implement this if they contain any references 210 * to the activity (anything in the view hierarchy etc.). If not, leaks can result since 211 * ItemInfo objects persist across rotation and can hence leak by holding stale references 212 * to the old view hierarchy / activity. 213 */ unbind()214 void unbind() { 215 } 216 217 @Override toString()218 public String toString() { 219 return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container 220 + " screen=" + screen + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX 221 + " spanY=" + spanY + " dropPos=" + dropPos + " user=" + user 222 + ")"; 223 } 224 } 225