Replace the launcher telephony apps with the default work profile one
when using AutoInstalls or when restoring, and when work telephony is
enabled.

Test: atest RestoreDbTaskTest
Bug: 258631628
Change-Id: I3e699e5c34c09daf60e29724eda04282493673e7
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 55ede6c..27c41c2 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -16,11 +16,14 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+
 import android.content.ComponentName;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.LauncherActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.sqlite.SQLiteDatabase;
@@ -40,9 +43,12 @@
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.qsb.QsbContainerView;
+import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
@@ -53,6 +59,7 @@
 
 import java.io.IOException;
 import java.util.Locale;
+import java.util.Map;
 import java.util.function.Supplier;
 
 /**
@@ -162,7 +169,7 @@
     private final InvariantDeviceProfile mIdp;
     private final int mRowCount;
     private final int mColumnCount;
-
+    private final Map<String, LauncherActivityInfo> mActivityOverride;
     private final int[] mTemp = new int[2];
     @Thunk
     final ContentValues mValues;
@@ -193,6 +200,7 @@
         mIdp = LauncherAppState.getIDP(context);
         mRowCount = mIdp.numRows;
         mColumnCount = mIdp.numColumns;
+        mActivityOverride = ApiWrapper.getActivityOverrides(context);
     }
 
     /**
@@ -299,6 +307,9 @@
         mValues.put(Favorites.SPANX, 1);
         mValues.put(Favorites.SPANY, 1);
         mValues.put(Favorites._ID, id);
+
+        maybeReplaceShortcut(intent.getComponent().getPackageName(), type);
+
         if (mCallback.insertAndCheck(mDb, mValues) < 0) {
             return -1;
         } else {
@@ -364,7 +375,7 @@
                                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
 
                     return addShortcut(info.loadLabel(mPackageManager).toString(),
-                            intent, Favorites.ITEM_TYPE_APPLICATION);
+                            intent, ITEM_TYPE_APPLICATION);
                 } catch (PackageManager.NameNotFoundException e) {
                     Log.e(TAG, "Favorite not found: " + packageName + "/" + className);
                 }
@@ -404,7 +415,7 @@
                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                             | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
-                    Favorites.ITEM_TYPE_APPLICATION);
+                    ITEM_TYPE_APPLICATION);
         }
     }
 
@@ -573,8 +584,7 @@
         }
 
         @Override
-        public int parseAndAdd(XmlPullParser parser)
-                throws XmlPullParserException, IOException {
+        public int parseAndAdd(XmlPullParser parser) throws XmlPullParserException, IOException {
             final String title;
             final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
             if (titleResId != 0) {
@@ -717,4 +727,13 @@
     static void copyInteger(ContentValues from, ContentValues to, String key) {
         to.put(key, from.getAsInteger(key));
     }
+
+    private void maybeReplaceShortcut(String packageName, int type) {
+        if (mActivityOverride.containsKey(packageName) && type == ITEM_TYPE_APPLICATION) {
+            LauncherActivityInfo replacementInfo = mActivityOverride.get(packageName);
+            mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
+                    .getSerialNumberForUser(replacementInfo.getUser()));
+            mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
+        }
+    }
 }
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 2a452be..5789a6c 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -20,15 +20,19 @@
 import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
 import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
 import static com.android.launcher3.LauncherPrefs.RESTORE_DEVICE;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
 
 import android.app.backup.BackupManager;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherActivityInfo;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.SparseLongArray;
 
@@ -44,15 +48,21 @@
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.model.DeviceGridState;
 import com.android.launcher3.model.GridBackupTable;
+import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
+import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.LogConfig;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 
 import java.io.InvalidObjectException;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * Utility class to update DB schema after it has been restored.
@@ -159,6 +169,7 @@
      *   3. If the user serial for any restored profile is different than that of the previous
      *      device, update the entries to the new profile id.
      *   4. If restored from a single display backup, remove gaps between screenIds
+     *   5. Override shortcuts that need to be replaced.
      *
      * @return number of items deleted.
      */
@@ -245,6 +256,9 @@
             removeScreenIdGaps(db);
         }
 
+        // Override shortcuts
+        maybeOverrideShortcuts(context, db, myProfileId);
+
         return itemsDeleted;
     }
 
@@ -374,4 +388,48 @@
                 APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString()));
     }
 
+    protected static void maybeOverrideShortcuts(Context context, SQLiteDatabase db,
+            long currentUser) {
+        Map<String, LauncherActivityInfo> activityOverrides = ApiWrapper.getActivityOverrides(
+                context);
+
+        if (activityOverrides == null || activityOverrides.isEmpty()) {
+            return;
+        }
+
+        try (Cursor c = db.query(Favorites.TABLE_NAME,
+                new String[]{Favorites._ID, Favorites.INTENT},
+                String.format("%s=? AND %s=? AND ( %s )", Favorites.ITEM_TYPE, Favorites.PROFILE_ID,
+                        getTelephonyIntentSQLLiteSelection(activityOverrides.keySet())),
+                new String[]{String.valueOf(ITEM_TYPE_APPLICATION), String.valueOf(currentUser)},
+                null, null, null);
+             SQLiteTransaction t = new SQLiteTransaction(db)) {
+            final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
+            final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT);
+            while (c.moveToNext()) {
+                LauncherActivityInfo override = activityOverrides.get(Intent.parseUri(
+                        c.getString(intentIndex), 0).getComponent().getPackageName());
+                if (override != null) {
+                    ContentValues values = new ContentValues();
+                    values.put(Favorites.PROFILE_ID,
+                            UserCache.INSTANCE.get(context).getSerialNumberForUser(
+                                    override.getUser()));
+                    values.put(Favorites.INTENT, AppInfo.makeLaunchIntent(override).toUri(0));
+                    db.update(Favorites.TABLE_NAME, values, String.format("%s=?", Favorites._ID),
+                            new String[]{String.valueOf(c.getInt(idIndex))});
+                }
+            }
+            t.commit();
+        } catch (Exception ex) {
+            Log.e(TAG, "Error while overriding shortcuts", ex);
+        }
+    }
+
+    private static String getTelephonyIntentSQLLiteSelection(Collection<String> packages) {
+        return packages.stream().map(
+                packageToChange -> String.format("intent LIKE '%%' || '%s' || '%%' ",
+                        packageToChange)).collect(
+                Collectors.joining(" OR "));
+    }
+
 }