/** * @hide Implement to provide correct calling token. */ public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) { if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, -1, options, user); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, -1, ar.getResultCode(), ar.getResultData()); } cancelInputsAndStartExitTransition(options); }
@Override public void enableAndResetCache() { synchronized (this) { mUsers = new LongArrayMap<>(); mUserToSerialMap = new HashMap<>(); List<UserHandle> users = mUserManager.getUserProfiles(); if (users != null) { for (UserHandle user : users) { long serial = mUserManager.getSerialNumberForUser(user); UserHandleCompat userCompat = UserHandleCompat.fromUser(user); mUsers.put(serial, userCompat); mUserToSerialMap.put(userCompat, serial); } } } }
/** * Returns true if the shortcuts already exists on the workspace. This must be called after * the workspace has been loaded. We identify a shortcut by its intent. */ private boolean shortcutExists(BgDataModel dataModel, Intent intent, UserHandle user) { final String intentWithPkg, intentWithoutPkg; if (intent == null) { // Skip items with null intents return true; } if (intent.getComponent() != null) { // If component is not null, an intent with null package will produce // the same result and should also be a match. String packageName = intent.getComponent().getPackageName(); if (intent.getPackage() != null) { intentWithPkg = intent.toUri(0); intentWithoutPkg = new Intent(intent).setPackage(null).toUri(0); } else { intentWithPkg = new Intent(intent).setPackage(packageName).toUri(0); intentWithoutPkg = intent.toUri(0); } } else { intentWithPkg = intent.toUri(0); intentWithoutPkg = intent.toUri(0); } synchronized (dataModel) { for (ItemInfo item : dataModel.itemsIdMap) { if (item instanceof ShortcutInfo) { ShortcutInfo info = (ShortcutInfo) item; if (item.getIntent() != null && info.user.equals(user)) { Intent copyIntent = new Intent(item.getIntent()); copyIntent.setSourceBounds(intent.getSourceBounds()); String s = copyIntent.toUri(0); if (intentWithPkg.equals(s) || intentWithoutPkg.equals(s)) { return true; } } } } } return false; }
/** * Clear all the deep shortcuts for the given package, and re-add the new shortcuts. */ public synchronized void updateDeepShortcutMap( String packageName, UserHandle user, List<ShortcutInfoCompat> shortcuts) { if (packageName != null) { Iterator<ComponentKey> keysIter = deepShortcutMap.keySet().iterator(); while (keysIter.hasNext()) { ComponentKey next = keysIter.next(); if (next.componentName.getPackageName().equals(packageName) && next.user.equals(user)) { keysIter.remove(); } } } // Now add the new shortcuts to the map. for (ShortcutInfoCompat shortcut : shortcuts) { boolean shouldShowInContainer = shortcut.isEnabled() && (shortcut.isDeclaredInManifest() || shortcut.isDynamic()); if (shouldShowInContainer) { ComponentKey targetComponent = new ComponentKey(shortcut.getActivity(), shortcut.getUserHandle()); deepShortcutMap.addToList(targetComponent, shortcut.getId()); } } }
public void updateIconsAndLabels(HashSet<String> packages, UserHandle user, ArrayList<AppInfo> outUpdates) { for (AppInfo info : data) { if (info.user.equals(user) && packages.contains(info.componentName.getPackageName())) { mIconCache.updateTitleAndIcon(info); outUpdates.add(info); } } }
@Override public long getSerialNumberForUser(UserHandle user) { synchronized (this) { if (mUserToSerialMap != null) { Long serial = mUserToSerialMap.get(user); return serial == null ? 0 : serial; } } return mUserManager.getSerialNumberForUser(user); }
@Override public UserHandle getUserForSerialNumber(long serialNumber) { synchronized (this) { if (mUsers != null) { return mUsers.get(serialNumber); } } return mUserManager.getUserForSerialNumber(serialNumber); }
private void scheduleManagedHeuristicRunnable(final ManagedProfileHeuristic heuristic, final UserHandle user, final List<LauncherActivityInfo> apps) { if (heuristic != null) { // Assume the app lists now is updated. mIsManagedHeuristicAppsUpdated = false; final Runnable managedHeuristicRunnable = new Runnable() { @Override public void run() { if (mIsManagedHeuristicAppsUpdated) { // If app list is updated, we need to reschedule it otherwise old app // list will override everything in processUserApps(). sWorker.post(new Runnable() { public void run() { final List<LauncherActivityInfo> updatedApps = mLauncherApps.getActivityList(null, user); scheduleManagedHeuristicRunnable(heuristic, user, updatedApps); } }); } else { heuristic.processUserApps(apps); } } }; runOnMainThread(new Runnable() { @Override public void run() { // Check isLoadingWorkspace on the UI thread, as it is updated on the UI // thread. if (mIsLoadingAndBindingWorkspace) { synchronized (mBindCompleteRunnables) { mBindCompleteRunnables.add(managedHeuristicRunnable); } } else { runOnWorkerThread(managedHeuristicRunnable); } } }); } }
@Override public List<UserHandle> getUserProfiles() { synchronized (this) { if (mUsers != null) { return new ArrayList<>(mUserToSerialMap.keySet()); } } List<UserHandle> users = mUserManager.getUserProfiles(); return users == null ? Collections.<UserHandle>emptyList() : users; }
private void loadDeepShortcuts() { sBgDataModel.deepShortcutMap.clear(); DeepShortcutManager shortcutManager = DeepShortcutManager.getInstance(mContext); mHasShortcutHostPermission = shortcutManager.hasHostPermission(); if (mHasShortcutHostPermission) { for (UserHandle user : mUserManager.getUserProfiles()) { if (mUserManager.isUserUnlocked(user)) { List<ShortcutInfoCompat> shortcuts = shortcutManager.queryForAllShortcuts(user); sBgDataModel.updateDeepShortcutMap(null, user, shortcuts); } } } }
@RequiresApi(JELLY_BEAN_MR1) @SuppressLint("MissingPermission") @Override public void sendOrderedBroadcastAsUser(final Intent intent, final UserHandle user, final String receiverPermission, final BroadcastReceiver resultReceiver, final Handler scheduler, final int initialCode, final String initialData, final Bundle initialExtras) { mCondom.proceedBroadcast(this, intent, new CondomCore.WrappedProcedure() { @Override public void run() { mApplication.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras); }}, resultReceiver); }
/** * Checks the list of user apps, and generates package event accordingly. * {@see #onLauncherAppsAdded}, {@see #onLauncherPackageRemoved} */ void processUserApps(List<LauncherActivityInfo> apps, UserHandle user) { String prefKey = INSTALLED_PACKAGES_PREFIX + mUserManager.getSerialNumberForUser(user); HashSet<String> oldPackageSet = new HashSet<>(); final boolean userAppsExisted = getUserApps(oldPackageSet, prefKey); HashSet<String> packagesRemoved = new HashSet<>(oldPackageSet); HashSet<String> newPackageSet = new HashSet<>(); ArrayList<LauncherActivityInstallInfo> packagesAdded = new ArrayList<>(); for (LauncherActivityInfo info : apps) { String packageName = info.getComponentName().getPackageName(); newPackageSet.add(packageName); packagesRemoved.remove(packageName); if (!oldPackageSet.contains(packageName)) { oldPackageSet.add(packageName); packagesAdded.add(new LauncherActivityInstallInfo( info, info.getFirstInstallTime())); } } if (!packagesAdded.isEmpty() || !packagesRemoved.isEmpty()) { mPrefs.edit().putStringSet(prefKey, newPackageSet).apply(); if (!packagesAdded.isEmpty()) { Collections.sort(packagesAdded); onLauncherAppsAdded(packagesAdded, user, userAppsExisted); } if (!packagesRemoved.isEmpty()) { for (String pkg : packagesRemoved) { onLauncherPackageRemoved(pkg, user); } } } }
@Override public List<AppWidgetProviderInfo> getAllProviders() { ArrayList<AppWidgetProviderInfo> providers = new ArrayList<AppWidgetProviderInfo>(); for (UserHandle user : mUserManager.getUserProfiles()) { providers.addAll(mAppWidgetManager.getInstalledProvidersForProfile(user)); } return providers; }
public static ItemInfoMatcher ofComponents( final HashSet<ComponentName> components, final UserHandle user) { return new ItemInfoMatcher() { @Override public boolean matches(ItemInfo info, ComponentName cn) { return components.contains(cn) && info.user.equals(user); } }; }
@Override public HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap() { HashMap<ComponentKey, AppWidgetProviderInfo> result = new HashMap<>(); for (UserHandle user : mUserManager.getUserProfiles()) { for (AppWidgetProviderInfo info : mAppWidgetManager.getInstalledProvidersForProfile(user)) { result.put(new ComponentKey(info.provider, user), info); } } return result; }
/** * @hide Implement to provide correct calling token. */ public void startActivityForResultAsUser(Intent intent, int requestCode, @Nullable Bundle options, UserHandle user) { if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options, user); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); }
void bindUpdatedShortcuts( final ArrayList<ShortcutInfo> updatedShortcuts, final ArrayList<ShortcutInfo> removedShortcuts, final UserHandle user) { if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) { scheduleCallbackTask(new CallbackTask() { @Override public void execute(Callbacks callbacks) { callbacks.bindShortcutsChanged(updatedShortcuts, removedShortcuts, user); } }); } }
private void removePackage(String packageName, UserHandle user, long userSerial) { synchronized(mPackageVersions) { mPackageVersions.remove(packageName); } mDb.delete( CacheDb.COLUMN_PACKAGE + " = ? AND " + CacheDb.COLUMN_USER + " = ?", new String[]{packageName, Long.toString(userSerial)}); }
/** * Called when the icons for packages have been updated in the icon cache. */ public void onPackageIconsUpdated(HashSet<String> updatedPackages, UserHandle user) { // If any package icon has changed (app was updated while launcher was dead), // update the corresponding shortcuts. enqueueModelUpdateTask(new CacheDataUpdatedTask( CacheDataUpdatedTask.OP_CACHE_UPDATE, user, updatedPackages)); }
/** * Query the system server for all the shortcuts matching the given parameters. * If packageName == null, we query for all shortcuts with the passed flags, regardless of app. * * TODO: Use the cache to optimize this so we don't make an RPC every time. */ @TargetApi(25) private List<ShortcutInfoCompat> query(int flags, String packageName, ComponentName activity, List<String> shortcutIds, UserHandle user) { if (AndroidVersion.isAtLeastNougatMR1) { ShortcutQuery q = new ShortcutQuery(); q.setQueryFlags(flags); if (packageName != null) { q.setPackage(packageName); q.setActivity(activity); q.setShortcutIds(shortcutIds); } List<ShortcutInfo> shortcutInfos = null; try { shortcutInfos = mLauncherApps.getShortcuts(q, user); mWasLastCallSuccess = true; } catch (SecurityException|IllegalStateException e) { e.printStackTrace(); mWasLastCallSuccess = false; } if (shortcutInfos == null) { return Collections.EMPTY_LIST; } List<ShortcutInfoCompat> shortcutInfoCompats = new ArrayList<>(shortcutInfos.size()); for (ShortcutInfo shortcutInfo : shortcutInfos) { shortcutInfoCompats.add(new ShortcutInfoCompat(shortcutInfo)); } return shortcutInfoCompats; } else { return Collections.EMPTY_LIST; } }
public void onPackageChanged(String packageName, UserHandle user) { mCallback.onPackageChanged(packageName, UserHandleCompat.fromUser(user)); }
public static UserHandle getUserHandle(int userId) throws Exception { Constructor<?> uhConst = XposedHelpers.findConstructorExact(UserHandle.class, int.class); return (UserHandle) uhConst.newInstance(userId); }
public void onPackageRemoved(String packageName, UserHandle user) { mCallback.onPackageRemoved(packageName, UserHandleCompat.fromUser(user)); }
/** * Create a new PendingIntent object which you can hand to others * for them to use to send result data back to your * {@link #onActivityResult} callback. The created object will be either * one-shot (becoming invalid after a result is sent back) or multiple * (allowing any number of results to be sent through it). * * @param requestCode Private request code for the sender that will be * associated with the result data when it is returned. The sender can not * modify this value, allowing you to identify incoming results. * @param data Default data to supply in the result, which may be modified * by the sender. * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT PendingIntent.FLAG_ONE_SHOT}, * {@link PendingIntent#FLAG_NO_CREATE PendingIntent.FLAG_NO_CREATE}, * {@link PendingIntent#FLAG_CANCEL_CURRENT PendingIntent.FLAG_CANCEL_CURRENT}, * {@link PendingIntent#FLAG_UPDATE_CURRENT PendingIntent.FLAG_UPDATE_CURRENT}, * or any of the flags as supported by * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts * of the intent that can be supplied when the actual send happens. * * @return Returns an existing or new PendingIntent matching the given * parameters. May return null only if * {@link PendingIntent#FLAG_NO_CREATE PendingIntent.FLAG_NO_CREATE} has been * supplied. * * @see PendingIntent */ public PendingIntent createPendingResult(int requestCode, @NonNull Intent data, @PendingIntent.Flags int flags) { String packageName = getPackageName(); try { data.prepareToLeaveProcess(this); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, mParent == null ? mToken : mParent.mToken, mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null, UserHandle.myUserId()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { // Empty } return null; }
/** * @hide Implement to provide correct calling token. */ public void startActivityForResultAsUser(Intent intent, int requestCode, UserHandle user) { startActivityForResultAsUser(intent, requestCode, null, user); }
@Override @TargetApi(Build.VERSION_CODES.LOLLIPOP) public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user, Rect badgeLocation, int badgeDensity) { return this.mHostPackageManager.getUserBadgedDrawableForDensity(drawable, user, badgeLocation, badgeDensity); }
/** * Returns whether the target app is suspended for a given user as per * {@link android.app.admin.DevicePolicyManager#isPackageSuspended}. */ public boolean isAppSuspended(String packageName, UserHandle user) { ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, 0, user); return info != null && isAppSuspended(info); }
/** @hide */ @Override public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle userHandle) { return mBase.getApplicationHiddenSettingAsUser(packageName, userHandle); }
@Override public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) { return mLauncherApps.getActivityList(packageName, user); }
@Override public void onShortcutsChanged(String packageName, List<ShortcutInfoCompat> shortcuts, UserHandle user) { // Do nothing }
/** * Gets an entry for the package, which can be used as a fallback entry for various components. * This method is not thread safe, it must be called from a synchronized method. */ private CacheEntry getEntryForPackageLocked(String packageName, UserHandle user, boolean useLowResIcon) { ComponentKey cacheKey = getPackageKey(packageName, user); CacheEntry entry = mCache.get(cacheKey); if (entry == null || (entry.isLowResIcon && !useLowResIcon)) { entry = new CacheEntry(); boolean entryUpdated = true; // Check the DB first. if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) { try { int uninstalled = android.os.Build.VERSION.SDK_INT >= 24 ? PackageManager.MATCH_UNINSTALLED_PACKAGES : PackageManager.GET_UNINSTALLED_PACKAGES; int flags = Process.myUserHandle().equals(user) ? 0 : uninstalled; PackageInfo info = mPackageManager.getPackageInfo(packageName, flags); ApplicationInfo appInfo = info.applicationInfo; if (appInfo == null) { throw new NameNotFoundException("ApplicationInfo is null"); } // Load the full res icon for the application, but if useLowResIcon is set, then // only keep the low resolution icon instead of the larger full-sized icon Bitmap icon = LauncherIcons.createBadgedIconBitmap( appInfo.loadIcon(mPackageManager), user, mContext, appInfo.targetSdkVersion); Bitmap lowResIcon = generateLowResIcon(icon, mPackageBgColor); entry.title = appInfo.loadLabel(mPackageManager); entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user); entry.icon = useLowResIcon ? lowResIcon : icon; entry.isLowResIcon = useLowResIcon; // Add the icon in the DB here, since these do not get written during // package updates. ContentValues values = newContentValues(icon, lowResIcon, entry.title.toString(), packageName); addIconToDB(values, cacheKey.componentName, info, mUserManager.getSerialNumberForUser(user)); } catch (NameNotFoundException e) { e.printStackTrace(); entryUpdated = false; } } // Only add a filled-out entry to the cache if (entryUpdated) { mCache.put(cacheKey, entry); } } return entry; }
@Override public boolean isPackageEnabledForProfile(String packageName, UserHandle user) { return mLauncherApps.isPackageEnabled(packageName, user); }
public void onPackageRemoved(String packageName, UserHandle user) { mCallback.onPackageRemoved(packageName, user); }
@RequiresApi(JELLY_BEAN_MR1) @SuppressLint("MissingPermission") @Override public void sendBroadcastAsUser(final Intent intent, final UserHandle user) { mCondom.proceedBroadcast(this, intent, new CondomCore.WrappedProcedure() { @Override public void run() { CondomContext.super.sendBroadcastAsUser(intent, user); }}, null); }
public void onPackageChanged(String packageName, UserHandle user) { mCallback.onPackageChanged(packageName, user); }
/** @hide */ @Override public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) { mBase.startActivitiesAsUser(intents, options, userHandle); }