Search in sources :

Example 61 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project android_frameworks_base by ResurrectionRemix.

the class ShortcutPackage method rescanPackageIfNeeded.

/**
     * Called when the package may be added or updated, or its activities may be disabled, and
     * if so, rescan the package and do the necessary stuff.
     *
     * Add case:
     * - Publish manifest shortcuts.
     *
     * Update case:
     * - Re-publish manifest shortcuts.
     * - If there are shortcuts with resources (icons or strings), update their timestamps.
     * - Disable shortcuts whose target activities are disabled.
     *
     * @return TRUE if any shortcuts have been changed.
     */
public boolean rescanPackageIfNeeded(boolean isNewApp, boolean forceRescan) {
    final ShortcutService s = mShortcutUser.mService;
    final long start = s.injectElapsedRealtime();
    final PackageInfo pi;
    try {
        pi = mShortcutUser.mService.getPackageInfo(getPackageName(), getPackageUserId());
        if (pi == null) {
            // Shouldn't happen.
            return false;
        }
        // Always scan the settings app, since its version code is the same for DR and MR1.
        // TODO Fix it properly: b/32554059
        final boolean isSettings = "com.android.settings".equals(getPackageName());
        if (!isNewApp && !forceRescan && !isSettings) {
            // really change on OTAs.
            if ((getPackageInfo().getVersionCode() == pi.versionCode) && (getPackageInfo().getLastUpdateTime() == pi.lastUpdateTime) && areAllActivitiesStillEnabled()) {
                return false;
            }
        }
        if (isSettings) {
            if (ShortcutService.DEBUG) {
                Slog.d(TAG, "Always scan settings.");
            }
        }
    } finally {
        s.logDurationStat(Stats.PACKAGE_UPDATE_CHECK, start);
    }
    // Now prepare to publish manifest shortcuts.
    List<ShortcutInfo> newManifestShortcutList = null;
    try {
        newManifestShortcutList = ShortcutParser.parseShortcuts(mShortcutUser.mService, getPackageName(), getPackageUserId());
    } catch (IOException | XmlPullParserException e) {
        Slog.e(TAG, "Failed to load shortcuts from AndroidManifest.xml.", e);
    }
    final int manifestShortcutSize = newManifestShortcutList == null ? 0 : newManifestShortcutList.size();
    if (ShortcutService.DEBUG) {
        Slog.d(TAG, String.format("Package %s has %d manifest shortcut(s)", getPackageName(), manifestShortcutSize));
    }
    if (isNewApp && (manifestShortcutSize == 0)) {
        // disabled.
        return false;
    }
    if (ShortcutService.DEBUG) {
        Slog.d(TAG, String.format("Package %s %s, version %d -> %d", getPackageName(), (isNewApp ? "added" : "updated"), getPackageInfo().getVersionCode(), pi.versionCode));
    }
    getPackageInfo().updateVersionInfo(pi);
    boolean changed = false;
    // Also check if shortcuts' activities are still main activities.  Otherwise, disable them.
    if (!isNewApp) {
        Resources publisherRes = null;
        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
            final ShortcutInfo si = mShortcuts.valueAt(i);
            if (si.isDynamic()) {
                if (!s.injectIsMainActivity(si.getActivity(), getPackageUserId())) {
                    Slog.w(TAG, String.format("%s is no longer main activity. Disabling shorcut %s.", getPackageName(), si.getId()));
                    if (disableDynamicWithId(si.getId())) {
                        // Actually removed.
                        continue;
                    }
                // Still pinned, so fall-through and possibly update the resources.
                }
                changed = true;
            }
            if (si.hasAnyResources()) {
                if (!si.isOriginallyFromManifest()) {
                    if (publisherRes == null) {
                        publisherRes = getPackageResources();
                        if (publisherRes == null) {
                            // Resources couldn't be loaded.
                            break;
                        }
                    }
                    // If this shortcut is not from a manifest, then update all resource IDs
                    // from resource names.  (We don't allow resource strings for
                    // non-manifest at the moment, but icons can still be resources.)
                    si.lookupAndFillInResourceIds(publisherRes);
                }
                changed = true;
                si.setTimestamp(s.injectCurrentTimeMillis());
            }
        }
    }
    // (Re-)publish manifest shortcut.
    changed |= publishManifestShortcuts(newManifestShortcutList);
    if (newManifestShortcutList != null) {
        changed |= pushOutExcessShortcuts();
    }
    s.verifyStates();
    if (changed) {
        // This will send a notification to the launcher, and also save .
        s.packageShortcutsChanged(getPackageName(), getPackageUserId());
    } else {
        // Still save the version code.
        s.scheduleSaveUser(getPackageUserId());
    }
    return changed;
}
Also used : ShortcutInfo(android.content.pm.ShortcutInfo) PackageInfo(android.content.pm.PackageInfo) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) IOException(java.io.IOException) Resources(android.content.res.Resources)

Example 62 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project android_frameworks_base by ResurrectionRemix.

the class ShortcutParser method parseShortcuts.

@Nullable
public static List<ShortcutInfo> parseShortcuts(ShortcutService service, String packageName, @UserIdInt int userId) throws IOException, XmlPullParserException {
    if (ShortcutService.DEBUG) {
        Slog.d(TAG, String.format("Scanning package %s for manifest shortcuts on user %d", packageName, userId));
    }
    final List<ResolveInfo> activities = service.injectGetMainActivities(packageName, userId);
    if (activities == null || activities.size() == 0) {
        return null;
    }
    List<ShortcutInfo> result = null;
    try {
        final int size = activities.size();
        for (int i = 0; i < size; i++) {
            final ActivityInfo activityInfoNoMetadata = activities.get(i).activityInfo;
            if (activityInfoNoMetadata == null) {
                continue;
            }
            final ActivityInfo activityInfoWithMetadata = service.getActivityInfoWithMetadata(activityInfoNoMetadata.getComponentName(), userId);
            if (activityInfoWithMetadata != null) {
                result = parseShortcutsOneFile(service, activityInfoWithMetadata, packageName, userId, result);
            }
        }
    } catch (RuntimeException e) {
        // Resource ID mismatch may cause various runtime exceptions when parsing XMLs,
        // But we don't crash the device, so just swallow them.
        service.wtf("Exception caught while parsing shortcut XML for package=" + packageName, e);
        return null;
    }
    return result;
}
Also used : ResolveInfo(android.content.pm.ResolveInfo) ActivityInfo(android.content.pm.ActivityInfo) ShortcutInfo(android.content.pm.ShortcutInfo) Nullable(android.annotation.Nullable)

Example 63 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project android_frameworks_base by ResurrectionRemix.

the class ShortcutService method addDynamicShortcuts.

@Override
public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList, @UserIdInt int userId) {
    verifyCaller(packageName, userId);
    final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
    final int size = newShortcuts.size();
    synchronized (mLock) {
        throwIfUserLockedL(userId);
        final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
        ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
        fillInDefaultActivity(newShortcuts);
        ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_ADD);
        // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
        ps.clearAllImplicitRanks();
        assignImplicitRanks(newShortcuts);
        // Throttling.
        if (!ps.tryApiCall()) {
            return false;
        }
        for (int i = 0; i < size; i++) {
            final ShortcutInfo newShortcut = newShortcuts.get(i);
            // Validate the shortcut.
            fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */
            false);
            // When ranks are changing, we need to insert between ranks, so set the
            // "rank changed" flag.
            newShortcut.setRankChanged();
            // Add it.
            ps.addOrUpdateDynamicShortcut(newShortcut);
        }
        // Lastly, adjust the ranks.
        ps.adjustRanks();
    }
    packageShortcutsChanged(packageName, userId);
    verifyStates();
    return true;
}
Also used : ShortcutInfo(android.content.pm.ShortcutInfo) ArrayList(java.util.ArrayList) List(java.util.List) LocaleList(android.os.LocaleList)

Example 64 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project android_frameworks_base by ResurrectionRemix.

the class ShortcutService method setDynamicShortcuts.

// === APIs ===
@Override
public boolean setDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList, @UserIdInt int userId) {
    verifyCaller(packageName, userId);
    final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
    final int size = newShortcuts.size();
    synchronized (mLock) {
        throwIfUserLockedL(userId);
        final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
        ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
        fillInDefaultActivity(newShortcuts);
        ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_SET);
        // Throttling.
        if (!ps.tryApiCall()) {
            return false;
        }
        // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
        ps.clearAllImplicitRanks();
        assignImplicitRanks(newShortcuts);
        for (int i = 0; i < size; i++) {
            fixUpIncomingShortcutInfo(newShortcuts.get(i), /* forUpdate= */
            false);
        }
        // First, remove all un-pinned; dynamic shortcuts
        ps.deleteAllDynamicShortcuts();
        // Then, add/update all.  We need to make sure to take over "pinned" flag.
        for (int i = 0; i < size; i++) {
            final ShortcutInfo newShortcut = newShortcuts.get(i);
            ps.addOrUpdateDynamicShortcut(newShortcut);
        }
        // Lastly, adjust the ranks.
        ps.adjustRanks();
    }
    packageShortcutsChanged(packageName, userId);
    verifyStates();
    return true;
}
Also used : ShortcutInfo(android.content.pm.ShortcutInfo) ArrayList(java.util.ArrayList) List(java.util.List) LocaleList(android.os.LocaleList)

Example 65 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project android_frameworks_base by ResurrectionRemix.

the class ShortcutPackage method adjustRanks.

/**
     * Re-calculate the ranks for all shortcuts.
     */
public void adjustRanks() {
    final ShortcutService s = mShortcutUser.mService;
    final long now = s.injectCurrentTimeMillis();
    // First, clear ranks for floating shortcuts.
    for (int i = mShortcuts.size() - 1; i >= 0; i--) {
        final ShortcutInfo si = mShortcuts.valueAt(i);
        if (si.isFloating()) {
            if (si.getRank() != 0) {
                si.setTimestamp(now);
                si.setRank(0);
            }
        }
    }
    // Then adjust ranks.  Ranks are unique for each activity, so we first need to sort
    // shortcuts to each activity.
    // Then sort the shortcuts within each activity with mShortcutRankComparator, and
    // assign ranks from 0.
    final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all = sortShortcutsToActivities();
    for (int outer = all.size() - 1; outer >= 0; outer--) {
        // For each activity.
        final ArrayList<ShortcutInfo> list = all.valueAt(outer);
        // Sort by ranks and other signals.
        Collections.sort(list, mShortcutRankComparator);
        int rank = 0;
        final int size = list.size();
        for (int i = 0; i < size; i++) {
            final ShortcutInfo si = list.get(i);
            if (si.isManifestShortcut()) {
                // Don't adjust ranks for manifest shortcuts.
                continue;
            }
            // At this point, it must be dynamic.
            if (!si.isDynamic()) {
                s.wtf("Non-dynamic shortcut found.");
                continue;
            }
            final int thisRank = rank++;
            if (si.getRank() != thisRank) {
                si.setTimestamp(now);
                si.setRank(thisRank);
            }
        }
    }
}
Also used : ShortcutInfo(android.content.pm.ShortcutInfo) ArrayList(java.util.ArrayList) ComponentName(android.content.ComponentName)

Aggregations

ShortcutInfo (android.content.pm.ShortcutInfo)324 ComponentName (android.content.ComponentName)144 PersistableBundle (android.os.PersistableBundle)48 ArrayList (java.util.ArrayList)46 Intent (android.content.Intent)44 Icon (android.graphics.drawable.Icon)32 List (java.util.List)17 Matchers.anyString (org.mockito.Matchers.anyString)16 LocaleList (android.os.LocaleList)12 File (java.io.File)12 Nullable (android.annotation.Nullable)8 ShortcutQuery (android.content.pm.LauncherApps.ShortcutQuery)8 Resources (android.content.res.Resources)8 Bundle (android.os.Bundle)8 ArrayMap (android.util.ArrayMap)8 PackageWithUser (com.android.server.pm.ShortcutUser.PackageWithUser)8 ShortcutManagerTestUtils.makeBundle (com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle)8 IOException (java.io.IOException)8 ArraySet (android.util.ArraySet)5 Manifest.permission (android.Manifest.permission)4