Search in sources :

Example 1 with IntentSender

use of android.content.IntentSender in project android_frameworks_base by ParanoidAndroid.

the class ActivityStack method startActivityMayWait.

final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config, Bundle options, int userId) {
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    boolean componentSpecified = intent.getComponent() != null;
    // Don't modify the client's object!
    intent = new Intent(intent);
    // Collect information about the target of the Intent.
    ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profileFile, profileFd, userId);
    synchronized (mService) {
        int callingPid;
        if (callingUid >= 0) {
            callingPid = -1;
        } else if (caller == null) {
            callingPid = Binder.getCallingPid();
            callingUid = Binder.getCallingUid();
        } else {
            callingPid = callingUid = -1;
        }
        mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
        if (DEBUG_CONFIGURATION)
            Slog.v(TAG, "Starting activity when config will change = " + mConfigWillChange);
        final long origId = Binder.clearCallingIdentity();
        if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
            // have another, different heavy-weight process running.
            if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
                if (mService.mHeavyWeightProcess != null && (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
                    int realCallingPid = callingPid;
                    int realCallingUid = callingUid;
                    if (caller != null) {
                        ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
                        if (callerApp != null) {
                            realCallingPid = callerApp.pid;
                            realCallingUid = callerApp.info.uid;
                        } else {
                            Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + realCallingPid + ") when starting: " + intent.toString());
                            ActivityOptions.abort(options);
                            return ActivityManager.START_PERMISSION_DENIED;
                        }
                    }
                    IIntentSender target = mService.getIntentSenderLocked(ActivityManager.INTENT_SENDER_ACTIVITY, "android", realCallingUid, 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 (mService.mHeavyWeightProcess.activities.size() > 0) {
                        ActivityRecord hist = mService.mHeavyWeightProcess.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;
                    try {
                        ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent(intent, null, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS, userId);
                        aInfo = rInfo != null ? rInfo.activityInfo : null;
                        aInfo = mService.getActivityInfoForUser(aInfo, userId);
                    } catch (RemoteException e) {
                        aInfo = null;
                    }
                }
            }
        }
        int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, startFlags, options, componentSpecified, null);
        if (mConfigWillChange && mMainStack) {
            // 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()");
            mConfigWillChange = false;
            if (DEBUG_CONFIGURATION)
                Slog.v(TAG, "Updating to new configuration after starting activity.");
            mService.updateConfigurationLocked(config, null, false, false);
        }
        Binder.restoreCallingIdentity(origId);
        if (outResult != null) {
            outResult.result = res;
            if (res == ActivityManager.START_SUCCESS) {
                mWaitingActivityLaunched.add(outResult);
                do {
                    try {
                        mService.wait();
                    } catch (InterruptedException e) {
                    }
                } while (!outResult.timeout && outResult.who == null);
            } else if (res == ActivityManager.START_TASK_TO_FRONT) {
                ActivityRecord r = this.topRunningActivityLocked(null);
                if (r.nowVisible) {
                    outResult.timeout = false;
                    outResult.who = new ComponentName(r.info.packageName, r.info.name);
                    outResult.totalTime = 0;
                    outResult.thisTime = 0;
                } else {
                    outResult.thisTime = SystemClock.uptimeMillis();
                    mWaitingActivityVisible.add(outResult);
                    do {
                        try {
                            mService.wait();
                        } catch (InterruptedException e) {
                        }
                    } while (!outResult.timeout && outResult.who == null);
                }
            }
        }
        return res;
    }
}
Also used : ActivityInfo(android.content.pm.ActivityInfo) HeavyWeightSwitcherActivity(com.android.internal.app.HeavyWeightSwitcherActivity) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) IIntentSender(android.content.IIntentSender) ResolveInfo(android.content.pm.ResolveInfo) ComponentName(android.content.ComponentName) IIntentSender(android.content.IIntentSender) IntentSender(android.content.IntentSender) RemoteException(android.os.RemoteException)

Example 2 with IntentSender

use of android.content.IntentSender 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;
    }
}
Also used : ActivityInfo(android.content.pm.ActivityInfo) Message(android.os.Message) HeavyWeightSwitcherActivity(com.android.internal.app.HeavyWeightSwitcherActivity) IActivityContainer(android.app.IActivityContainer) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) UserInfo(android.content.pm.UserInfo) ResolveInfo(android.content.pm.ResolveInfo) IIntentSender(android.content.IIntentSender) UserManager(android.os.UserManager) ComponentName(android.content.ComponentName) RemoteException(android.os.RemoteException) IntentSender(android.content.IntentSender) IIntentSender(android.content.IIntentSender) ActivityOptions(android.app.ActivityOptions)

Example 3 with IntentSender

use of android.content.IntentSender in project android_frameworks_base by ResurrectionRemix.

the class ActivityStarter method showConfirmDeviceCredential.

void showConfirmDeviceCredential(int userId) {
    // First, retrieve the stack that we want to resume after credential is confirmed.
    ActivityStack targetStack;
    ActivityStack fullscreenStack = mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
    ActivityStack freeformStack = mSupervisor.getStack(FREEFORM_WORKSPACE_STACK_ID);
    if (fullscreenStack != null && fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
        // Single window case and the case that the docked stack is shown with fullscreen stack.
        targetStack = fullscreenStack;
    } else if (freeformStack != null && freeformStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
        targetStack = freeformStack;
    } else {
        // The case that the docked stack is shown with recent.
        targetStack = mSupervisor.getStack(HOME_STACK_ID);
    }
    if (targetStack == null) {
        return;
    }
    final KeyguardManager km = (KeyguardManager) mService.mContext.getSystemService(Context.KEYGUARD_SERVICE);
    final Intent credential = km.createConfirmDeviceCredentialIntent(null, null, userId);
    // For safety, check null here in case users changed the setting after the checking.
    if (credential == null) {
        return;
    }
    final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
    if (activityRecord != null) {
        final IIntentSender target = mService.getIntentSenderLocked(ActivityManager.INTENT_SENDER_ACTIVITY, activityRecord.launchedFromPackage, activityRecord.launchedFromUid, activityRecord.userId, null, null, 0, new Intent[] { activityRecord.intent }, new String[] { activityRecord.resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null);
        credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
        // Show confirm credentials activity.
        startConfirmCredentialIntent(credential);
    }
}
Also used : IIntentSender(android.content.IIntentSender) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) IntentSender(android.content.IntentSender) IIntentSender(android.content.IIntentSender) KeyguardManager(android.app.KeyguardManager)

Example 4 with IntentSender

use of android.content.IntentSender in project android_frameworks_base by ResurrectionRemix.

the class ActivityStarter method buildEphemeralInstallerIntent.

/**
     * Builds and returns an intent to launch the ephemeral installer.
     */
private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent, String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
    final Intent nonEphemeralIntent = new Intent(origIntent);
    nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
    // Intent that is launched if the ephemeral package couldn't be installed
    // for any reason.
    final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null, /*token*/
    null, /*resultWho*/
    1, new Intent[] { nonEphemeralIntent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null);
    final Intent ephemeralIntent;
    if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
        // Force the intent to be directed to the ephemeral package
        ephemeralIntent = new Intent(origIntent);
        ephemeralIntent.setPackage(ephemeralPackage);
    } else {
        // Success intent goes back to the installer
        ephemeralIntent = new Intent(launchIntent);
    }
    // Intent that is eventually launched if the ephemeral package was
    // installed successfully. This will actually be launched by a platform
    // broadcast receiver.
    final IIntentSender successIntentTarget = mService.getIntentSenderLocked(ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, Binder.getCallingUid(), userId, null, /*token*/
    null, /*resultWho*/
    0, new Intent[] { ephemeralIntent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null);
    // Finally build the actual intent to launch the ephemeral installer
    int flags = launchIntent.getFlags();
    final Intent intent = new Intent();
    intent.setFlags(flags | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
    intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
    intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
    // TODO: Remove when the platform has fully implemented ephemeral apps
    intent.setData(origIntent.getData().buildUpon().clearQuery().build());
    return intent;
}
Also used : IIntentSender(android.content.IIntentSender) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) IntentSender(android.content.IntentSender) IIntentSender(android.content.IIntentSender)

Example 5 with IntentSender

use of android.content.IntentSender in project android_frameworks_base by ResurrectionRemix.

the class PrintManager method print.

/**
     * Creates a print job for printing a {@link PrintDocumentAdapter} with
     * default print attributes.
     * <p>
     * Calling this method brings the print UI allowing the user to customize
     * the print job and returns a {@link PrintJob} object without waiting for the
     * user to customize or confirm the print job. The returned print job instance
     * is in a {@link PrintJobInfo#STATE_CREATED created} state.
     * <p>
     * This method can be called only from an {@link Activity}. The rationale is that
     * printing from a service will create an inconsistent user experience as the print
     * UI would appear without any context.
     * </p>
     * <p>
     * Also the passed in {@link PrintDocumentAdapter} will be considered invalid if
     * your activity is finished. The rationale is that once the activity that
     * initiated printing is finished, the provided adapter may be in an inconsistent
     * state as it may depend on the UI presented by the activity.
     * </p>
     * <p>
     * The default print attributes are a hint to the system how the data is to
     * be printed. For example, a photo editor may look at the photo aspect ratio
     * to determine the default orientation and provide a hint whether the printing
     * should be in portrait or landscape. The system will do a best effort to
     * selected the hinted options in the print dialog, given the current printer
     * supports them.
     * </p>
     * <p>
     * <strong>Note:</strong> Calling this method will bring the print dialog and
     * the system will connect to the provided {@link PrintDocumentAdapter}. If a
     * configuration change occurs that you application does not handle, for example
     * a rotation change, the system will drop the connection to the adapter as the
     * activity has to be recreated and the old adapter may be invalid in this context,
     * hence a new adapter instance is required. As a consequence, if your activity
     * does not handle configuration changes (default behavior), you have to save the
     * state that you were printing and call this method again when your activity
     * is recreated.
     * </p>
     *
     * @param printJobName A name for the new print job which is shown to the user.
     * @param documentAdapter An adapter that emits the document to print.
     * @param attributes The default print job attributes or <code>null</code>.
     * @return The created print job on success or null on failure.
     * @throws IllegalStateException If not called from an {@link Activity}.
     * @throws IllegalArgumentException If the print job name is empty or the
     * document adapter is null.
     *
     * @see PrintJob
     */
@NonNull
public PrintJob print(@NonNull String printJobName, @NonNull PrintDocumentAdapter documentAdapter, @Nullable PrintAttributes attributes) {
    if (mService == null) {
        Log.w(LOG_TAG, "Feature android.software.print not available");
        return null;
    }
    if (!(mContext instanceof Activity)) {
        throw new IllegalStateException("Can print only from an activity");
    }
    if (TextUtils.isEmpty(printJobName)) {
        throw new IllegalArgumentException("printJobName cannot be empty");
    }
    if (documentAdapter == null) {
        throw new IllegalArgumentException("documentAdapter cannot be null");
    }
    PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate((Activity) mContext, documentAdapter);
    try {
        Bundle result = mService.print(printJobName, delegate, attributes, mContext.getPackageName(), mAppId, mUserId);
        if (result != null) {
            PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB);
            IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT);
            if (printJob == null || intent == null) {
                return null;
            }
            try {
                mContext.startIntentSender(intent, null, 0, 0, 0);
                return new PrintJob(printJob, this);
            } catch (SendIntentException sie) {
                Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
            }
        }
    } catch (RemoteException re) {
        throw re.rethrowFromSystemServer();
    }
    return null;
}
Also used : Bundle(android.os.Bundle) Activity(android.app.Activity) IntentSender(android.content.IntentSender) RemoteException(android.os.RemoteException) SendIntentException(android.content.IntentSender.SendIntentException) NonNull(android.annotation.NonNull)

Aggregations

IntentSender (android.content.IntentSender)94 Intent (android.content.Intent)48 IIntentSender (android.content.IIntentSender)46 PendingIntent (android.app.PendingIntent)40 RemoteException (android.os.RemoteException)30 UserHandle (android.os.UserHandle)14 ActivityOptions (android.app.ActivityOptions)13 KeyguardManager (android.app.KeyguardManager)10 UserInfo (android.content.pm.UserInfo)10 Bundle (android.os.Bundle)10 IActivityManager (android.app.IActivityManager)8 ComponentName (android.content.ComponentName)8 ActivityInfo (android.content.pm.ActivityInfo)8 ResolveInfo (android.content.pm.ResolveInfo)8 HeavyWeightSwitcherActivity (com.android.internal.app.HeavyWeightSwitcherActivity)8 AccountManager (android.accounts.AccountManager)7 Activity (android.app.Activity)7 PackageManager (android.content.pm.PackageManager)7 Point (android.graphics.Point)7 SpannableStringBuilder (android.text.SpannableStringBuilder)7