Loading src/com/android/launcher3/LauncherModel.java +109 −108 Original line number Diff line number Diff line Loading @@ -1144,8 +1144,6 @@ public class LauncherModel extends BroadcastReceiver HashMap<ComponentKey, AppWidgetProviderInfo> widgetProvidersMap = null; try { final int intentIndex = c.getColumnIndexOrThrow (LauncherSettings.Favorites.INTENT); final int appWidgetIdIndex = c.getColumnIndexOrThrow( LauncherSettings.Favorites.APPWIDGET_ID); final int appWidgetProviderIndex = c.getColumnIndexOrThrow( Loading Loading @@ -1192,7 +1190,7 @@ public class LauncherModel extends BroadcastReceiver String intentDescription; LauncherAppWidgetInfo appWidgetInfo; Intent intent; String targetPackage; String targetPkg; while (!mStopped && c.moveToNext()) { try { Loading @@ -1204,116 +1202,126 @@ public class LauncherModel extends BroadcastReceiver boolean allowMissingTarget = false; switch (c.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: { case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: intent = c.parseIntent(); if (intent == null) { c.markDeleted("Invalid or null intent"); continue; } int disabledState = quietMode.get(c.serialNumber) ? ShortcutInfo.FLAG_DISABLED_QUIET_USER : 0; ComponentName cn = intent.getComponent(); targetPkg = cn == null ? intent.getPackage() : cn.getPackageName(); if (!Process.myUserHandle().equals(c.user)) { if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { c.markDeleted("Legacy shortcuts are only allowed for default user"); continue; } else if (c.restoreFlag != 0) { // Don't restore items for other profiles. c.markDeleted("Restore from managed profile not supported"); continue; } // Follow through. } case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: intentDescription = c.getString(intentIndex); int disabledState = 0; targetPackage = null; try { intent = Intent.parseUri(intentDescription, 0); ComponentName cn = intent.getComponent(); if (cn != null && cn.getPackageName() != null) { boolean validPkg = launcherApps.isPackageEnabledForProfile( cn.getPackageName(), c.user); boolean validComponent = validPkg && launcherApps.isActivityEnabledForProfile(cn, c.user); if (validPkg) { targetPackage = cn.getPackageName(); if (TextUtils.isEmpty(targetPkg) && c.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { c.markDeleted("Only legacy shortcuts can have null package"); continue; } if (validComponent) { // If there is no target package, its an implicit intent // (legacy shortcut) which is always valid boolean validTarget = TextUtils.isEmpty(targetPkg) || launcherApps.isPackageEnabledForProfile(targetPkg, c.user); if (cn != null && validTarget) { // If the apk is present and the shortcut points to a specific // component. // If the component is already present if (launcherApps.isActivityEnabledForProfile(cn, c.user)) { // no special handling necessary for this item c.markRestored(); if (quietMode.get(c.serialNumber)) { disabledState = ShortcutInfo.FLAG_DISABLED_QUIET_USER; } } else if (validPkg) { intent = null; } else { if (c.hasRestoreFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) { // We allow auto install apps to have their intent // updated after an install. intent = manager.getLaunchIntentForPackage( cn.getPackageName()); intent = manager.getLaunchIntentForPackage(targetPkg); if (intent != null) { c.restoreFlag = 0; c.updater().put( LauncherSettings.Favorites.INTENT, intent.toUri(0)).commit(); cn = intent.getComponent(); } else { c.markDeleted("Unable to find a launch target"); continue; } } if (intent == null) { } else { // The app is installed but the component is no // longer available. c.markDeleted("Invalid component removed: " + cn); continue; } else { // no special handling necessary for this item c.markRestored(); } } else if (c.restoreFlag != 0) { } } // else if cn == null => can't infer much, leave it // else if !validPkg => could be restored icon or missing sd-card if (!TextUtils.isEmpty(targetPkg) && !validTarget) { // Points to a valid app (superset of cn != null) but the apk // is not available. if (c.restoreFlag != 0) { // Package is not yet available but might be // installed later. FileLog.d(TAG, "package not yet restored: " + cn); FileLog.d(TAG, "package not yet restored: " + targetPkg); if (c.hasRestoreFlag(ShortcutInfo.FLAG_RESTORE_STARTED)) { // Restore has started once. } else if (installingPkgs.containsKey(cn.getPackageName())) { } else if (installingPkgs.containsKey(targetPkg)) { // App restore has started. Update the flag c.restoreFlag |= ShortcutInfo.FLAG_RESTORE_STARTED; c.updater().put( LauncherSettings.Favorites.RESTORED, c.restoreFlag).commit(); c.updater().commit(); } else { c.markDeleted("Unrestored package removed: " + cn); c.markDeleted("Unrestored app removed: " + targetPkg); continue; } } else if (PackageManagerHelper.isAppOnSdcard( manager, cn.getPackageName())) { manager, targetPkg)) { // Package is present but not available. disabledState |= ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE; // Add the icon on the workspace anyway. allowMissingTarget = true; disabledState = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE; } else if (!isSdCardReady) { // SdCard is not ready yet. Package might get available, // once it is ready. Log.d(TAG, "Invalid package: " + cn + " (check again later)"); pendingPackages.addToList(c.user, cn.getPackageName()); allowMissingTarget = true; Log.d(TAG, "Missing pkg, will check later: " + targetPkg); pendingPackages.addToList(c.user, targetPkg); // Add the icon on the workspace anyway. allowMissingTarget = true; } else { // Do not wait for external media load anymore. // Log the invalid package, and remove it c.markDeleted("Invalid package removed: " + cn); c.markDeleted("Invalid package removed: " + targetPkg); continue; } } else if (cn == null) { // For shortcuts with no component, keep them as they are c.markRestored(); } } catch (URISyntaxException e) { c.markDeleted("Invalid uri: " + intentDescription); continue; if (validTarget) { // The shortcut points to a valid target (either no target // or something which is ready to be used) c.markRestored(); } boolean useLowResIcon = !c.isOnWorkspaceOrHotseat() && c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW; if (c.restoreFlag != 0) { if (c.user.equals(Process.myUserHandle())) { // Already verified above that user is same as default user info = c.getRestoredItemInfo(intent); } else { // Don't restore items for other profiles. c.markDeleted("Restore from managed profile not supported"); continue; } } else if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { info = c.getAppShortcutInfo( Loading Loading @@ -1343,7 +1351,7 @@ public class LauncherModel extends BroadcastReceiver info = c.loadSimpleShortcut(); // Shortcuts are only available on the primary profile if (PackageManagerHelper.isAppSuspended(manager, targetPackage)) { if (PackageManagerHelper.isAppSuspended(manager, targetPkg)) { disabledState |= ShortcutInfo.FLAG_DISABLED_SUSPENDED; } Loading Loading @@ -1375,17 +1383,14 @@ public class LauncherModel extends BroadcastReceiver info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE; } if (c.restoreFlag != 0) { ComponentName cn = info.getTargetComponent(); if (cn != null) { Integer progress = installingPkgs.get(cn.getPackageName()); if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) { Integer progress = installingPkgs.get(targetPkg); if (progress != null) { info.setInstallProgress(progress); } else { info.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE; } } } c.checkAndAddItem(info, sBgDataModel); } else { Loading Loading @@ -1489,11 +1494,7 @@ public class LauncherModel extends BroadcastReceiver } if (appWidgetInfo.hasRestoreFlag( LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) { intentDescription = c.getString(intentIndex); if (!TextUtils.isEmpty(intentDescription)) { appWidgetInfo.bindOptions = Intent.parseUri(intentDescription, 0); } appWidgetInfo.bindOptions = c.parseIntent(); } c.applyCommonProperties(appWidgetInfo); Loading src/com/android/launcher3/LauncherSettings.java +1 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ public class LauncherSettings { public static final String MODIFIED = "modified"; } static interface BaseLauncherColumns extends ChangeLogColumns { static public interface BaseLauncherColumns extends ChangeLogColumns { /** * Descriptive name of the gesture that can be displayed to the user. * <P>Type: TEXT</P> Loading src/com/android/launcher3/model/LoaderCursor.java +14 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.PackageManagerHelper; import java.net.URISyntaxException; import java.security.InvalidParameterException; import java.util.ArrayList; Loading Loading @@ -84,6 +85,7 @@ public class LoaderCursor extends CursorWrapper { private final int cellYIndex; private final int profileIdIndex; private final int restoredIndex; private final int intentIndex; // Properties loaded per iteration public long serialNumber; Loading Loading @@ -114,6 +116,7 @@ public class LoaderCursor extends CursorWrapper { cellYIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); profileIdIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID); restoredIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.RESTORED); intentIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); } @Override Loading @@ -131,6 +134,17 @@ public class LoaderCursor extends CursorWrapper { return result; } public Intent parseIntent() { String intentDescription = getString(intentIndex); try { return TextUtils.isEmpty(intentDescription) ? null : Intent.parseUri(intentDescription, 0); } catch (URISyntaxException e) { Log.e(TAG, "Error parsing Intent"); return null; } } public ShortcutInfo loadSimpleShortcut() { final ShortcutInfo info = new ShortcutInfo(); // Non-app shortcuts are only supported for current user. Loading tests/src/com/android/launcher3/model/LoaderCursorTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Arrays; import static com.android.launcher3.LauncherSettings.BaseLauncherColumns.INTENT; import static com.android.launcher3.LauncherSettings.Favorites.CELLX; import static com.android.launcher3.LauncherSettings.Favorites.CELLY; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER; Loading Loading @@ -73,7 +74,7 @@ public class LoaderCursorTest { mCursor = new MatrixCursor(new String[] { ICON, ICON_PACKAGE, ICON_RESOURCE, TITLE, _ID, CONTAINER, ITEM_TYPE, PROFILE_ID, SCREEN, CELLX, CELLY, RESTORED SCREEN, CELLX, CELLY, RESTORED, INTENT }); mContext = InstrumentationRegistry.getTargetContext(); Loading Loading
src/com/android/launcher3/LauncherModel.java +109 −108 Original line number Diff line number Diff line Loading @@ -1144,8 +1144,6 @@ public class LauncherModel extends BroadcastReceiver HashMap<ComponentKey, AppWidgetProviderInfo> widgetProvidersMap = null; try { final int intentIndex = c.getColumnIndexOrThrow (LauncherSettings.Favorites.INTENT); final int appWidgetIdIndex = c.getColumnIndexOrThrow( LauncherSettings.Favorites.APPWIDGET_ID); final int appWidgetProviderIndex = c.getColumnIndexOrThrow( Loading Loading @@ -1192,7 +1190,7 @@ public class LauncherModel extends BroadcastReceiver String intentDescription; LauncherAppWidgetInfo appWidgetInfo; Intent intent; String targetPackage; String targetPkg; while (!mStopped && c.moveToNext()) { try { Loading @@ -1204,116 +1202,126 @@ public class LauncherModel extends BroadcastReceiver boolean allowMissingTarget = false; switch (c.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: { case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: intent = c.parseIntent(); if (intent == null) { c.markDeleted("Invalid or null intent"); continue; } int disabledState = quietMode.get(c.serialNumber) ? ShortcutInfo.FLAG_DISABLED_QUIET_USER : 0; ComponentName cn = intent.getComponent(); targetPkg = cn == null ? intent.getPackage() : cn.getPackageName(); if (!Process.myUserHandle().equals(c.user)) { if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { c.markDeleted("Legacy shortcuts are only allowed for default user"); continue; } else if (c.restoreFlag != 0) { // Don't restore items for other profiles. c.markDeleted("Restore from managed profile not supported"); continue; } // Follow through. } case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: intentDescription = c.getString(intentIndex); int disabledState = 0; targetPackage = null; try { intent = Intent.parseUri(intentDescription, 0); ComponentName cn = intent.getComponent(); if (cn != null && cn.getPackageName() != null) { boolean validPkg = launcherApps.isPackageEnabledForProfile( cn.getPackageName(), c.user); boolean validComponent = validPkg && launcherApps.isActivityEnabledForProfile(cn, c.user); if (validPkg) { targetPackage = cn.getPackageName(); if (TextUtils.isEmpty(targetPkg) && c.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { c.markDeleted("Only legacy shortcuts can have null package"); continue; } if (validComponent) { // If there is no target package, its an implicit intent // (legacy shortcut) which is always valid boolean validTarget = TextUtils.isEmpty(targetPkg) || launcherApps.isPackageEnabledForProfile(targetPkg, c.user); if (cn != null && validTarget) { // If the apk is present and the shortcut points to a specific // component. // If the component is already present if (launcherApps.isActivityEnabledForProfile(cn, c.user)) { // no special handling necessary for this item c.markRestored(); if (quietMode.get(c.serialNumber)) { disabledState = ShortcutInfo.FLAG_DISABLED_QUIET_USER; } } else if (validPkg) { intent = null; } else { if (c.hasRestoreFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) { // We allow auto install apps to have their intent // updated after an install. intent = manager.getLaunchIntentForPackage( cn.getPackageName()); intent = manager.getLaunchIntentForPackage(targetPkg); if (intent != null) { c.restoreFlag = 0; c.updater().put( LauncherSettings.Favorites.INTENT, intent.toUri(0)).commit(); cn = intent.getComponent(); } else { c.markDeleted("Unable to find a launch target"); continue; } } if (intent == null) { } else { // The app is installed but the component is no // longer available. c.markDeleted("Invalid component removed: " + cn); continue; } else { // no special handling necessary for this item c.markRestored(); } } else if (c.restoreFlag != 0) { } } // else if cn == null => can't infer much, leave it // else if !validPkg => could be restored icon or missing sd-card if (!TextUtils.isEmpty(targetPkg) && !validTarget) { // Points to a valid app (superset of cn != null) but the apk // is not available. if (c.restoreFlag != 0) { // Package is not yet available but might be // installed later. FileLog.d(TAG, "package not yet restored: " + cn); FileLog.d(TAG, "package not yet restored: " + targetPkg); if (c.hasRestoreFlag(ShortcutInfo.FLAG_RESTORE_STARTED)) { // Restore has started once. } else if (installingPkgs.containsKey(cn.getPackageName())) { } else if (installingPkgs.containsKey(targetPkg)) { // App restore has started. Update the flag c.restoreFlag |= ShortcutInfo.FLAG_RESTORE_STARTED; c.updater().put( LauncherSettings.Favorites.RESTORED, c.restoreFlag).commit(); c.updater().commit(); } else { c.markDeleted("Unrestored package removed: " + cn); c.markDeleted("Unrestored app removed: " + targetPkg); continue; } } else if (PackageManagerHelper.isAppOnSdcard( manager, cn.getPackageName())) { manager, targetPkg)) { // Package is present but not available. disabledState |= ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE; // Add the icon on the workspace anyway. allowMissingTarget = true; disabledState = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE; } else if (!isSdCardReady) { // SdCard is not ready yet. Package might get available, // once it is ready. Log.d(TAG, "Invalid package: " + cn + " (check again later)"); pendingPackages.addToList(c.user, cn.getPackageName()); allowMissingTarget = true; Log.d(TAG, "Missing pkg, will check later: " + targetPkg); pendingPackages.addToList(c.user, targetPkg); // Add the icon on the workspace anyway. allowMissingTarget = true; } else { // Do not wait for external media load anymore. // Log the invalid package, and remove it c.markDeleted("Invalid package removed: " + cn); c.markDeleted("Invalid package removed: " + targetPkg); continue; } } else if (cn == null) { // For shortcuts with no component, keep them as they are c.markRestored(); } } catch (URISyntaxException e) { c.markDeleted("Invalid uri: " + intentDescription); continue; if (validTarget) { // The shortcut points to a valid target (either no target // or something which is ready to be used) c.markRestored(); } boolean useLowResIcon = !c.isOnWorkspaceOrHotseat() && c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW; if (c.restoreFlag != 0) { if (c.user.equals(Process.myUserHandle())) { // Already verified above that user is same as default user info = c.getRestoredItemInfo(intent); } else { // Don't restore items for other profiles. c.markDeleted("Restore from managed profile not supported"); continue; } } else if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { info = c.getAppShortcutInfo( Loading Loading @@ -1343,7 +1351,7 @@ public class LauncherModel extends BroadcastReceiver info = c.loadSimpleShortcut(); // Shortcuts are only available on the primary profile if (PackageManagerHelper.isAppSuspended(manager, targetPackage)) { if (PackageManagerHelper.isAppSuspended(manager, targetPkg)) { disabledState |= ShortcutInfo.FLAG_DISABLED_SUSPENDED; } Loading Loading @@ -1375,17 +1383,14 @@ public class LauncherModel extends BroadcastReceiver info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE; } if (c.restoreFlag != 0) { ComponentName cn = info.getTargetComponent(); if (cn != null) { Integer progress = installingPkgs.get(cn.getPackageName()); if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) { Integer progress = installingPkgs.get(targetPkg); if (progress != null) { info.setInstallProgress(progress); } else { info.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE; } } } c.checkAndAddItem(info, sBgDataModel); } else { Loading Loading @@ -1489,11 +1494,7 @@ public class LauncherModel extends BroadcastReceiver } if (appWidgetInfo.hasRestoreFlag( LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) { intentDescription = c.getString(intentIndex); if (!TextUtils.isEmpty(intentDescription)) { appWidgetInfo.bindOptions = Intent.parseUri(intentDescription, 0); } appWidgetInfo.bindOptions = c.parseIntent(); } c.applyCommonProperties(appWidgetInfo); Loading
src/com/android/launcher3/LauncherSettings.java +1 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ public class LauncherSettings { public static final String MODIFIED = "modified"; } static interface BaseLauncherColumns extends ChangeLogColumns { static public interface BaseLauncherColumns extends ChangeLogColumns { /** * Descriptive name of the gesture that can be displayed to the user. * <P>Type: TEXT</P> Loading
src/com/android/launcher3/model/LoaderCursor.java +14 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.PackageManagerHelper; import java.net.URISyntaxException; import java.security.InvalidParameterException; import java.util.ArrayList; Loading Loading @@ -84,6 +85,7 @@ public class LoaderCursor extends CursorWrapper { private final int cellYIndex; private final int profileIdIndex; private final int restoredIndex; private final int intentIndex; // Properties loaded per iteration public long serialNumber; Loading Loading @@ -114,6 +116,7 @@ public class LoaderCursor extends CursorWrapper { cellYIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); profileIdIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID); restoredIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.RESTORED); intentIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); } @Override Loading @@ -131,6 +134,17 @@ public class LoaderCursor extends CursorWrapper { return result; } public Intent parseIntent() { String intentDescription = getString(intentIndex); try { return TextUtils.isEmpty(intentDescription) ? null : Intent.parseUri(intentDescription, 0); } catch (URISyntaxException e) { Log.e(TAG, "Error parsing Intent"); return null; } } public ShortcutInfo loadSimpleShortcut() { final ShortcutInfo info = new ShortcutInfo(); // Non-app shortcuts are only supported for current user. Loading
tests/src/com/android/launcher3/model/LoaderCursorTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Arrays; import static com.android.launcher3.LauncherSettings.BaseLauncherColumns.INTENT; import static com.android.launcher3.LauncherSettings.Favorites.CELLX; import static com.android.launcher3.LauncherSettings.Favorites.CELLY; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER; Loading Loading @@ -73,7 +74,7 @@ public class LoaderCursorTest { mCursor = new MatrixCursor(new String[] { ICON, ICON_PACKAGE, ICON_RESOURCE, TITLE, _ID, CONTAINER, ITEM_TYPE, PROFILE_ID, SCREEN, CELLX, CELLY, RESTORED SCREEN, CELLX, CELLY, RESTORED, INTENT }); mContext = InstrumentationRegistry.getTargetContext(); Loading