AutoInstallsLayout.java revision cf0c746ec080ee528d4994c382562fda1e647752
10fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal/* 20fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * Copyright (C) 2014 The Android Open Source Project 30fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * 40fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * Licensed under the Apache License, Version 2.0 (the "License"); 50fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * you may not use this file except in compliance with the License. 60fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * You may obtain a copy of the License at 70fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * 80fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * http://www.apache.org/licenses/LICENSE-2.0 90fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * 100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * Unless required by applicable law or agreed to in writing, software 110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * distributed under the License is distributed on an "AS IS" BASIS, 120fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * See the License for the specific language governing permissions and 140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * limitations under the License. 150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal */ 160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 170fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalpackage com.android.launcher3; 180fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 190fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.appwidget.AppWidgetHost; 200fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.appwidget.AppWidgetManager; 210fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.ComponentName; 220fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.ContentValues; 230fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.Context; 240fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.Intent; 250fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.pm.ActivityInfo; 260fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.pm.PackageManager; 270fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.res.Resources; 280fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.content.res.XmlResourceParser; 290fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.database.sqlite.SQLiteDatabase; 300fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.graphics.drawable.Drawable; 310fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.net.Uri; 320fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.os.Bundle; 330fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.text.TextUtils; 340fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.util.Log; 350fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.util.Pair; 360fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport android.util.Patterns; 370fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 380fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport com.android.launcher3.LauncherProvider.SqlArguments; 390fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport com.android.launcher3.LauncherSettings.Favorites; 40091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk; 410fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 420fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport org.xmlpull.v1.XmlPullParser; 430fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport org.xmlpull.v1.XmlPullParserException; 440fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 450fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport java.io.IOException; 460fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport java.util.ArrayList; 470fe505bf82a265e51c556d7204976651cde7f55cSunny Goyalimport java.util.HashMap; 48b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyalimport java.util.Locale; 490fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 500fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal/** 513a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Layout parsing code for auto installs layout 520fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal */ 533a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyalpublic class AutoInstallsLayout { 540fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG = "AutoInstalls"; 553a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal private static final boolean LOGD = false; 560fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 570fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal /** Marker action used to discover a package which defines launcher customization */ 580fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal static final String ACTION_LAUNCHER_CUSTOMIZATION = 592233c8850d521defa82e358e3c5bae3ec75df426Sunny Goyal "android.autoinstalls.config.action.PLAY_AUTO_INSTALL"; 600fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 61b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal /** 62b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal * Layout resource which also includes grid size and hotseat count, e.g., default_layout_6x6_h5 63b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal */ 64b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal private static final String FORMATTED_LAYOUT_RES_WITH_HOSTEAT = "default_layout_%dx%d_h%s"; 65b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal private static final String FORMATTED_LAYOUT_RES = "default_layout_%dx%d"; 660fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String LAYOUT_RES = "default_layout"; 670fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 680fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal static AutoInstallsLayout get(Context context, AppWidgetHost appWidgetHost, 690fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal LayoutParserCallback callback) { 700fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Pair<String, Resources> customizationApkInfo = Utilities.findSystemApk( 710fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ACTION_LAUNCHER_CUSTOMIZATION, context.getPackageManager()); 720fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (customizationApkInfo == null) { 730fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return null; 740fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 75b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal return get(context, customizationApkInfo.first, customizationApkInfo.second, 76b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal appWidgetHost, callback); 77b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal } 78b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal 79b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal static AutoInstallsLayout get(Context context, String pkg, Resources targetRes, 80b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal AppWidgetHost appWidgetHost, LayoutParserCallback callback) { 812e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen InvariantDeviceProfile grid = LauncherAppState.getInstance().getInvariantDeviceProfile(); 82b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal 83b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal // Try with grid size and hotseat count 84b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal String layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES_WITH_HOSTEAT, 85b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal (int) grid.numColumns, (int) grid.numRows, (int) grid.numHotseatIcons); 86b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal int layoutId = targetRes.getIdentifier(layoutName, "xml", pkg); 87b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal 88b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal // Try with only grid size 89b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal if (layoutId == 0) { 90b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal Log.d(TAG, "Formatted layout: " + layoutName 91b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal + " not found. Trying layout without hosteat"); 92b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES, 93b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal (int) grid.numColumns, (int) grid.numRows); 94b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal layoutId = targetRes.getIdentifier(layoutName, "xml", pkg); 95b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal } 96b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal 97b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal // Try the default layout 98b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal if (layoutId == 0) { 99b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal Log.d(TAG, "Formatted layout: " + layoutName + " not found. Trying the default layout"); 100b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal layoutId = targetRes.getIdentifier(LAYOUT_RES, "xml", pkg); 101b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal } 1020fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1030fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (layoutId == 0) { 1040fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Log.e(TAG, "Layout definition not found in package: " + pkg); 1050fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return null; 1060fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 107b2d46ceaaa32ece85f18e049d9e30a5ccaf80e45Sunny Goyal return new AutoInstallsLayout(context, appWidgetHost, callback, targetRes, layoutId, 1083a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal TAG_WORKSPACE); 1090fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 1100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // Object Tags 112b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal private static final String TAG_INCLUDE = "include"; 1130fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_WORKSPACE = "workspace"; 1140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_APP_ICON = "appicon"; 1150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_AUTO_INSTALL = "autoinstall"; 1160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_FOLDER = "folder"; 1170fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_APPWIDGET = "appwidget"; 1180fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_SHORTCUT = "shortcut"; 1190fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String TAG_EXTRA = "extra"; 1200fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1210fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_CONTAINER = "container"; 1220fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_RANK = "rank"; 1230fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1240fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_PACKAGE_NAME = "packageName"; 1250fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_CLASS_NAME = "className"; 1260fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_TITLE = "title"; 1270fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_SCREEN = "screen"; 1280fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_X = "x"; 1290fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_Y = "y"; 1300fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_SPAN_X = "spanX"; 1310fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_SPAN_Y = "spanY"; 1320fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_ICON = "icon"; 1330fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_URL = "url"; 1340fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 135b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal // Attrs for "Include" 136b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal private static final String ATTR_WORKSPACE = "workspace"; 137b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal 1380fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // Style attrs -- "Extra" 1390fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_KEY = "key"; 1400fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ATTR_VALUE = "value"; 1410fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1420fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String HOTSEAT_CONTAINER_NAME = 1430fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Favorites.containerToString(Favorites.CONTAINER_HOTSEAT); 1440fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1450fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE = 1460fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE"; 1470fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 148091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen @Thunk final Context mContext; 149091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen @Thunk final AppWidgetHost mAppWidgetHost; 150bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal protected final LayoutParserCallback mCallback; 1510fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1523a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected final PackageManager mPackageManager; 1533a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected final Resources mSourceRes; 1543a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected final int mLayoutId; 1553a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 1563a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal private final int mHotseatAllAppsRank; 1570fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1583a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal private final long[] mTemp = new long[2]; 159091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen @Thunk final ContentValues mValues; 160bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal protected final String mRootTag; 1610fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1623a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected SQLiteDatabase mDb; 1630fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1640fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost, 1653a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal LayoutParserCallback callback, Resources res, 1663a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal int layoutId, String rootTag) { 167bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal this(context, appWidgetHost, callback, res, layoutId, rootTag, 1682e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen LauncherAppState.getInstance().getInvariantDeviceProfile().hotseatAllAppsRank); 169bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal } 170bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal 171bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost, 172bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal LayoutParserCallback callback, Resources res, 173bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal int layoutId, String rootTag, int hotseatAllAppsRank) { 1740fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mContext = context; 1750fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mAppWidgetHost = appWidgetHost; 1760fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mCallback = callback; 1770fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1780fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mPackageManager = context.getPackageManager(); 1790fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues = new ContentValues(); 1803a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mRootTag = rootTag; 1810fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1823a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mSourceRes = res; 1830fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mLayoutId = layoutId; 184bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal mHotseatAllAppsRank = hotseatAllAppsRank; 1850fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 1860fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 1873a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 1883a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Loads the layout in the db and returns the number of entries added on the desktop. 1893a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 1900fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) { 1910fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mDb = db; 1920fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal try { 1933a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return parseLayout(mLayoutId, screenIds); 1948fd74831de067fbadad180c54f70fb4a5375a933Sameer Padala } catch (Exception e) { 1950fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Log.w(TAG, "Got exception parsing layout.", e); 1960fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 1970fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 1980fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 1990fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 2003a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 2013a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Parses the layout and returns the number of elements added on the homescreen. 2023a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 2033a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected int parseLayout(int layoutId, ArrayList<Long> screenIds) 2040fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throws XmlPullParserException, IOException { 2053a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal XmlResourceParser parser = mSourceRes.getXml(layoutId); 2063a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal beginDocument(parser, mRootTag); 2070fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final int depth = parser.getDepth(); 2080fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int type; 2090fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal HashMap<String, TagParser> tagParserMap = getLayoutElementsMap(); 2100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int count = 0; 2110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 2120fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal while (((type = parser.next()) != XmlPullParser.END_TAG || 2130fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { 2140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (type != XmlPullParser.START_TAG) { 2150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal continue; 2160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 2173a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal count += parseAndAddNode(parser, tagParserMap, screenIds); 2183a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 2193a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return count; 2203a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 2210fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 2223a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 2233a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Parses container and screenId attribute from the current tag, and puts it in the out. 2243a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * @param out array of size 2. 2253a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 2263a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected void parseContainerAndScreen(XmlResourceParser parser, long[] out) { 2273a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (HOTSEAT_CONTAINER_NAME.equals(getAttributeValue(parser, ATTR_CONTAINER))) { 2283a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal out[0] = Favorites.CONTAINER_HOTSEAT; 2293a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal // Hack: hotseat items are stored using screen ids 2303a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal long rank = Long.parseLong(getAttributeValue(parser, ATTR_RANK)); 2313a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal out[1] = (rank < mHotseatAllAppsRank) ? rank : (rank + 1); 2323a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } else { 2333a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal out[0] = Favorites.CONTAINER_DESKTOP; 2343a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal out[1] = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN)); 2353a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 2363a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 2370fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 2383a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 2393a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Parses the current node and returns the number of elements added. 2403a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 2413a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected int parseAndAddNode( 2423a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal XmlResourceParser parser, 2433a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal HashMap<String, TagParser> tagParserMap, 2443a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal ArrayList<Long> screenIds) 2453a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal throws XmlPullParserException, IOException { 246b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal 247b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal if (TAG_INCLUDE.equals(parser.getName())) { 248b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0); 249b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal if (resId != 0) { 250b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal // recursively load some more favorites, why not? 251b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal return parseLayout(resId, screenIds); 252b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal } else { 253b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal return 0; 254b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal } 255b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal } 256b564efb0244adf0fb8429940f9f716938c62a7acSunny Goyal 2573a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.clear(); 2583a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal parseContainerAndScreen(parser, mTemp); 2593a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal final long container = mTemp[0]; 2603a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal final long screenId = mTemp[1]; 2613a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 2623a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.CONTAINER, container); 2633a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.SCREEN, screenId); 2643a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X)); 2653a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y)); 2663a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 2673a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal TagParser tagParser = tagParserMap.get(parser.getName()); 2683a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (tagParser == null) { 2693a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName()); 2703a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return 0; 2713a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 2723a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal long newElementId = tagParser.parseAndAdd(parser); 2733a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (newElementId >= 0) { 2743a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal // Keep track of the set of screens which need to be added to the db. 2753a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (!screenIds.contains(screenId) && 2763a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal container == Favorites.CONTAINER_DESKTOP) { 2773a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal screenIds.add(screenId); 2780fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 2793a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return 1; 2800fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 2813a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return 0; 2820fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 2830fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 2840fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal protected long addShortcut(String title, Intent intent, int type) { 2850fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal long id = mCallback.generateNewItemId(); 2860fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.INTENT, intent.toUri(0)); 2870fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.TITLE, title); 2880fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.ITEM_TYPE, type); 2890fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.SPANX, 1); 2900fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.SPANY, 1); 2910fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites._ID, id); 2920fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (mCallback.insertAndCheck(mDb, mValues) < 0) { 2930fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 2940fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } else { 2950fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return id; 2960fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 2970fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 2980fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 2990fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal protected HashMap<String, TagParser> getFolderElementsMap() { 3000fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal HashMap<String, TagParser> parsers = new HashMap<String, TagParser>(); 3010fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parsers.put(TAG_APP_ICON, new AppShortcutParser()); 3020fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser()); 3033a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes)); 3040fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return parsers; 3050fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3060fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3070fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal protected HashMap<String, TagParser> getLayoutElementsMap() { 3080fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal HashMap<String, TagParser> parsers = new HashMap<String, TagParser>(); 3090fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parsers.put(TAG_APP_ICON, new AppShortcutParser()); 3100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser()); 3110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parsers.put(TAG_FOLDER, new FolderParser()); 3120fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parsers.put(TAG_APPWIDGET, new AppWidgetParser()); 3133a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes)); 3140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return parsers; 3150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3173a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected interface TagParser { 3180fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal /** 3190fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * Parses the tag and adds to the db 3200fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * @return the id of the row added or -1; 3210fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal */ 3223a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal long parseAndAdd(XmlResourceParser parser) 3230fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throws XmlPullParserException, IOException; 3240fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3250fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3263a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 3273a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * App shortcuts: required attributes packageName and className 3283a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 3293a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected class AppShortcutParser implements TagParser { 3300fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3310fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal @Override 3323a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public long parseAndAdd(XmlResourceParser parser) { 3330fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME); 3340fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String className = getAttributeValue(parser, ATTR_CLASS_NAME); 3350fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3360fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) { 3370fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ActivityInfo info; 3380fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal try { 3390fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ComponentName cn; 3400fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal try { 3410fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal cn = new ComponentName(packageName, className); 3420fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal info = mPackageManager.getActivityInfo(cn, 0); 3430fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } catch (PackageManager.NameNotFoundException nnfe) { 3440fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal String[] packages = mPackageManager.currentToCanonicalPackageNames( 3450fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal new String[] { packageName }); 3460fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal cn = new ComponentName(packages[0], className); 3470fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal info = mPackageManager.getActivityInfo(cn, 0); 3480fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3490fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final Intent intent = new Intent(Intent.ACTION_MAIN, null) 3500fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal .addCategory(Intent.CATEGORY_LAUNCHER) 3510fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal .setComponent(cn) 3520fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 3530fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 3540fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3550fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return addShortcut(info.loadLabel(mPackageManager).toString(), 3560fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal intent, Favorites.ITEM_TYPE_APPLICATION); 3570fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } catch (PackageManager.NameNotFoundException e) { 358cf0c746ec080ee528d4994c382562fda1e647752Adam Cohen Log.e(TAG, "Unable to add favorite: " + packageName + "/" + className, e); 3590fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3600fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 3610fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } else { 3623a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return invalidPackageOrClass(parser); 3630fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3640fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3653a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 3663a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 3673a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Helper method to allow extending the parser capabilities 3683a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 3693a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected long invalidPackageOrClass(XmlResourceParser parser) { 370cf0c746ec080ee528d4994c382562fda1e647752Adam Cohen Log.w(TAG, "Skipping invalid <favorite> with no component"); 3713a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return -1; 3723a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 3730fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3740fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3753a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 3763a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * AutoInstall: required attributes packageName and className 3773a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 3783a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected class AutoInstallParser implements TagParser { 3790fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 3800fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal @Override 3813a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public long parseAndAdd(XmlResourceParser parser) { 3820fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME); 3830fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String className = getAttributeValue(parser, ATTR_CLASS_NAME); 3840fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) { 3850fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component"); 3860fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 3870fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3880fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 389349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal mValues.put(Favorites.RESTORED, ShortcutInfo.FLAG_AUTOINTALL_ICON); 3900fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final Intent intent = new Intent(Intent.ACTION_MAIN, null) 3910fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal .addCategory(Intent.CATEGORY_LAUNCHER) 3920fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal .setComponent(new ComponentName(packageName, className)) 3930fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 3940fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 3950fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return addShortcut(mContext.getString(R.string.package_state_unknown), intent, 3960fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Favorites.ITEM_TYPE_APPLICATION); 3970fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3980fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 3990fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4003a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 4013a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Parses a web shortcut. Required attributes url, icon, title 4023a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 4033a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected class ShortcutParser implements TagParser { 4043a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 4053a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal private final Resources mIconRes; 4063a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 4073a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public ShortcutParser(Resources iconRes) { 4083a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mIconRes = iconRes; 4093a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 4100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal @Override 4123a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public long parseAndAdd(XmlResourceParser parser) { 4130fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0); 4140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final int iconId = getAttributeResourceValue(parser, ATTR_ICON, 0); 4150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (titleResId == 0 || iconId == 0) { 4170fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.d(TAG, "Ignoring shortcut"); 4180fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 4190fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4200fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4213a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal final Intent intent = parseIntent(parser); 4223a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (intent == null) { 4230fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 4240fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4253a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 4263a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal Drawable icon = mIconRes.getDrawable(iconId); 4270fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (icon == null) { 4280fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.d(TAG, "Ignoring shortcut, can't load icon"); 4290fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 4300fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4310fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4320fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ItemInfo.writeBitmap(mValues, Utilities.createIconBitmap(icon, mContext)); 4333a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE); 4343a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId)); 4353a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId)); 4363a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 4373a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 4380fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 4393a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return addShortcut(mSourceRes.getString(titleResId), 4403a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal intent, Favorites.ITEM_TYPE_SHORTCUT); 4413a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 4423a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 4433a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected Intent parseIntent(XmlResourceParser parser) { 4443a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal final String url = getAttributeValue(parser, ATTR_URL); 4453a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) { 4463a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url); 4473a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return null; 4483a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 4493a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal return new Intent(Intent.ACTION_VIEW, null).setData(Uri.parse(url)); 4500fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4510fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4520fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4533a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal /** 4543a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * AppWidget parser: Required attributes packageName, className, spanX and spanY. 4553a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal * Options child nodes: <extra key=... value=... /> 4563a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal */ 4573a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected class AppWidgetParser implements TagParser { 4580fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4590fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal @Override 4603a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public long parseAndAdd(XmlResourceParser parser) 4610fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throws XmlPullParserException, IOException { 4620fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME); 4630fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String className = getAttributeValue(parser, ATTR_CLASS_NAME); 4640fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) { 4650fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component"); 4660fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 4670fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4680fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4690fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ComponentName cn = new ComponentName(packageName, className); 4700fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal try { 4710fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mPackageManager.getReceiverInfo(cn, 0); 4720fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } catch (Exception e) { 4730fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal String[] packages = mPackageManager.currentToCanonicalPackageNames( 4740fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal new String[] { packageName }); 4750fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal cn = new ComponentName(packages[0], className); 4760fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal try { 4770fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mPackageManager.getReceiverInfo(cn, 0); 4780fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } catch (Exception e1) { 4790fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.d(TAG, "Can't find widget provider: " + className); 4800fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 4810fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4820fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4830fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4840fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.SPANX, getAttributeValue(parser, ATTR_SPAN_X)); 4850fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.SPANY, getAttributeValue(parser, ATTR_SPAN_Y)); 4860fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4870fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // Read the extras 4880fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Bundle extras = new Bundle(); 4890fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int widgetDepth = parser.getDepth(); 4900fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int type; 4910fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal while ((type = parser.next()) != XmlPullParser.END_TAG || 4920fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parser.getDepth() > widgetDepth) { 4930fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (type != XmlPullParser.START_TAG) { 4940fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal continue; 4950fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 4960fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 4970fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (TAG_EXTRA.equals(parser.getName())) { 4980fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal String key = getAttributeValue(parser, ATTR_KEY); 4990fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal String value = getAttributeValue(parser, ATTR_VALUE); 5000fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (key != null && value != null) { 5010fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal extras.putString(key, value); 5020fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } else { 5030fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throw new RuntimeException("Widget extras must have a key and value"); 5040fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5050fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } else { 5060fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throw new RuntimeException("Widgets can contain only extras"); 5070fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5080fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5090fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext); 5110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal long insertedId = -1; 5120fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal try { 5130fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); 5140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn)) { 5160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.e(TAG, "Unable to bind app widget id " + cn); 5170fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 5180fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5190fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5200fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET); 5210fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.APPWIDGET_ID, appWidgetId); 5220fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString()); 5230fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites._ID, mCallback.generateNewItemId()); 5240fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal insertedId = mCallback.insertAndCheck(mDb, mValues); 5250fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (insertedId < 0) { 5260fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mAppWidgetHost.deleteAppWidgetId(appWidgetId); 5270fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return insertedId; 5280fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5290fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5300fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // Send a broadcast to configure the widget 5310fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (!extras.isEmpty()) { 5320fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE); 5330fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal intent.setComponent(cn); 5340fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal intent.putExtras(extras); 5350fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 5360fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mContext.sendBroadcast(intent); 5370fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5380fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } catch (RuntimeException ex) { 5390fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.e(TAG, "Problem allocating appWidgetId", ex); 5400fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5410fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return insertedId; 5420fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5430fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5440fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5453a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected class FolderParser implements TagParser { 5463a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal private final HashMap<String, TagParser> mFolderElements; 5473a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 5483a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public FolderParser() { 5493a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal this(getFolderElementsMap()); 5503a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 5513a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal 5523a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public FolderParser(HashMap<String, TagParser> elements) { 5533a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal mFolderElements = elements; 5543a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal } 5550fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5560fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal @Override 5573a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal public long parseAndAdd(XmlResourceParser parser) 5580fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throws XmlPullParserException, IOException { 5590fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final String title; 5600fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0); 5610fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (titleResId != 0) { 5623a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal title = mSourceRes.getString(titleResId); 5630fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } else { 5640fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal title = mContext.getResources().getString(R.string.folder_name); 5650fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5660fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5670fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.TITLE, title); 5680fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER); 5690fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.SPANX, 1); 5700fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.SPANY, 1); 5710fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites._ID, mCallback.generateNewItemId()); 5720fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal long folderId = mCallback.insertAndCheck(mDb, mValues); 5730fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (folderId < 0) { 5740fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (LOGD) Log.e(TAG, "Unable to add folder"); 5750fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return -1; 5760fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5770fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5780fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final ContentValues myValues = new ContentValues(mValues); 5790fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ArrayList<Long> folderItems = new ArrayList<Long>(); 5800fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5810fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int type; 5820fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int folderDepth = parser.getDepth(); 58356a57bb6bbcdfd3f309727fcfcbbc896f583ded9Sunny Goyal int rank = 0; 5840fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal while ((type = parser.next()) != XmlPullParser.END_TAG || 5850fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal parser.getDepth() > folderDepth) { 5860fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (type != XmlPullParser.START_TAG) { 5870fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal continue; 5880fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 5890fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.clear(); 5900fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mValues.put(Favorites.CONTAINER, folderId); 59156a57bb6bbcdfd3f309727fcfcbbc896f583ded9Sunny Goyal mValues.put(Favorites.RANK, rank); 5920fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 5930fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal TagParser tagParser = mFolderElements.get(parser.getName()); 5940fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (tagParser != null) { 5953a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal final long id = tagParser.parseAndAdd(parser); 5960fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (id >= 0) { 5970fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal folderItems.add(id); 59856a57bb6bbcdfd3f309727fcfcbbc896f583ded9Sunny Goyal rank++; 5990fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6000fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } else { 6010fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throw new RuntimeException("Invalid folder item " + parser.getName()); 6020fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6030fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6040fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6050fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal long addedId = folderId; 6060fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6070fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // We can only have folders with >= 2 items, so we need to remove the 6080fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // folder and clean up if less than 2 items were included, or some 6090fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // failed to add, and less than 2 were actually added 6100fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (folderItems.size() < 2) { 6110fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // Delete the folder 6121d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal Uri uri = Favorites.getContentUri(folderId); 6130fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal SqlArguments args = new SqlArguments(uri, null, null); 6140fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mDb.delete(args.table, args.where, args.args); 6150fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal addedId = -1; 6160fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6170fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // If we have a single item, promote it to where the folder 6180fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal // would have been. 6190fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (folderItems.size() == 1) { 6200fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal final ContentValues childValues = new ContentValues(); 6210fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal copyInteger(myValues, childValues, Favorites.CONTAINER); 6220fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal copyInteger(myValues, childValues, Favorites.SCREEN); 6230fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal copyInteger(myValues, childValues, Favorites.CELLX); 6240fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal copyInteger(myValues, childValues, Favorites.CELLY); 6250fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6260fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal addedId = folderItems.get(0); 6270fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal mDb.update(LauncherProvider.TABLE_FAVORITES, childValues, 6280fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal Favorites._ID + "=" + addedId, null); 6290fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6300fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6310fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return addedId; 6320fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6330fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6340fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6353a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected static final void beginDocument(XmlPullParser parser, String firstElementName) 6360fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throws XmlPullParserException, IOException { 6370fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int type; 6380fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal while ((type = parser.next()) != XmlPullParser.START_TAG 6390fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal && type != XmlPullParser.END_DOCUMENT); 6400fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6410fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (type != XmlPullParser.START_TAG) { 6420fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throw new XmlPullParserException("No start tag found"); 6430fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6440fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6450fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (!parser.getName().equals(firstElementName)) { 6460fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + 6470fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal ", expected " + firstElementName); 6480fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6490fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6500fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6510fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal /** 6520fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * Return attribute value, attempting launcher-specific namespace first 6530fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * before falling back to anonymous attribute. 6540fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal */ 6553a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected static String getAttributeValue(XmlResourceParser parser, String attribute) { 6560fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal String value = parser.getAttributeValue( 6570fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute); 6580fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (value == null) { 6590fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal value = parser.getAttributeValue(null, attribute); 6600fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6610fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return value; 6620fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6630fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6640fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal /** 6650fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * Return attribute resource value, attempting launcher-specific namespace 6660fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal * first before falling back to anonymous attribute. 6670fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal */ 6683a5a9d18daacb878a3eb379fce540ee6c67063e6Sunny Goyal protected static int getAttributeResourceValue(XmlResourceParser parser, String attribute, 6690fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int defaultValue) { 6700fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal int value = parser.getAttributeResourceValue( 6710fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute, 6720fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal defaultValue); 6730fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal if (value == defaultValue) { 6740fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal value = parser.getAttributeResourceValue(null, attribute, defaultValue); 6750fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6760fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal return value; 6770fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6780fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6790fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal public static interface LayoutParserCallback { 6800fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal long generateNewItemId(); 6810fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 6820fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal long insertAndCheck(SQLiteDatabase db, ContentValues values); 6830fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6840fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal 685091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen @Thunk static void copyInteger(ContentValues from, ContentValues to, String key) { 6860fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal to.put(key, from.getAsInteger(key)); 6870fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal } 6880fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal} 689