Search in sources :

Example 6 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project platform_frameworks_base by android.

the class ShortcutPackage method deleteAllDynamicShortcuts.

/**
     * Remove all dynamic shortcuts.
     */
public void deleteAllDynamicShortcuts() {
    final long now = mShortcutUser.mService.injectCurrentTimeMillis();
    boolean changed = false;
    for (int i = mShortcuts.size() - 1; i >= 0; i--) {
        final ShortcutInfo si = mShortcuts.valueAt(i);
        if (si.isDynamic()) {
            changed = true;
            si.setTimestamp(now);
            si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
            // It may still be pinned, so clear the rank.
            si.setRank(0);
        }
    }
    if (changed) {
        removeOrphans();
    }
}
Also used : ShortcutInfo(android.content.pm.ShortcutInfo)

Example 7 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project platform_frameworks_base by android.

the class ShortcutPackage method pushOutExcessShortcuts.

/**
     * For each target activity, make sure # of dynamic + manifest shortcuts <= max.
     * If too many, we'll remove the dynamic with the lowest ranks.
     */
private boolean pushOutExcessShortcuts() {
    final ShortcutService service = mShortcutUser.mService;
    final int maxShortcuts = service.getMaxActivityShortcuts();
    boolean changed = false;
    final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all = sortShortcutsToActivities();
    for (int outer = all.size() - 1; outer >= 0; outer--) {
        final ArrayList<ShortcutInfo> list = all.valueAt(outer);
        if (list.size() <= maxShortcuts) {
            continue;
        }
        // Sort by isManifestShortcut() and getRank().
        Collections.sort(list, mShortcutTypeAndRankComparator);
        // Keep [0 .. max), and remove (as dynamic) [max .. size)
        for (int inner = list.size() - 1; inner >= maxShortcuts; inner--) {
            final ShortcutInfo shortcut = list.get(inner);
            if (shortcut.isManifestShortcut()) {
                // This shouldn't happen -- excess shortcuts should all be non-manifest.
                // But just in case.
                service.wtf("Found manifest shortcuts in excess list.");
                continue;
            }
            deleteDynamicWithId(shortcut.getId());
        }
    }
    return changed;
}
Also used : ShortcutInfo(android.content.pm.ShortcutInfo) ArrayList(java.util.ArrayList) ComponentName(android.content.ComponentName)

Example 8 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project platform_frameworks_base by android.

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;
        }
        if (!isNewApp && !forceRescan) {
            // really change on OTAs.
            if ((getPackageInfo().getVersionCode() == pi.versionCode) && (getPackageInfo().getLastUpdateTime() == pi.lastUpdateTime) && areAllActivitiesStillEnabled()) {
                return false;
            }
        }
    } 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 9 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project platform_frameworks_base by android.

the class ShortcutPackage method parseShortcut.

private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName, @UserIdInt int userId) throws IOException, XmlPullParserException {
    String id;
    ComponentName activityComponent;
    // Icon icon;
    String title;
    int titleResId;
    String titleResName;
    String text;
    int textResId;
    String textResName;
    String disabledMessage;
    int disabledMessageResId;
    String disabledMessageResName;
    Intent intentLegacy;
    PersistableBundle intentPersistableExtrasLegacy = null;
    ArrayList<Intent> intents = new ArrayList<>();
    int rank;
    PersistableBundle extras = null;
    long lastChangedTimestamp;
    int flags;
    int iconResId;
    String iconResName;
    String bitmapPath;
    ArraySet<String> categories = null;
    id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
    activityComponent = ShortcutService.parseComponentNameAttribute(parser, ATTR_ACTIVITY);
    title = ShortcutService.parseStringAttribute(parser, ATTR_TITLE);
    titleResId = ShortcutService.parseIntAttribute(parser, ATTR_TITLE_RES_ID);
    titleResName = ShortcutService.parseStringAttribute(parser, ATTR_TITLE_RES_NAME);
    text = ShortcutService.parseStringAttribute(parser, ATTR_TEXT);
    textResId = ShortcutService.parseIntAttribute(parser, ATTR_TEXT_RES_ID);
    textResName = ShortcutService.parseStringAttribute(parser, ATTR_TEXT_RES_NAME);
    disabledMessage = ShortcutService.parseStringAttribute(parser, ATTR_DISABLED_MESSAGE);
    disabledMessageResId = ShortcutService.parseIntAttribute(parser, ATTR_DISABLED_MESSAGE_RES_ID);
    disabledMessageResName = ShortcutService.parseStringAttribute(parser, ATTR_DISABLED_MESSAGE_RES_NAME);
    intentLegacy = ShortcutService.parseIntentAttributeNoDefault(parser, ATTR_INTENT_LEGACY);
    rank = (int) ShortcutService.parseLongAttribute(parser, ATTR_RANK);
    lastChangedTimestamp = ShortcutService.parseLongAttribute(parser, ATTR_TIMESTAMP);
    flags = (int) ShortcutService.parseLongAttribute(parser, ATTR_FLAGS);
    iconResId = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES_ID);
    iconResName = ShortcutService.parseStringAttribute(parser, ATTR_ICON_RES_NAME);
    bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
    final int outerDepth = parser.getDepth();
    int type;
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
        if (type != XmlPullParser.START_TAG) {
            continue;
        }
        final int depth = parser.getDepth();
        final String tag = parser.getName();
        if (ShortcutService.DEBUG_LOAD) {
            Slog.d(TAG, String.format("  depth=%d type=%d name=%s", depth, type, tag));
        }
        switch(tag) {
            case TAG_INTENT_EXTRAS_LEGACY:
                intentPersistableExtrasLegacy = PersistableBundle.restoreFromXml(parser);
                continue;
            case TAG_INTENT:
                intents.add(parseIntent(parser));
                continue;
            case TAG_EXTRAS:
                extras = PersistableBundle.restoreFromXml(parser);
                continue;
            case TAG_CATEGORIES:
                // This just contains string-array.
                continue;
            case TAG_STRING_ARRAY_XMLUTILS:
                if (NAME_CATEGORIES.equals(ShortcutService.parseStringAttribute(parser, ATTR_NAME_XMLUTILS))) {
                    final String[] ar = XmlUtils.readThisStringArrayXml(parser, TAG_STRING_ARRAY_XMLUTILS, null);
                    categories = new ArraySet<>(ar.length);
                    for (int i = 0; i < ar.length; i++) {
                        categories.add(ar[i]);
                    }
                }
                continue;
        }
        throw ShortcutService.throwForInvalidTag(depth, tag);
    }
    if (intentLegacy != null) {
        // For the legacy file format which supported only one intent per shortcut.
        ShortcutInfo.setIntentExtras(intentLegacy, intentPersistableExtrasLegacy);
        intents.clear();
        intents.add(intentLegacy);
    }
    return new ShortcutInfo(userId, id, packageName, activityComponent, /* icon =*/
    null, title, titleResId, titleResName, text, textResId, textResName, disabledMessage, disabledMessageResId, disabledMessageResName, categories, intents.toArray(new Intent[intents.size()]), rank, extras, lastChangedTimestamp, flags, iconResId, iconResName, bitmapPath);
}
Also used : PersistableBundle(android.os.PersistableBundle) ShortcutInfo(android.content.pm.ShortcutInfo) ArrayList(java.util.ArrayList) ComponentName(android.content.ComponentName) Intent(android.content.Intent)

Example 10 with ShortcutInfo

use of android.content.pm.ShortcutInfo in project platform_frameworks_base by android.

the class ShortcutPackage method dumpCheckin.

@Override
public JSONObject dumpCheckin(boolean clear) throws JSONException {
    final JSONObject result = super.dumpCheckin(clear);
    int numDynamic = 0;
    int numPinned = 0;
    int numManifest = 0;
    int numBitmaps = 0;
    long totalBitmapSize = 0;
    final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
    final int size = shortcuts.size();
    for (int i = 0; i < size; i++) {
        final ShortcutInfo si = shortcuts.valueAt(i);
        if (si.isDynamic())
            numDynamic++;
        if (si.isDeclaredInManifest())
            numManifest++;
        if (si.isPinned())
            numPinned++;
        if (si.getBitmapPath() != null) {
            numBitmaps++;
            totalBitmapSize += new File(si.getBitmapPath()).length();
        }
    }
    result.put(KEY_DYNAMIC, numDynamic);
    result.put(KEY_MANIFEST, numManifest);
    result.put(KEY_PINNED, numPinned);
    result.put(KEY_BITMAPS, numBitmaps);
    result.put(KEY_BITMAP_BYTES, totalBitmapSize);
    return result;
}
Also used : JSONObject(org.json.JSONObject) ShortcutInfo(android.content.pm.ShortcutInfo) File(java.io.File)

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