14d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal/* 24d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * Copyright (C) 2015 The Android Open Source Project 34d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * 44d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License"); 54d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * you may not use this file except in compliance with the License. 64d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * You may obtain a copy of the License at 74d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * 84d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * http://www.apache.org/licenses/LICENSE-2.0 94d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * 104d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * Unless required by applicable law or agreed to in writing, software 114d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS, 124d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * See the License for the specific language governing permissions and 144d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal * limitations under the License. 154d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal */ 164d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal 1718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalpackage com.android.launcher3.util; 1818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 194d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyalimport android.annotation.TargetApi; 2018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport android.content.Context; 2118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport android.content.SharedPreferences; 2218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport android.content.pm.PackageInfo; 2318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport android.content.pm.PackageManager; 2418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport android.content.pm.PackageManager.NameNotFoundException; 254d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyalimport android.os.Build; 2618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport android.util.Log; 2718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 2818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.FolderInfo; 2918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.ItemInfo; 3018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.LauncherAppState; 3118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.LauncherFiles; 3218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.LauncherModel; 3318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.MainThreadExecutor; 3418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.R; 3518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.ShortcutInfo; 3618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.Utilities; 3718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.compat.LauncherActivityInfoCompat; 3818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.compat.LauncherAppsCompat; 3918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.compat.UserHandleCompat; 4018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.compat.UserManagerCompat; 4118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 4218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport java.util.ArrayList; 4318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport java.util.Collections; 44a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyalimport java.util.Comparator; 4518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport java.util.HashSet; 4618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport java.util.List; 47a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyalimport java.util.Set; 4818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 4918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal/** 5018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Handles addition of app shortcuts for managed profiles. 5118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Methods of class should only be called on {@link LauncherModel#sWorkerThread}. 5218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 534d113a5ff44ff1a7f19263bde21581fbf9a54212Sunny Goyal@TargetApi(Build.VERSION_CODES.LOLLIPOP) 5418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalpublic class ManagedProfileHeuristic { 5518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 5618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private static final String TAG = "ManagedProfileHeuristic"; 5718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 5818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 5918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Maintain a set of packages installed per user. 6018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 6118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private static final String INSTALLED_PACKAGES_PREFIX = "installed_packages_for_user_"; 6218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 6318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private static final String USER_FOLDER_ID_PREFIX = "user_folder_"; 6418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 6518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 6618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Duration (in milliseconds) for which app shortcuts will be added to work folder. 6718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 6818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private static final long AUTO_ADD_TO_FOLDER_DURATION = 8 * 60 * 60 * 1000; 6918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 7018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public static ManagedProfileHeuristic get(Context context, UserHandleCompat user) { 719fc953b94dbc6b99e6de08c9dcc80a0cb8e3e319Sunny Goyal if (Utilities.ATLEAST_LOLLIPOP && !UserHandleCompat.myUserHandle().equals(user)) { 7218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal return new ManagedProfileHeuristic(context, user); 7318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 7418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal return null; 7518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 7618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 7718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final Context mContext; 7818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final UserHandleCompat mUser; 7918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final LauncherModel mModel; 8018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 8118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final SharedPreferences mPrefs; 8218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final long mUserSerial; 8318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final long mUserCreationTime; 8418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private final String mPackageSetKey; 8518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 86a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal private ArrayList<ShortcutInfo> mHomescreenApps; 87a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal private ArrayList<ShortcutInfo> mWorkFolderApps; 8818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 8918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private ManagedProfileHeuristic(Context context, UserHandleCompat user) { 9018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mContext = context; 9118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mUser = user; 9218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mModel = LauncherAppState.getInstance().getModel(); 9318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 9418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal UserManagerCompat userManager = UserManagerCompat.getInstance(context); 9518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mUserSerial = userManager.getSerialNumberForUser(user); 9618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mUserCreationTime = userManager.getUserCreationTime(user); 9718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mPackageSetKey = INSTALLED_PACKAGES_PREFIX + mUserSerial; 9818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 9918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mPrefs = mContext.getSharedPreferences(LauncherFiles.MANAGED_USER_PREFERENCES_KEY, 10018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal Context.MODE_PRIVATE); 10118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 10218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 10318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 10418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Checks the list of user apps and adds icons for newly installed apps on the homescreen or 10518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * workfolder. 10618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 10718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public void processUserApps(List<LauncherActivityInfoCompat> apps) { 108a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal mHomescreenApps = new ArrayList<>(); 109a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal mWorkFolderApps = new ArrayList<>(); 110a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal 111a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal HashSet<String> packageSet = new HashSet<>(); 112a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal final boolean userAppsExisted = getUserApps(packageSet); 113a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal 11418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal boolean newPackageAdded = false; 11518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 11618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal for (LauncherActivityInfoCompat info : apps) { 11718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal String packageName = info.getComponentName().getPackageName(); 11818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (!packageSet.contains(packageName)) { 11918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal packageSet.add(packageName); 12018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal newPackageAdded = true; 12118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 12218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal try { 12318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal PackageInfo pkgInfo = mContext.getPackageManager() 12418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal .getPackageInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); 12518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal markForAddition(info, pkgInfo.firstInstallTime); 12618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } catch (NameNotFoundException e) { 12718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal Log.e(TAG, "Unknown package " + packageName, e); 12818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 12918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 13018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 13118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 13218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (newPackageAdded) { 13318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply(); 134a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal // Do not add shortcuts on the homescreen for the first time. This prevents the launcher 135a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal // getting filled with the managed user apps, when it start with a fresh DB (or after 136a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal // a very long time). 137a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal finalizeAdditions(userAppsExisted); 13818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 13918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 14018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 14118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private void markForAddition(LauncherActivityInfoCompat info, long installTime) { 142a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal ArrayList<ShortcutInfo> targetList = 14318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal (installTime <= mUserCreationTime + AUTO_ADD_TO_FOLDER_DURATION) ? 14418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mWorkFolderApps : mHomescreenApps; 14518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal targetList.add(ShortcutInfo.fromActivityInfo(info, mContext)); 14618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 14718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 14818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 14918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Adds and binds shortcuts marked to be added to the work folder. 15018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 15118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private void finalizeWorkFolder() { 15218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (mWorkFolderApps.isEmpty()) { 15318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal return; 15418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 155a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal Collections.sort(mWorkFolderApps, new Comparator<ShortcutInfo>() { 156a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal 157a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal @Override 158a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal public int compare(ShortcutInfo lhs, ShortcutInfo rhs) { 159a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal return Long.compare(lhs.firstInstallTime, rhs.firstInstallTime); 160a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal } 161a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal }); 16218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 16318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal // Try to get a work folder. 16418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal String folderIdKey = USER_FOLDER_ID_PREFIX + mUserSerial; 16518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (mPrefs.contains(folderIdKey)) { 16618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal long folderId = mPrefs.getLong(folderIdKey, 0); 16718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal final FolderInfo workFolder = mModel.findFolderById(folderId); 16818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 16918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (workFolder == null || !workFolder.hasOption(FolderInfo.FLAG_WORK_FOLDER)) { 17018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal // Could not get a work folder. Add all the icons to homescreen. 17118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mHomescreenApps.addAll(mWorkFolderApps); 17218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal return; 17318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 17418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal saveWorkFolderShortcuts(folderId, workFolder.contents.size()); 17518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 176a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal final ArrayList<ShortcutInfo> shortcuts = mWorkFolderApps; 17718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal // FolderInfo could already be bound. We need to add shortcuts on the UI thread. 17818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal new MainThreadExecutor().execute(new Runnable() { 17918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 18018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal @Override 18118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public void run() { 182a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal for (ShortcutInfo info : shortcuts) { 183a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal workFolder.add(info); 18418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 18518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 18618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal }); 18718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } else { 18818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal // Create a new folder. 18918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal final FolderInfo workFolder = new FolderInfo(); 19018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal workFolder.title = mContext.getText(R.string.work_folder_name); 19118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal workFolder.setOption(FolderInfo.FLAG_WORK_FOLDER, true, null); 19218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 19318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal // Add all shortcuts before adding it to the UI, as an empty folder might get deleted. 194a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal for (ShortcutInfo info : mWorkFolderApps) { 195a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal workFolder.add(info); 19618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 19718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 19818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal // Add the item to home screen and DB. This also generates an item id synchronously. 19918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal ArrayList<ItemInfo> itemList = new ArrayList<ItemInfo>(1); 20018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal itemList.add(workFolder); 20118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mModel.addAndBindAddedWorkspaceItems(mContext, itemList); 20218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mPrefs.edit().putLong(USER_FOLDER_ID_PREFIX + mUserSerial, workFolder.id).apply(); 20318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 20418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal saveWorkFolderShortcuts(workFolder.id, 0); 20518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 20618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 20718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 20818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 20918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Add work folder shortcuts to the DB. 21018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 21118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private void saveWorkFolderShortcuts(long workFolderId, int startingRank) { 21218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal for (ItemInfo info : mWorkFolderApps) { 21318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal info.rank = startingRank++; 21418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal LauncherModel.addItemToDatabase(mContext, info, workFolderId, 0, 0, 0); 21518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 21618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 21718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 21818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 21918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Adds and binds all shortcuts marked for addition. 22018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 221a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal private void finalizeAdditions(boolean addHomeScreenShortcuts) { 22218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal finalizeWorkFolder(); 22318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 224a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal if (addHomeScreenShortcuts && !mHomescreenApps.isEmpty()) { 22518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mModel.addAndBindAddedWorkspaceItems(mContext, mHomescreenApps); 22618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 22718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 22818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 22918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 23018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Updates the list of installed apps and adds any new icons on homescreen or work folder. 23118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 23218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public void processPackageAdd(String[] packages) { 233a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal mHomescreenApps = new ArrayList<>(); 234a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal mWorkFolderApps = new ArrayList<>(); 235a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal 236a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal HashSet<String> packageSet = new HashSet<>(); 237a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal final boolean userAppsExisted = getUserApps(packageSet); 238a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal 23918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal boolean newPackageAdded = false; 24018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal long installTime = System.currentTimeMillis(); 24118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext); 24218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 24318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal for (String packageName : packages) { 24418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (!packageSet.contains(packageName)) { 24518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal packageSet.add(packageName); 24618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal newPackageAdded = true; 24718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 24818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal List<LauncherActivityInfoCompat> activities = 24918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal launcherApps.getActivityList(packageName, mUser); 25018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (!activities.isEmpty()) { 25118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal markForAddition(activities.get(0), installTime); 25218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 25318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 25418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 25518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 25618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (newPackageAdded) { 25718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply(); 258a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal finalizeAdditions(userAppsExisted); 25918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 26018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 26118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 26218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 26318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Updates the list of installed packages for the user. 26418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 26518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public void processPackageRemoved(String[] packages) { 266a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal HashSet<String> packageSet = new HashSet<String>(); 267a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal getUserApps(packageSet); 26818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal boolean packageRemoved = false; 26918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 27018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal for (String packageName : packages) { 27118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (packageSet.remove(packageName)) { 27218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal packageRemoved = true; 27318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 27418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 27518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 27618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (packageRemoved) { 27718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply(); 27818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 27918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 28018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 281a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal /** 282a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal * Reads the list of user apps which have already been processed. 283a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal * @return false if the list didn't exist, true otherwise 284a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal */ 285a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal private boolean getUserApps(HashSet<String> outExistingApps) { 286a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal Set<String> userApps = mPrefs.getStringSet(mPackageSetKey, null); 287a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal if (userApps == null) { 288a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal return false; 289a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal } else { 290a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal outExistingApps.addAll(userApps); 291a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal return true; 292a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal } 29318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 29418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 29518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal /** 29618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal * Verifies that entries corresponding to {@param users} exist and removes all invalid entries. 29718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal */ 29818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public static void processAllUsers(List<UserHandleCompat> users, Context context) { 2999fc953b94dbc6b99e6de08c9dcc80a0cb8e3e319Sunny Goyal if (!Utilities.ATLEAST_LOLLIPOP) { 30018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal return; 30118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 30218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal UserManagerCompat userManager = UserManagerCompat.getInstance(context); 30318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal HashSet<String> validKeys = new HashSet<String>(); 30418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal for (UserHandleCompat user : users) { 30518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal addAllUserKeys(userManager.getSerialNumberForUser(user), validKeys); 30618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 30718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 30818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal SharedPreferences prefs = context.getSharedPreferences( 30918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal LauncherFiles.MANAGED_USER_PREFERENCES_KEY, 31018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal Context.MODE_PRIVATE); 31118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal SharedPreferences.Editor editor = prefs.edit(); 31218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal for (String key : prefs.getAll().keySet()) { 31318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal if (!validKeys.contains(key)) { 31418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal editor.remove(key); 31518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 31618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 31718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal editor.apply(); 31818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 31918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal 32018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal private static void addAllUserKeys(long userSerial, HashSet<String> keysOut) { 32118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal keysOut.add(INSTALLED_PACKAGES_PREFIX + userSerial); 32218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal keysOut.add(USER_FOLDER_ID_PREFIX + userSerial); 32318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal } 324e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal 325e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal /** 326e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal * For each user, if a work folder has not been created, mark it such that the folder will 327e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal * never get created. 328e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal */ 329e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal public static void markExistingUsersForNoFolderCreation(Context context) { 330e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal UserManagerCompat userManager = UserManagerCompat.getInstance(context); 331e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal UserHandleCompat myUser = UserHandleCompat.myUserHandle(); 332e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal 333e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal SharedPreferences prefs = null; 334e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal for (UserHandleCompat user : userManager.getUserProfiles()) { 335e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal if (myUser.equals(user)) { 336e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal continue; 337e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal } 338e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal 339e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal if (prefs == null) { 340e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal prefs = context.getSharedPreferences( 341e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal LauncherFiles.MANAGED_USER_PREFERENCES_KEY, 342e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal Context.MODE_PRIVATE); 343e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal } 344e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal String folderIdKey = USER_FOLDER_ID_PREFIX + userManager.getSerialNumberForUser(user); 345e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal if (!prefs.contains(folderIdKey)) { 346e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal prefs.edit().putLong(folderIdKey, ItemInfo.NO_ID).apply(); 347e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal } 348e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal } 349e2fba6cba10d9b7996ebb86dfd67bed96cff0dedSunny Goyal } 35018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal} 351