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