use of android.content.pm.LauncherActivityInfo in project island by oasisfeng.
the class IslandManager method launchApp.
@OwnerUser
public static boolean launchApp(final Context context, final String pkg, final UserHandle profile) {
final LauncherApps launcher_apps = requireNonNull((LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE));
try {
final List<LauncherActivityInfo> activities = launcher_apps.getActivityList(pkg, profile);
if (activities == null || activities.isEmpty())
return false;
launcher_apps.startMainActivity(activities.get(0).getComponentName(), profile, null, null);
} catch (final SecurityException e) {
// SecurityException: Cannot retrieve activities for unrelated profile 10
Log.e(TAG, "Error launching app: " + pkg + " @ user " + profile, e);
return false;
}
return true;
}
use of android.content.pm.LauncherActivityInfo in project island by oasisfeng.
the class MainActivity method onCreate.
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!Users.isOwner()) {
if (Users.isProfileManagedByIsland()) {
// Should generally not run in profile, unless the managed profile provision is interrupted or manually provision is not complete.
onCreateInProfile();
finish();
} else
// Running in non-primary user or profile not managed by Island. TODO: Proper handling?
startSetupWizard();
return;
}
final String caller = CallerAwareActivity.getCallingPackage(this);
// Possibly started by IslandProvisioning, refresh user state as profile or its owner may be changed.
if (Modules.MODULE_ENGINE.equals(caller))
Users.refreshUsers(this);
if (mIsDeviceOwner = new DevicePolicies(this).isProfileOrDeviceOwnerOnCallingUser()) {
// As device owner, always show main UI.
startMainUi(savedInstanceState);
return;
}
final UserHandle profile = Users.profile;
if (profile == null) {
// Nothing setup yet
Log.i(TAG, "Profile not setup yet");
startSetupWizard();
return;
}
if (!Users.isProfileManagedByIsland(profile)) {
// Profile without owner or not managed by us, probably caused by provision interruption before device-admin is activated.
final Optional<ComponentName> owner = DevicePolicies.getProfileOwnerAsUser(this, profile);
if (owner == null) {
Log.w(TAG, "Cannot detect profile owner");
startMainUi(savedInstanceState);
} else if (!owner.isPresent()) {
Log.w(TAG, "Profile without owner");
if (// Try starting Island in profile to finish the provisioning.
IslandManager.launchApp(this, getPackageName(), profile))
// Try starting Island in profile to finish the provisioning.
finish();
else
// Cannot resume the provisioning, probably this profile is not created by us, go ahead with normal setup.
startSetupWizard();
} else {
// Profile is not owned by us, show setup wizard.
startSetupWizard();
}
} else {
final LauncherApps launcher_apps = (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
final List<LauncherActivityInfo> our_activities_in_launcher;
if (launcher_apps != null && !(our_activities_in_launcher = launcher_apps.getActivityList(getPackageName(), profile)).isEmpty() && our_activities_in_launcher.get(0).getComponentName().getClassName().equals(MainActivity.class.getName())) {
// Main activity is left enabled, probably due to pending post-provisioning in manual setup. Some domestic ROMs may block implicit broadcast, causing ACTION_USER_INITIALIZE being dropped.
Analytics.$().event("profile_provision_leftover").send();
Log.w(TAG, "Setup in Island is not complete, continue it now.");
try {
launcher_apps.startMainActivity(our_activities_in_launcher.get(0).getComponentName(), profile, null, null);
} catch (final RuntimeException e) {
Analytics.$().logAndReport(TAG, "Error starting self in profile " + Users.toId(profile), e);
startSetupWizard();
}
finish();
return;
}
startMainUi(savedInstanceState);
}
}
use of android.content.pm.LauncherActivityInfo in project android_packages_apps_Launcher3 by crdroidandroid.
the class PredictionUpdateTask method execute.
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
Context context = app.getContext();
// TODO: remove this
Utilities.getDevicePrefs(context).edit().putBoolean(LAST_PREDICTION_ENABLED_STATE, !mTargets.isEmpty()).apply();
FixedContainerItems fci = mPredictorState.items;
Set<UserHandle> usersForChangedShortcuts = new HashSet<>(fci.items.stream().filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT).map(info -> info.user).collect(Collectors.toSet()));
fci.items.clear();
for (AppTarget target : mTargets) {
WorkspaceItemInfo itemInfo;
ShortcutInfo si = target.getShortcutInfo();
if (si != null) {
usersForChangedShortcuts.add(si.getUserHandle());
itemInfo = new WorkspaceItemInfo(si, context);
app.getIconCache().getShortcutIcon(itemInfo, si);
} else {
String className = target.getClassName();
if (COMPONENT_CLASS_MARKER.equals(className)) {
// TODO: Implement this
continue;
}
ComponentName cn = new ComponentName(target.getPackageName(), className);
UserHandle user = target.getUser();
itemInfo = apps.data.stream().filter(info -> user.equals(info.user) && cn.equals(info.componentName)).map(ai -> {
app.getIconCache().getTitleAndIcon(ai, false);
return ai.makeWorkspaceItem();
}).findAny().orElseGet(() -> {
LauncherActivityInfo lai = context.getSystemService(LauncherApps.class).resolveActivity(AppInfo.makeLaunchIntent(cn), user);
if (lai == null) {
return null;
}
AppInfo ai = new AppInfo(context, lai, user);
app.getIconCache().getTitleAndIcon(ai, lai, false);
return ai.makeWorkspaceItem();
});
if (itemInfo == null) {
continue;
}
}
itemInfo.container = fci.containerId;
fci.items.add(itemInfo);
}
bindExtraContainerItems(fci);
usersForChangedShortcuts.forEach(u -> dataModel.updateShortcutPinnedState(app.getContext(), u));
// Save to disk
mPredictorState.storage.write(context, fci.items);
}
use of android.content.pm.LauncherActivityInfo in project android_packages_apps_Launcher3 by crdroidandroid.
the class LoaderTask method run.
public void run() {
synchronized (this) {
// Skip fast if we are already stopped.
if (mStopped) {
return;
}
}
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
TimingLogger logger = new TimingLogger(TAG, "run");
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
loadWorkspace(allShortcuts);
logASplit(logger, "loadWorkspace");
// (e.g. both grid preview and minimal device mode uses a different db)
if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
verifyNotStopped();
sanitizeData();
logASplit(logger, "sanitizeData");
}
verifyNotStopped();
mResults.bindWorkspace();
logASplit(logger, "bindWorkspace");
mModelDelegate.workspaceLoadComplete();
// Notify the installer packages of packages with active installs on the first screen.
sendFirstScreenActiveInstallsBroadcast();
logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");
// Take a break
waitForIdle();
logASplit(logger, "step 1 complete");
verifyNotStopped();
// second step
List<LauncherActivityInfo> allActivityList = loadAllApps();
logASplit(logger, "loadAllApps");
verifyNotStopped();
mResults.bindAllApps();
logASplit(logger, "bindAllApps");
verifyNotStopped();
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
setIgnorePackages(updateHandler);
updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel()::onPackageIconsUpdated);
logASplit(logger, "update icon cache");
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
verifyNotStopped();
logASplit(logger, "save shortcuts in icon cache");
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), mApp.getModel()::onPackageIconsUpdated);
}
// Take a break
waitForIdle();
logASplit(logger, "step 2 complete");
verifyNotStopped();
// third step
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
logASplit(logger, "loadDeepShortcuts");
verifyNotStopped();
mResults.bindDeepShortcuts();
logASplit(logger, "bindDeepShortcuts");
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
verifyNotStopped();
logASplit(logger, "save deep shortcuts in icon cache");
updateHandler.updateIcons(allDeepShortcuts, new ShortcutCachingLogic(), (pkgs, user) -> {
});
}
// Take a break
waitForIdle();
logASplit(logger, "step 3 complete");
verifyNotStopped();
// fourth step
List<ComponentWithLabelAndIcon> allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null);
logASplit(logger, "load widgets");
verifyNotStopped();
mResults.bindWidgets();
logASplit(logger, "bindWidgets");
verifyNotStopped();
updateHandler.updateIcons(allWidgetsList, new ComponentWithIconCachingLogic(mApp.getContext(), true), mApp.getModel()::onWidgetLabelsUpdated);
logASplit(logger, "save widgets in icon cache");
// fifth step
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
loadFolderNames();
}
verifyNotStopped();
updateHandler.finish();
logASplit(logger, "finish icon update");
mModelDelegate.modelLoadComplete();
transaction.commit();
} catch (CancellationException e) {
// Loader stopped, ignore
logASplit(logger, "Cancelled");
} finally {
logger.dumpToLog();
}
TraceHelper.INSTANCE.endSection(traceToken);
}
use of android.content.pm.LauncherActivityInfo in project android_packages_apps_Launcher3 by crdroidandroid.
the class PackageUpdatedTask method execute.
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
final Context context = app.getContext();
final IconCache iconCache = app.getIconCache();
final String[] packages = mPackages;
final int N = packages.length;
final FlagOp flagOp;
final HashSet<String> packageSet = new HashSet<>(Arrays.asList(packages));
final ItemInfoMatcher matcher = mOp == OP_USER_AVAILABILITY_CHANGE ? // We want to update all packages for this user
ItemInfoMatcher.ofUser(mUser) : ItemInfoMatcher.ofPackages(packageSet, mUser);
final HashSet<ComponentName> removedComponents = new HashSet<>();
final HashMap<String, List<LauncherActivityInfo>> activitiesLists = new HashMap<>();
boolean needsRestart = false;
switch(mOp) {
case OP_ADD:
{
for (int i = 0; i < N; i++) {
if (DEBUG)
Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
if (isTargetPackage(packages[i])) {
needsRestart = true;
}
iconCache.updateIconsForPkg(packages[i], mUser);
if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
appsList.removePackage(packages[i], mUser);
}
activitiesLists.put(packages[i], appsList.addPackage(context, packages[i], mUser));
}
flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
}
case OP_UPDATE:
try (SafeCloseable t = appsList.trackRemoves(a -> removedComponents.add(a.componentName))) {
for (int i = 0; i < N; i++) {
if (DEBUG)
Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
iconCache.updateIconsForPkg(packages[i], mUser);
activitiesLists.put(packages[i], appsList.updatePackage(context, packages[i], mUser));
app.getWidgetCache().removePackage(packages[i], mUser);
// The update may have changed which shortcuts/widgets are available.
// Refresh the widgets for the package if we have an activity running.
Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
if (launcher != null) {
launcher.refreshAndBindWidgetsForPackageUser(new PackageUserKey(packages[i], mUser));
}
}
}
// Since package was just updated, the target must be available now.
flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
case OP_REMOVE:
{
for (int i = 0; i < N; i++) {
FileLog.d(TAG, "Removing app icon" + packages[i]);
iconCache.removeIconsForPkg(packages[i], mUser);
if (isTargetPackage(packages[i])) {
needsRestart = true;
}
}
// Fall through
}
case OP_UNAVAILABLE:
for (int i = 0; i < N; i++) {
if (DEBUG)
Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
appsList.removePackage(packages[i], mUser);
app.getWidgetCache().removePackage(packages[i], mUser);
}
flagOp = FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
case OP_SUSPEND:
case OP_UNSUSPEND:
flagOp = mOp == OP_SUSPEND ? FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED) : FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED);
if (DEBUG)
Log.d(TAG, "mAllAppsList.(un)suspend " + N);
appsList.updateDisabledFlags(matcher, flagOp);
for (int i = 0; i < N; i++) {
if (isTargetPackage(packages[i])) {
needsRestart = true;
}
}
break;
case OP_USER_AVAILABILITY_CHANGE:
{
UserManagerState ums = new UserManagerState();
ums.init(UserCache.INSTANCE.get(context), context.getSystemService(UserManager.class));
flagOp = ums.isUserQuiet(mUser) ? FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER) : FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER);
appsList.updateDisabledFlags(matcher, flagOp);
// We are not synchronizing here, as int operations are atomic
appsList.setFlags(FLAG_QUIET_MODE_ENABLED, ums.isAnyProfileQuietModeEnabled());
break;
}
default:
flagOp = FlagOp.NO_OP;
break;
}
bindApplicationsIfNeeded();
final IntSet removedShortcuts = new IntSet();
// Shortcuts to keep even if the corresponding app was removed
final IntSet forceKeepShortcuts = new IntSet();
// Update shortcut infos
if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
final ArrayList<WorkspaceItemInfo> updatedWorkspaceItems = new ArrayList<>();
final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<>();
// For system apps, package manager send OP_UPDATE when an app is enabled.
final boolean isNewApkAvailable = mOp == OP_ADD || mOp == OP_UPDATE;
synchronized (dataModel) {
dataModel.forAllWorkspaceItemInfos(mUser, si -> {
boolean infoUpdated = false;
boolean shortcutUpdated = false;
// Update shortcuts which use iconResource.
if ((si.iconResource != null) && packageSet.contains(si.iconResource.packageName)) {
LauncherIcons li = LauncherIcons.obtain(context);
BitmapInfo iconInfo = li.createIconBitmap(si.iconResource);
li.recycle();
if (iconInfo != null) {
si.bitmap = iconInfo;
infoUpdated = true;
}
}
ComponentName cn = si.getTargetComponent();
if (cn != null && matcher.matches(si, cn)) {
String packageName = cn.getPackageName();
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)) {
forceKeepShortcuts.add(si.id);
if (mOp == OP_REMOVE) {
return;
}
}
if (si.isPromise() && isNewApkAvailable) {
boolean isTargetValid = !cn.getClassName().equals(IconCache.EMPTY_CLASS_NAME);
if (si.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
List<ShortcutInfo> shortcut = new ShortcutRequest(context, mUser).forPackage(cn.getPackageName(), si.getDeepShortcutId()).query(ShortcutRequest.PINNED);
if (shortcut.isEmpty()) {
isTargetValid = false;
} else {
si.updateFromDeepShortcutInfo(shortcut.get(0), context);
infoUpdated = true;
}
} else if (isTargetValid) {
isTargetValid = context.getSystemService(LauncherApps.class).isActivityEnabled(cn, mUser);
}
if (!isTargetValid && si.hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON)) {
if (updateWorkspaceItemIntent(context, si, packageName)) {
infoUpdated = true;
} else if (si.hasPromiseIconUi()) {
removedShortcuts.add(si.id);
return;
}
} else if (!isTargetValid) {
removedShortcuts.add(si.id);
FileLog.e(TAG, "Restored shortcut no longer valid " + si.getIntent());
return;
} else {
si.status = WorkspaceItemInfo.DEFAULT;
infoUpdated = true;
}
} else if (isNewApkAvailable && removedComponents.contains(cn)) {
if (updateWorkspaceItemIntent(context, si, packageName)) {
infoUpdated = true;
}
}
if (isNewApkAvailable) {
List<LauncherActivityInfo> activities = activitiesLists.get(packageName);
si.setProgressLevel(activities == null || activities.isEmpty() ? 100 : PackageManagerHelper.getLoadingProgress(activities.get(0)), PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
iconCache.getTitleAndIcon(si, si.usingLowResIcon());
infoUpdated = true;
}
}
int oldRuntimeFlags = si.runtimeStatusFlags;
si.runtimeStatusFlags = flagOp.apply(si.runtimeStatusFlags);
if (si.runtimeStatusFlags != oldRuntimeFlags) {
shortcutUpdated = true;
}
}
if (infoUpdated || shortcutUpdated) {
updatedWorkspaceItems.add(si);
}
if (infoUpdated && si.id != ItemInfo.NO_ID) {
getModelWriter().updateItemInDatabase(si);
}
});
for (LauncherAppWidgetInfo widgetInfo : dataModel.appWidgets) {
if (mUser.equals(widgetInfo.user) && widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) && packageSet.contains(widgetInfo.providerName.getPackageName())) {
widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY & ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
// adding this flag ensures that launcher shows 'click to setup'
// if the widget has a config activity. In case there is no config
// activity, it will be marked as 'restored' during bind.
widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
widgets.add(widgetInfo);
getModelWriter().updateItemInDatabase(widgetInfo);
}
}
}
bindUpdatedWorkspaceItems(updatedWorkspaceItems);
if (!removedShortcuts.isEmpty()) {
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts));
}
if (!widgets.isEmpty()) {
scheduleCallbackTask(c -> c.bindWidgetsRestored(widgets));
}
}
final HashSet<String> removedPackages = new HashSet<>();
if (mOp == OP_REMOVE) {
// Mark all packages in the broadcast to be removed
Collections.addAll(removedPackages, packages);
// No need to update the removedComponents as
// removedPackages is a super-set of removedComponents
} else if (mOp == OP_UPDATE) {
// Mark disabled packages in the broadcast to be removed
final LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
for (int i = 0; i < N; i++) {
if (!launcherApps.isPackageEnabled(packages[i], mUser)) {
removedPackages.add(packages[i]);
}
}
}
if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser).or(ItemInfoMatcher.ofComponents(removedComponents, mUser)).and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());
deleteAndBindComponentsRemoved(removeMatch);
// Remove any queued items from the install queue
ItemInstallQueue.INSTANCE.get(context).removeFromInstallQueue(removedPackages, mUser);
}
if (mOp == OP_ADD) {
// AppWidgetHost events, this is just to initialize the long-press options.
for (int i = 0; i < N; i++) {
dataModel.widgetsModel.update(app, new PackageUserKey(packages[i], mUser));
}
bindUpdatedWidgets(dataModel);
}
if (needsRestart) {
Utilities.restart(context);
}
}
Aggregations