--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+/**
+ * A dialog shown to the user when they try to launch an app from a quiet profile
+ * ({@link UserManager#isQuietModeEnabled(UserHandle)}, or when the app is suspended by the
+ * profile owner or device owner.
+ */
+public class UnlaunchableAppActivity extends Activity
+ implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
+ private static final String TAG = "UnlaunchableAppActivity";
+
+ private static final int UNLAUNCHABLE_REASON_QUIET_MODE = 1;
+ private static final int UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE = 2;
+ private static final String EXTRA_UNLAUNCHABLE_REASON = "unlaunchable_reason";
+
+ private int mUserId;
+ private int mReason;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = getIntent();
+ mReason = intent.getIntExtra(EXTRA_UNLAUNCHABLE_REASON, -1);
+ mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+
+ if (mUserId == UserHandle.USER_NULL) {
+ Log.wtf(TAG, "Invalid user id: " + mUserId + ". Stopping.");
+ finish();
+ return;
+ }
+
+ String dialogTitle;
+ String dialogMessage;
+ if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) {
+ dialogTitle = getResources().getString(R.string.work_mode_off_title);
+ dialogMessage = getResources().getString(R.string.work_mode_off_message);
+ } else if (mReason == UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE) {
+ PackageManager pm = getPackageManager();
+ DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ String packageLabel = packageName;
+ try {
+ Context userContext = createPackageContextAsUser(packageName, 0,
+ UserHandle.of(mUserId));
+ ApplicationInfo appInfo = userContext.getApplicationInfo();
+ if (appInfo != null) {
+ packageLabel = userContext.getPackageManager().getApplicationLabel(appInfo)
+ .toString();
+ }
+ } catch (NameNotFoundException e) {
+ }
+ dialogTitle = String.format(getResources().getString(R.string.suspended_package_title),
+ packageLabel);
+ dialogMessage = dpm.getShortSupportMessageForUser(dpm.getProfileOwnerAsUser(mUserId),
+ mUserId);
+ if (dialogMessage == null) {
+ dialogMessage = String.format(
+ getResources().getString(R.string.suspended_package_message),
+ dpm.getProfileOwnerNameAsUser(mUserId));
+ }
+ } else {
+ Log.wtf(TAG, "Invalid unlaunchable type: " + mReason);
+ finish();
+ return;
+ }
+
+ View rootView = LayoutInflater.from(this).inflate(R.layout.unlaunchable_app_activity, null);
+ TextView titleView = (TextView)rootView.findViewById(R.id.unlaunchable_app_title);
+ TextView messageView = (TextView)rootView.findViewById(R.id.unlaunchable_app_message);
+ titleView.setText(dialogTitle);
+ messageView.setText(dialogMessage);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ .setView(rootView)
+ .setOnDismissListener(this);
+ if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) {
+ builder.setPositiveButton(R.string.work_mode_turn_on, this)
+ .setNegativeButton(R.string.cancel, null);
+ } else {
+ builder.setPositiveButton(R.string.ok, null);
+ }
+ builder.show();
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
+ UserManager.get(this).setQuietModeEnabled(mUserId, false);
+ }
+ }
+
+ private static final Intent createBaseIntent() {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName("android", UnlaunchableAppActivity.class.getName()));
+ intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ return intent;
+ }
+
+ public static Intent createInQuietModeDialogIntent(int userId) {
+ Intent intent = createBaseIntent();
+ intent.putExtra(EXTRA_UNLAUNCHABLE_REASON, UNLAUNCHABLE_REASON_QUIET_MODE);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ return intent;
+ }
+
+ public static Intent createPackageSuspendedDialogIntent(String packageName, int userId) {
+ Intent intent = createBaseIntent();
+ intent.putExtra(EXTRA_UNLAUNCHABLE_REASON, UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+ return intent;
+ }
+}
</intent-filter>
</activity>
+ <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
+ android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
<receiver android:name="com.android.server.BootReceiver"
android:systemUserOnly="true">
<intent-filter android:priority="1000">
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/dialog_padding"
+ android:orientation="vertical">
+ <TextView android:id="@+id/unlaunchable_app_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/dialog_padding"
+ android:paddingBottom="@dimen/dialog_padding"
+ android:textAppearance="@android:style/TextAppearance.Material.Title" />
+
+ <TextView android:id="@+id/unlaunchable_app_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/dialog_padding"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorSecondary" />
+</LinearLayout>
+
<!-- Menu item in the locale menu [CHAR LIMIT=30] -->
<string name="locale_search_menu">Search</string>
+ <!-- Title for dialog displayed when work profile is turned off. [CHAR LIMIT=30] -->
+ <string name="work_mode_off_title">Work mode is OFF</string>
+ <!-- Message displayed in dialog when work profile is turned off. [CHAR LIMIT=NONE] -->
+ <string name="work_mode_off_message">Allow work profile to function, including apps, background sync, and related features.</string>
+ <!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] -->
+ <string name="work_mode_turn_on">Turn on</string>
+ <!-- Title for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=30] -->
+ <string name="suspended_package_title">%1$s disabled</string>
+ <!-- Message for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=NONE] -->
+ <string name="suspended_package_message">Disabled by %1$s administrator. Contact them to learn more.</string>
</resources>
<java-symbol type="string" name="language_selection_title" />
<java-symbol type="string" name="search_language_hint" />
+ <java-symbol type="layout" name="unlaunchable_app_activity" />
+ <java-symbol type="id" name="unlaunchable_app_title" />
+ <java-symbol type="id" name="unlaunchable_app_message" />
+ <java-symbol type="string" name="work_mode_off_title" />
+ <java-symbol type="string" name="work_mode_off_message" />
+ <java-symbol type="string" name="work_mode_turn_on" />
+ <java-symbol type="string" name="suspended_package_title" />
+ <java-symbol type="string" name="suspended_package_message" />
</resources>
--- /dev/null
+package com.android.server.am;
+
+import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.app.PendingIntent.FLAG_ONE_SHOT;
+import static android.content.Context.KEYGUARD_SERVICE;
+import static android.content.Intent.EXTRA_INTENT;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_TASK_ID;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
+
+import android.app.KeyguardManager;
+import android.content.IIntentSender;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.os.Binder;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import com.android.internal.app.UnlaunchableAppActivity;
+
+/**
+ * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked}
+ * It's initialized
+ */
+class ActivityStartInterceptor {
+
+ private final ActivityManagerService mService;
+ private UserManager mUserManager;
+ private final ActivityStackSupervisor mSupervisor;
+
+ /*
+ * Per-intent states loaded from ActivityStarter than shouldn't be changed by any
+ * interception routines.
+ */
+ private int mRealCallingPid;
+ private int mRealCallingUid;
+ private int mUserId;
+ private int mStartFlags;
+ private String mCallingPackage;
+
+ /*
+ * Per-intent states that were load from ActivityStarter and are subject to modifications
+ * by the interception routines. After calling {@link #intercept} the caller should assign
+ * these values back to {@link ActivityStarter#startActivityLocked}'s local variables.
+ */
+ Intent mIntent;
+ int mCallingPid;
+ int mCallingUid;
+ ResolveInfo mRInfo;
+ ActivityInfo mAInfo;
+ String mResolvedType;
+ TaskRecord mInTask;
+
+ ActivityStartInterceptor(ActivityManagerService service, ActivityStackSupervisor supervisor) {
+ mService = service;
+ mSupervisor = supervisor;
+ }
+
+ void setStates(int userId, int realCallingPid, int realCallingUid, int startFlags,
+ String callingPackage) {
+ mRealCallingPid = realCallingPid;
+ mRealCallingUid = realCallingUid;
+ mUserId = userId;
+ mStartFlags = startFlags;
+ mCallingPackage = callingPackage;
+ }
+
+ void intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
+ TaskRecord inTask, int callingPid, int callingUid) {
+ mUserManager = UserManager.get(mService.mContext);
+ mIntent = intent;
+ mCallingPid = callingPid;
+ mCallingUid = callingUid;
+ mRInfo = rInfo;
+ mAInfo = aInfo;
+ mResolvedType = resolvedType;
+ mInTask = inTask;
+ interceptQuietProfileIfNeeded();
+ interceptSuspendPackageIfNeed();
+ interceptWorkProfileChallengeIfNeeded();
+ }
+
+ private void interceptQuietProfileIfNeeded() {
+ // Do not intercept if the user has not turned off the profile
+ if (!mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))) {
+ return;
+ }
+ mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId);
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+
+ final UserInfo parent = mUserManager.getProfileParent(mUserId);
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
+ null /*profilerInfo*/);
+ }
+
+ private void interceptSuspendPackageIfNeed() {
+ // Do not intercept if the admin did not suspend the package
+ if (mAInfo == null || mAInfo.applicationInfo == null ||
+ (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
+ return;
+ }
+ mIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(mAInfo.packageName,
+ mUserId);
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+
+ final UserInfo parent = mUserManager.getProfileParent(mUserId);
+ if (parent != null) {
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
+ } else {
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId);
+ }
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
+ null /*profilerInfo*/);
+ }
+
+ private void interceptWorkProfileChallengeIfNeeded() {
+ final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mIntent,
+ mResolvedType, mAInfo, mCallingPackage, mUserId);
+ if (interceptingIntent == null) {
+ return;
+ }
+ mIntent = interceptingIntent;
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+ // If we are intercepting and there was a task, convert it into an extra for the
+ // ConfirmCredentials intent and unassign it, as otherwise the task will move to
+ // front even if ConfirmCredentials is cancelled.
+ if (mInTask != null) {
+ mIntent.putExtra(EXTRA_TASK_ID, mInTask.taskId);
+ mInTask = null;
+ }
+
+ final UserInfo parent = mUserManager.getProfileParent(mUserId);
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
+ null /*profilerInfo*/);
+ }
+
+ /**
+ * Creates an intent to intercept the current activity start with Confirm Credentials if needed.
+ *
+ * @return The intercepting intent if needed.
+ */
+ private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType,
+ ActivityInfo aInfo, String callingPackage, int userId) {
+ if (!mService.mUserController.shouldConfirmCredentials(userId)) {
+ return null;
+ }
+ final IIntentSender target = mService.getIntentSenderLocked(
+ INTENT_SENDER_ACTIVITY, callingPackage,
+ Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
+ new String[]{ resolvedType },
+ FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE, null);
+ final int flags = intent.getFlags();
+ final KeyguardManager km = (KeyguardManager) mService.mContext
+ .getSystemService(KEYGUARD_SERVICE);
+ final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
+ if (newIntent == null) {
+ return null;
+ }
+ newIntent.setFlags(flags | FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ newIntent.putExtra(EXTRA_PACKAGE_NAME, aInfo.packageName);
+ newIntent.putExtra(EXTRA_INTENT, new IntentSender(target));
+ return newIntent;
+ }
+
+}
package com.android.server.am;
import static android.app.Activity.RESULT_CANCELED;
-import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
-import static android.app.ActivityManager.START_PERMISSION_DENIED;
import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
-import static android.app.PendingIntent.FLAG_IMMUTABLE;
-import static android.app.PendingIntent.FLAG_ONE_SHOT;
-import static android.content.Context.KEYGUARD_SERVICE;
-import static android.content.Intent.EXTRA_INTENT;
-import static android.content.Intent.EXTRA_PACKAGE_NAME;
-import static android.content.Intent.EXTRA_TASK_ID;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
-import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
-import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import android.app.IActivityContainer;
import android.app.IActivityManager;
import android.app.IApplicationThread;
-import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.os.UserManager;
import android.service.voice.IVoiceInteractionSession;
import android.util.EventLog;
import android.util.Slog;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mSupervisor;
+ private ActivityStartInterceptor mInterceptor;
private WindowManagerService mWindowManager;
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
mService = service;
mSupervisor = supervisor;
+ mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
}
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
}
}
- if (aInfo != null) {
- if ((aInfo.applicationInfo.flags & FLAG_SUSPENDED) != 0) {
- Slog.w(TAG, "Application \"" + aInfo.applicationInfo.packageName
- + "\" is suspended. Refusing to start: " + intent.toString());
- // TODO: show a dialog/activity informing the user that the application is suspended
- // and redirect the launch to it. Do not return START_PERMISSION_DENIED because
- // it is wrong.
- err = ActivityManager.START_PERMISSION_DENIED;
- }
- }
-
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
}
}
- final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(intent,
- resolvedType, aInfo, callingPackage, userId);
- if (interceptingIntent != null) {
- intent = interceptingIntent;
- callingPid = realCallingPid;
- callingUid = realCallingUid;
- resolvedType = null;
- // If we are intercepting and there was a task, convert it into an extra for the
- // ConfirmCredentials intent and unassign it, as otherwise the task will move to
- // front even if ConfirmCredentials is cancelled.
- if (inTask != null) {
- intent.putExtra(EXTRA_TASK_ID, inTask.taskId);
- inTask = null;
- }
-
- final UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
- rInfo = mSupervisor.resolveIntent(intent, resolvedType, parent.id);
- aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
- null /*profilerInfo*/);
- }
+ mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
+ mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid);
+ intent = mInterceptor.mIntent;
+ rInfo = mInterceptor.mRInfo;
+ aInfo = mInterceptor.mAInfo;
+ resolvedType = mInterceptor.mResolvedType;
+ inTask = mInterceptor.mInTask;
+ callingPid = mInterceptor.mCallingPid;
+ callingUid = mInterceptor.mCallingUid;
if (abort) {
if (resultRecord != null) {
return err;
}
- /**
- * Creates an intent to intercept the current activity start with Confirm Credentials if needed.
- *
- * @return The intercepting intent if needed.
- */
- private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType,
- ActivityInfo aInfo, String callingPackage, int userId) {
- if (!mService.mUserController.shouldConfirmCredentials(userId)) {
- return null;
- }
- final IIntentSender target = mService.getIntentSenderLocked(
- INTENT_SENDER_ACTIVITY, callingPackage,
- Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
- new String[]{ resolvedType },
- FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE, null);
- final int flags = intent.getFlags();
- final KeyguardManager km = (KeyguardManager) mService.mContext
- .getSystemService(KEYGUARD_SERVICE);
- final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
- if (newIntent == null) {
- return null;
- }
- newIntent.setFlags(flags | FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- newIntent.putExtra(EXTRA_PACKAGE_NAME, aInfo.packageName);
- newIntent.putExtra(EXTRA_INTENT, new IntentSender(target));
- return newIntent;
- }
-
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,