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();
}
}
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;
}
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;
}
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);
}
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;
}
Aggregations