use of android.content.pm.ActivityInfo in project android_frameworks_base by DirtyUnicorns.
the class PackageManagerService method findPreferredActivity.
// TODO: handle preferred activities missing while user has amnesia
ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int priority, boolean always, boolean removeMatches, boolean debug, int userId) {
if (!sUserManager.exists(userId))
return null;
flags = updateFlagsForResolve(flags, userId, intent);
// writer
synchronized (mPackages) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
}
if (DEBUG_PREFERRED)
intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
// Try to find a matching persistent preferred activity.
ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query, debug, userId);
// If a persistent preferred activity matched, use it.
if (pri != null) {
return pri;
}
PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
// Get the list of preferred activities that handle the intent
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Looking for preferred activities...");
List<PreferredActivity> prefs = pir != null ? pir.queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId) : null;
if (prefs != null && prefs.size() > 0) {
boolean changed = false;
try {
// First figure out how good the original match set is.
// We will only allow preferred activities that came
// from the same match quality.
int match = 0;
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Figuring out best match...");
final int N = query.size();
for (int j = 0; j < N; j++) {
final ResolveInfo ri = query.get(j);
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Match for " + ri.activityInfo + ": 0x" + Integer.toHexString(match));
if (ri.match > match) {
match = ri.match;
}
}
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Best match: 0x" + Integer.toHexString(match));
match &= IntentFilter.MATCH_CATEGORY_MASK;
final int M = prefs.size();
for (int i = 0; i < M; i++) {
final PreferredActivity pa = prefs.get(i);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Checking PreferredActivity ds=" + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>") + "\n component=" + pa.mPref.mComponent);
pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
}
if (pa.mPref.mMatch != match) {
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Skipping bad match " + Integer.toHexString(pa.mPref.mMatch));
continue;
}
// looking for, skip it.
if (always && !pa.mPref.mAlways) {
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Skipping mAlways=false entry");
continue;
}
final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Found preferred activity:");
if (ai != null) {
ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
} else {
Slog.v(TAG, " null");
}
}
if (ai == null) {
// This previously registered preferred activity
// component is no longer known. Most likely an update
// to the app was installed and in the new version this
// component no longer exists. Clean it up by removing
// it from the preferred activities list, and skip it.
Slog.w(TAG, "Removing dangling preferred activity: " + pa.mPref.mComponent);
pir.removeFilter(pa);
changed = true;
continue;
}
for (int j = 0; j < N; j++) {
final ResolveInfo ri = query.get(j);
if (!ri.activityInfo.applicationInfo.packageName.equals(ai.applicationInfo.packageName)) {
continue;
}
if (!ri.activityInfo.name.equals(ai.name)) {
continue;
}
if (removeMatches) {
pir.removeFilter(pa);
changed = true;
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Removing match " + pa.mPref.mComponent);
}
break;
}
// user their preference, if we're looking for an "always" type entry.
if (always && !pa.mPref.sameSet(query)) {
Slog.i(TAG, "Result set changed, dropping preferred activity for " + intent + " type " + resolvedType);
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Removing preferred activity since set changed " + pa.mPref.mComponent);
}
pir.removeFilter(pa);
// Re-add the filter as a "last chosen" entry (!always)
PreferredActivity lastChosen = new PreferredActivity(pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
pir.addFilter(lastChosen);
changed = true;
return null;
}
// Yay! Either the set matched or we're looking for the last chosen
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "Returning preferred activity: " + ri.activityInfo.packageName + "/" + ri.activityInfo.name);
return ri;
}
}
} finally {
if (changed) {
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
}
scheduleWritePackageRestrictionsLocked(userId);
}
}
}
}
if (DEBUG_PREFERRED || debug)
Slog.v(TAG, "No preferred activity to return");
return null;
}
use of android.content.pm.ActivityInfo in project android_frameworks_base by DirtyUnicorns.
the class PackageManagerService method createForwardingResolveInfoUnchecked.
private ResolveInfo createForwardingResolveInfoUnchecked(IntentFilter filter, int sourceUserId, int targetUserId) {
ResolveInfo forwardingResolveInfo = new ResolveInfo();
long ident = Binder.clearCallingIdentity();
boolean targetIsProfile;
try {
targetIsProfile = sUserManager.getUserInfo(targetUserId).isManagedProfile();
} finally {
Binder.restoreCallingIdentity(ident);
}
String className;
if (targetIsProfile) {
className = FORWARD_INTENT_TO_MANAGED_PROFILE;
} else {
className = FORWARD_INTENT_TO_PARENT;
}
ComponentName forwardingActivityComponentName = new ComponentName(mAndroidApplication.packageName, className);
ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0, sourceUserId);
if (!targetIsProfile) {
forwardingActivityInfo.showUserIcon = targetUserId;
forwardingResolveInfo.noResourceId = true;
}
forwardingResolveInfo.activityInfo = forwardingActivityInfo;
forwardingResolveInfo.priority = 0;
forwardingResolveInfo.preferredOrder = 0;
forwardingResolveInfo.match = 0;
forwardingResolveInfo.isDefault = true;
forwardingResolveInfo.filter = filter;
forwardingResolveInfo.targetUserId = targetUserId;
return forwardingResolveInfo;
}
use of android.content.pm.ActivityInfo in project android_frameworks_base by DirtyUnicorns.
the class ActivityManagerService method startHomeActivityLocked.
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) {
// error message and don't try to start anything.
return false;
}
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
use of android.content.pm.ActivityInfo in project android_frameworks_base by DirtyUnicorns.
the class ActivityManagerService method systemReady.
public void systemReady(final Runnable goingCallback) {
synchronized (this) {
if (mSystemReady) {
// by the SystemServer
if (goingCallback != null) {
goingCallback.run();
}
return;
}
mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class);
// Make sure we have the current profile info, since it is needed for security checks.
mUserController.onSystemReady();
mRecentTasks.onSystemReadyLocked();
mAppOpsService.systemReady();
mSystemReady = true;
}
ArrayList<ProcessRecord> procsToKill = null;
synchronized (mPidsSelfLocked) {
for (int i = mPidsSelfLocked.size() - 1; i >= 0; i--) {
ProcessRecord proc = mPidsSelfLocked.valueAt(i);
if (!isAllowedWhileBooting(proc.info)) {
if (procsToKill == null) {
procsToKill = new ArrayList<ProcessRecord>();
}
procsToKill.add(proc);
}
}
}
synchronized (this) {
if (procsToKill != null) {
for (int i = procsToKill.size() - 1; i >= 0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true, false, "system update done");
}
}
// Now that we have cleaned up any update processes, we
// are ready to start launching real processes and know that
// we won't trample on them any more.
mProcessesReady = true;
}
Slog.i(TAG, "System now ready");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY, SystemClock.uptimeMillis());
synchronized (this) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
ResolveInfo ri = mContext.getPackageManager().resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST), STOCK_PM_FLAGS);
CharSequence errorMsg = null;
if (ri != null) {
ActivityInfo ai = ri.activityInfo;
ApplicationInfo app = ai.applicationInfo;
if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
mTopAction = Intent.ACTION_FACTORY_TEST;
mTopData = null;
mTopComponent = new ComponentName(app.packageName, ai.name);
} else {
errorMsg = mContext.getResources().getText(com.android.internal.R.string.factorytest_not_system);
}
} else {
errorMsg = mContext.getResources().getText(com.android.internal.R.string.factorytest_no_action);
}
if (errorMsg != null) {
mTopAction = null;
mTopData = null;
mTopComponent = null;
Message msg = Message.obtain();
msg.what = SHOW_FACTORY_ERROR_UI_MSG;
msg.getData().putCharSequence("msg", errorMsg);
mUiHandler.sendMessage(msg);
}
}
}
retrieveSettings();
final int currentUserId;
synchronized (this) {
currentUserId = mUserController.getCurrentUserIdLocked();
readGrantedUriPermissionsLocked();
}
if (goingCallback != null)
goingCallback.run();
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, Integer.toString(currentUserId), currentUserId);
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(currentUserId), currentUserId);
mSystemServiceManager.startUser(currentUserId);
synchronized (this) {
// Only start up encryption-aware persistent apps; once user is
// unlocked we'll come back around and start unaware apps
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
// Start up initial activity.
mBooting = true;
// Enable home activity for system user, so that the system can always boot
if (UserManager.isSplitSystemUser()) {
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
startHomeActivityLocked(currentUserId, "systemReady");
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your" + " data partition or your device will be unstable.");
mUiHandler.obtainMessage(SHOW_UID_ERROR_UI_MSG).sendToTarget();
}
} catch (RemoteException e) {
}
if (!Build.isBuildConsistent()) {
Slog.e(TAG, "Build fingerprint is not consistent, warning user");
mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_UI_MSG).sendToTarget();
}
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, currentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
broadcastIntentLocked(null, null, intent, null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
}
}, 0, null, null, new String[] { INTERACT_ACROSS_USERS }, AppOpsManager.OP_NONE, null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
Binder.restoreCallingIdentity(ident);
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
}
}
use of android.content.pm.ActivityInfo in project android_frameworks_base by DirtyUnicorns.
the class ActivityStack method findTaskLocked.
/**
* Returns the top activity in any existing task matching the given Intent in the input result.
* Returns null if no such task is found.
*/
void findTaskLocked(ActivityRecord target, FindTaskResult result) {
Intent intent = target.intent;
ActivityInfo info = target.info;
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
boolean isDocument = intent != null & intent.isDocument();
// If documentData is non-null then it must match the existing task data.
Uri documentData = isDocument ? intent.getData() : null;
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
if (task.voiceSession != null) {
// We never match voice sessions; those always run independently.
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
continue;
}
if (task.userId != userId) {
// Looking for a different task.
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
continue;
}
final ActivityRecord r = task.getTopActivity();
if (r == null || r.finishing || r.userId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
continue;
}
if (r.mActivityType != target.mActivityType) {
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
continue;
}
final Intent taskIntent = task.intent;
final Intent affinityIntent = task.affinityIntent;
final boolean taskIsDocument;
final Uri taskDocumentData;
if (taskIntent != null && taskIntent.isDocument()) {
taskIsDocument = true;
taskDocumentData = taskIntent.getData();
} else if (affinityIntent != null && affinityIntent.isDocument()) {
taskIsDocument = true;
taskDocumentData = affinityIntent.getData();
} else {
taskIsDocument = false;
taskDocumentData = null;
}
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Comparing existing cls=" + taskIntent.getComponent().flattenToShortString() + "/aff=" + r.task.rootAffinity + " to new cls=" + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
// TODO Refactor to remove duplications. Check if logic can be simplified.
if (taskIntent != null && taskIntent.getComponent() != null && taskIntent.getComponent().compareTo(cls) == 0 && Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Found matching class!");
//dump();
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "For Intent " + intent + " bringing to top: " + r.intent);
result.r = r;
result.matchedByRootAffinity = false;
break;
} else if (affinityIntent != null && affinityIntent.getComponent() != null && affinityIntent.getComponent().compareTo(cls) == 0 && Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Found matching class!");
//dump();
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "For Intent " + intent + " bringing to top: " + r.intent);
result.r = r;
result.matchedByRootAffinity = false;
break;
} else if (!isDocument && !taskIsDocument && result.r == null && task.canMatchRootAffinity()) {
if (task.rootAffinity.equals(target.taskAffinity)) {
if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Found matching affinity candidate!");
// It is possible for multiple tasks to have the same root affinity especially
// if they are in separate stacks. We save off this candidate, but keep looking
// to see if there is a better candidate.
result.r = r;
result.matchedByRootAffinity = true;
}
} else if (DEBUG_TASKS)
Slog.d(TAG_TASKS, "Not a match: " + task);
}
}
Aggregations