use of android.app.IActivityContainer in project android_frameworks_base by DirtyUnicorns.
the class PendingIntentRecord method sendInner.
int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
if (intent != null)
intent.setDefusable(true);
if (options != null)
options.setDefusable(true);
if (whitelistDuration > 0 && !canceled) {
// Must call before acquiring the lock. It's possible the method return before sending
// the intent due to some validations inside the lock, in which case the UID shouldn't
// be whitelisted, but since the whitelist is temporary, that would be ok.
owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid, whitelistDuration);
}
synchronized (owner) {
final ActivityContainer activityContainer = (ActivityContainer) container;
if (activityContainer != null && activityContainer.mParentActivity != null && activityContainer.mParentActivity.state != ActivityStack.ActivityState.RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
if (!canceled) {
sent = true;
if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) {
owner.cancelIntentSenderLocked(this, true);
canceled = true;
}
Intent finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent();
final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
if (!immutable) {
if (intent != null) {
int changes = finalIntent.fillIn(intent, key.flags);
if ((changes & Intent.FILL_IN_DATA) == 0) {
resolvedType = key.requestResolvedType;
}
} else {
resolvedType = key.requestResolvedType;
}
flagsMask &= ~Intent.IMMUTABLE_FLAGS;
flagsValues &= flagsMask;
finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
} else {
resolvedType = key.requestResolvedType;
}
final long origId = Binder.clearCallingIdentity();
boolean sendFinish = finishedReceiver != null;
int userId = key.userId;
if (userId == UserHandle.USER_CURRENT) {
userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
}
int res = 0;
switch(key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
if (options == null) {
options = key.options;
} else if (key.options != null) {
Bundle opts = new Bundle(key.options);
opts.putAll(options);
options = opts;
}
try {
if (key.allIntents != null && key.allIntents.length > 1) {
Intent[] allIntents = new Intent[key.allIntents.length];
String[] allResolvedTypes = new String[key.allIntents.length];
System.arraycopy(key.allIntents, 0, allIntents, 0, key.allIntents.length);
if (key.allResolvedTypes != null) {
System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, key.allResolvedTypes.length);
}
allIntents[allIntents.length - 1] = finalIntent;
allResolvedTypes[allResolvedTypes.length - 1] = resolvedType;
owner.startActivitiesInPackage(uid, key.packageName, allIntents, allResolvedTypes, resultTo, options, userId);
} else {
owner.startActivityInPackage(uid, key.packageName, finalIntent, resolvedType, resultTo, resultWho, requestCode, 0, options, userId, container, null);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
}
break;
case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
if (key.activity.task.stack != null) {
key.activity.task.stack.sendActivityResultLocked(-1, key.activity, key.who, key.requestCode, code, finalIntent);
}
break;
case ActivityManager.INTENT_SENDER_BROADCAST:
try {
// If a completion callback has been requested, require
// that the broadcast be delivered synchronously
int sent = owner.broadcastIntentInPackage(key.packageName, uid, finalIntent, resolvedType, finishedReceiver, code, null, null, requiredPermission, options, (finishedReceiver != null), false, userId);
if (sent == ActivityManager.BROADCAST_SUCCESS) {
sendFinish = false;
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
}
break;
case ActivityManager.INTENT_SENDER_SERVICE:
try {
owner.startServiceInPackage(uid, finalIntent, resolvedType, key.packageName, userId);
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startService intent", e);
} catch (TransactionTooLargeException e) {
res = ActivityManager.START_CANCELED;
}
break;
}
if (sendFinish && res != ActivityManager.START_CANCELED) {
try {
finishedReceiver.performReceive(new Intent(finalIntent), 0, null, null, false, false, key.userId);
} catch (RemoteException e) {
}
}
Binder.restoreCallingIdentity(origId);
return res;
}
}
return ActivityManager.START_CANCELED;
}
use of android.app.IActivityContainer in project android_frameworks_base by AOSPA.
the class Am method runStackStart.
private void runStackStart() throws Exception {
String displayIdStr = nextArgRequired();
int displayId = Integer.parseInt(displayIdStr);
Intent intent = makeIntent(UserHandle.USER_CURRENT);
try {
IActivityContainer container = mAm.createStackOnDisplay(displayId);
if (container != null) {
container.startActivity(intent);
}
} catch (RemoteException e) {
}
}
use of android.app.IActivityContainer in project android_frameworks_base by AOSPA.
the class PendingIntentRecord method sendInner.
int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
if (intent != null)
intent.setDefusable(true);
if (options != null)
options.setDefusable(true);
if (whitelistDuration > 0 && !canceled) {
// Must call before acquiring the lock. It's possible the method return before sending
// the intent due to some validations inside the lock, in which case the UID shouldn't
// be whitelisted, but since the whitelist is temporary, that would be ok.
owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid, whitelistDuration);
}
synchronized (owner) {
final ActivityContainer activityContainer = (ActivityContainer) container;
if (activityContainer != null && activityContainer.mParentActivity != null && activityContainer.mParentActivity.state != ActivityStack.ActivityState.RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
if (!canceled) {
sent = true;
if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) {
owner.cancelIntentSenderLocked(this, true);
canceled = true;
}
Intent finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent();
final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
if (!immutable) {
if (intent != null) {
int changes = finalIntent.fillIn(intent, key.flags);
if ((changes & Intent.FILL_IN_DATA) == 0) {
resolvedType = key.requestResolvedType;
}
} else {
resolvedType = key.requestResolvedType;
}
flagsMask &= ~Intent.IMMUTABLE_FLAGS;
flagsValues &= flagsMask;
finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
} else {
resolvedType = key.requestResolvedType;
}
final long origId = Binder.clearCallingIdentity();
boolean sendFinish = finishedReceiver != null;
int userId = key.userId;
if (userId == UserHandle.USER_CURRENT) {
userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
}
int res = 0;
switch(key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
if (options == null) {
options = key.options;
} else if (key.options != null) {
Bundle opts = new Bundle(key.options);
opts.putAll(options);
options = opts;
}
try {
if (key.allIntents != null && key.allIntents.length > 1) {
Intent[] allIntents = new Intent[key.allIntents.length];
String[] allResolvedTypes = new String[key.allIntents.length];
System.arraycopy(key.allIntents, 0, allIntents, 0, key.allIntents.length);
if (key.allResolvedTypes != null) {
System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, key.allResolvedTypes.length);
}
allIntents[allIntents.length - 1] = finalIntent;
allResolvedTypes[allResolvedTypes.length - 1] = resolvedType;
owner.startActivitiesInPackage(uid, key.packageName, allIntents, allResolvedTypes, resultTo, options, userId);
} else {
owner.startActivityInPackage(uid, key.packageName, finalIntent, resolvedType, resultTo, resultWho, requestCode, 0, options, userId, container, null);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
}
break;
case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
if (key.activity.task.stack != null) {
key.activity.task.stack.sendActivityResultLocked(-1, key.activity, key.who, key.requestCode, code, finalIntent);
}
break;
case ActivityManager.INTENT_SENDER_BROADCAST:
try {
// If a completion callback has been requested, require
// that the broadcast be delivered synchronously
int sent = owner.broadcastIntentInPackage(key.packageName, uid, finalIntent, resolvedType, finishedReceiver, code, null, null, requiredPermission, options, (finishedReceiver != null), false, userId);
if (sent == ActivityManager.BROADCAST_SUCCESS) {
sendFinish = false;
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
}
break;
case ActivityManager.INTENT_SENDER_SERVICE:
try {
owner.startServiceInPackage(uid, finalIntent, resolvedType, key.packageName, userId);
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startService intent", e);
} catch (TransactionTooLargeException e) {
res = ActivityManager.START_CANCELED;
}
break;
}
if (sendFinish && res != ActivityManager.START_CANCELED) {
try {
finishedReceiver.performReceive(new Intent(finalIntent), 0, null, null, false, false, key.userId);
} catch (RemoteException e) {
}
}
Binder.restoreCallingIdentity(origId);
return res;
}
}
return ActivityManager.START_CANCELED;
}
use of android.app.IActivityContainer in project android_frameworks_base by ResurrectionRemix.
the class ActivityStarter method startActivityMayWait.
final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
boolean componentSpecified = intent.getComponent() != null;
// Save a copy in case ephemeral needs it
final Intent ephemeralIntent = new Intent(intent);
// Don't modify the client's object!
intent = new Intent(intent);
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
if (rInfo == null) {
UserInfo userInfo = mSupervisor.getUserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile()) {
// Special case for managed profiles, if attempting to launch non-cryto aware
// app in a locked managed profile from an unlocked parent allow it to resolve
// as user will be sent via confirm credentials to unlock the profile.
UserManager userManager = UserManager.get(mService.mContext);
boolean profileLockedAndParentUnlockingOrUnlocked = false;
long token = Binder.clearCallingIdentity();
try {
UserInfo parent = userManager.getProfileParent(userId);
profileLockedAndParentUnlockingOrUnlocked = (parent != null) && userManager.isUserUnlockingOrUnlocked(parent.id) && !userManager.isUserUnlockingOrUnlocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
}
}
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
ActivityOptions options = ActivityOptions.fromBundle(bOptions);
ActivityStackSupervisor.ActivityContainer container = (ActivityStackSupervisor.ActivityContainer) iContainer;
synchronized (mService) {
if (container != null && container.mParentActivity != null && container.mParentActivity.state != RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
try {
//TODO: This needs to be a flushed out API in the future.
boolean isProtected = intent.getComponent() != null && AppGlobals.getPackageManager().isComponentProtected(callingPackage, callingUid, intent.getComponent(), userId) && (intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
if (isProtected) {
Message msg = mService.mHandler.obtainMessage(ActivityManagerService.POST_COMPONENT_PROTECTED_MSG);
//Store start flags, userid
intent.setFlags(startFlags);
intent.putExtra("com.android.settings.PROTECTED_APPS_USER_ID", userId);
msg.obj = intent;
mService.mHandler.sendMessage(msg);
return ActivityManager.START_PROTECTED_APP;
}
} catch (RemoteException e) {
e.printStackTrace();
}
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = realCallingPid;
callingUid = realCallingUid;
} else {
callingPid = callingUid = -1;
}
final ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {
stack = mSupervisor.mFocusedStack;
} else {
stack = container.mStack;
}
stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION)
Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
if (aInfo != null && (aInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// have another, different heavy-weight process running.
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
final ProcessRecord heavy = mService.mHeavyWeightProcess;
if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid || !heavy.processName.equals(aInfo.processName))) {
int appCallingUid = callingUid;
if (caller != null) {
ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
appCallingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString());
ActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target = mService.getIntentSenderLocked(ActivityManager.INTENT_SENDER_ACTIVITY, "android", appCallingUid, userId, null, null, 0, new Intent[] { intent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent();
if (requestCode >= 0) {
// Caller is requesting a result.
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, new IntentSender(target));
if (heavy.activities.size() > 0) {
ActivityRecord hist = heavy.activities.get(0);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.task.taskId);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, aInfo.packageName);
newIntent.setFlags(intent.getFlags());
newIntent.setClassName("android", HeavyWeightSwitcherActivity.class.getName());
intent = newIntent;
resolvedType = null;
caller = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
componentSpecified = true;
rInfo = mSupervisor.resolveIntent(intent, null, /*resolvedType*/
userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
if (aInfo != null) {
aInfo = mService.getActivityInfoForUser(aInfo, userId);
}
}
}
}
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask);
Binder.restoreCallingIdentity(origId);
if (stack.mConfigWillChange) {
// If the caller also wants to switch to a new configuration,
// do so now. This allows a clean switch, as we are waiting
// for the current activity to pause (so we will not destroy
// it), and have not yet started the next activity.
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()");
stack.mConfigWillChange = false;
if (DEBUG_CONFIGURATION)
Slog.v(TAG_CONFIGURATION, "Updating to new configuration after starting activity.");
mService.updateConfigurationLocked(config, null, false);
}
if (outResult != null) {
outResult.result = res;
if (res == ActivityManager.START_SUCCESS) {
mSupervisor.mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (outResult.result != START_TASK_TO_FRONT && !outResult.timeout && outResult.who == null);
if (outResult.result == START_TASK_TO_FRONT) {
res = START_TASK_TO_FRONT;
}
}
if (res == START_TASK_TO_FRONT) {
ActivityRecord r = stack.topRunningActivityLocked();
if (r.nowVisible && r.state == RESUMED) {
outResult.timeout = false;
outResult.who = new ComponentName(r.info.packageName, r.info.name);
outResult.totalTime = 0;
outResult.thisTime = 0;
} else {
outResult.thisTime = SystemClock.uptimeMillis();
mSupervisor.mWaitingActivityVisible.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (!outResult.timeout && outResult.who == null);
}
}
}
final ActivityRecord launchedActivity = mReusedActivity != null ? mReusedActivity : outRecord[0];
mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
return res;
}
}
use of android.app.IActivityContainer in project android_frameworks_base by crdroidandroid.
the class PendingIntentRecord method sendInner.
int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
if (intent != null)
intent.setDefusable(true);
if (options != null)
options.setDefusable(true);
if (whitelistDuration > 0 && !canceled) {
// Must call before acquiring the lock. It's possible the method return before sending
// the intent due to some validations inside the lock, in which case the UID shouldn't
// be whitelisted, but since the whitelist is temporary, that would be ok.
owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid, whitelistDuration);
}
synchronized (owner) {
final ActivityContainer activityContainer = (ActivityContainer) container;
if (activityContainer != null && activityContainer.mParentActivity != null && activityContainer.mParentActivity.state != ActivityStack.ActivityState.RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
if (!canceled) {
sent = true;
if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) {
owner.cancelIntentSenderLocked(this, true);
canceled = true;
}
Intent finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent();
final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
if (!immutable) {
if (intent != null) {
int changes = finalIntent.fillIn(intent, key.flags);
if ((changes & Intent.FILL_IN_DATA) == 0) {
resolvedType = key.requestResolvedType;
}
} else {
resolvedType = key.requestResolvedType;
}
flagsMask &= ~Intent.IMMUTABLE_FLAGS;
flagsValues &= flagsMask;
finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
} else {
resolvedType = key.requestResolvedType;
}
final long origId = Binder.clearCallingIdentity();
boolean sendFinish = finishedReceiver != null;
int userId = key.userId;
if (userId == UserHandle.USER_CURRENT) {
userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
}
int res = 0;
switch(key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
if (options == null) {
options = key.options;
} else if (key.options != null) {
Bundle opts = new Bundle(key.options);
opts.putAll(options);
options = opts;
}
try {
if (key.allIntents != null && key.allIntents.length > 1) {
Intent[] allIntents = new Intent[key.allIntents.length];
String[] allResolvedTypes = new String[key.allIntents.length];
System.arraycopy(key.allIntents, 0, allIntents, 0, key.allIntents.length);
if (key.allResolvedTypes != null) {
System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, key.allResolvedTypes.length);
}
allIntents[allIntents.length - 1] = finalIntent;
allResolvedTypes[allResolvedTypes.length - 1] = resolvedType;
owner.startActivitiesInPackage(uid, key.packageName, allIntents, allResolvedTypes, resultTo, options, userId);
} else {
owner.startActivityInPackage(uid, key.packageName, finalIntent, resolvedType, resultTo, resultWho, requestCode, 0, options, userId, container, null);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
}
break;
case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
if (key.activity.task.stack != null) {
key.activity.task.stack.sendActivityResultLocked(-1, key.activity, key.who, key.requestCode, code, finalIntent);
}
break;
case ActivityManager.INTENT_SENDER_BROADCAST:
try {
// If a completion callback has been requested, require
// that the broadcast be delivered synchronously
int sent = owner.broadcastIntentInPackage(key.packageName, uid, finalIntent, resolvedType, finishedReceiver, code, null, null, requiredPermission, options, (finishedReceiver != null), false, userId);
if (sent == ActivityManager.BROADCAST_SUCCESS) {
sendFinish = false;
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
}
break;
case ActivityManager.INTENT_SENDER_SERVICE:
try {
owner.startServiceInPackage(uid, finalIntent, resolvedType, key.packageName, userId);
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startService intent", e);
} catch (TransactionTooLargeException e) {
res = ActivityManager.START_CANCELED;
}
break;
}
if (sendFinish && res != ActivityManager.START_CANCELED) {
try {
finishedReceiver.performReceive(new Intent(finalIntent), 0, null, null, false, false, key.userId);
} catch (RemoteException e) {
}
}
Binder.restoreCallingIdentity(origId);
return res;
}
}
return ActivityManager.START_CANCELED;
}
Aggregations