Merge "Support FBE for managed profiles." into nyc-dev am: 716a9e1892
am: 86dd0f2a9b
* commit '86dd0f2a9b907f2f8a9cdce2fc7f052916778cd7':
Support FBE for managed profiles.
This commit is contained in:
@@ -8515,6 +8515,7 @@ package android.content {
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
|
||||
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
|
||||
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
|
||||
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
|
||||
|
||||
@@ -8821,6 +8821,7 @@ package android.content {
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
|
||||
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
|
||||
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
|
||||
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
|
||||
|
||||
@@ -8520,6 +8520,7 @@ package android.content {
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
|
||||
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
|
||||
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
|
||||
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
|
||||
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
|
||||
|
||||
@@ -3027,6 +3027,17 @@ public class Intent implements Parcelable, Cloneable {
|
||||
public static final String ACTION_MANAGED_PROFILE_REMOVED =
|
||||
"android.intent.action.MANAGED_PROFILE_REMOVED";
|
||||
|
||||
/**
|
||||
* Broadcast sent to the primary user when the credential-encrypted private storage for
|
||||
* an associated managed profile is unlocked. Carries an extra {@link #EXTRA_USER} that
|
||||
* specifies the UserHandle of the profile that was unlocked. Only applications (for example
|
||||
* Launchers) that need to display merged content across both primary and managed profiles
|
||||
* need to worry about this broadcast. This is only sent to registered receivers,
|
||||
* not manifest receivers.
|
||||
*/
|
||||
public static final String ACTION_MANAGED_PROFILE_UNLOCKED =
|
||||
"android.intent.action.MANAGED_PROFILE_UNLOCKED";
|
||||
|
||||
/**
|
||||
* Broadcast sent to the primary user when an associated managed profile's availability has
|
||||
* changed. This includes when the user toggles the profile's quiet mode. Carries an extra
|
||||
|
||||
@@ -4210,6 +4210,11 @@
|
||||
<!-- Notification detail shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
|
||||
<string name="user_encrypted_detail">User data locked</string>
|
||||
|
||||
<!-- Notification detail shown when work profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
|
||||
<string name="profile_encrypted_detail">Work profile locked</string>
|
||||
<!-- Notification message shown when work profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
|
||||
<string name="profile_encrypted_message">Tap to unlock work profile</string>
|
||||
|
||||
<!-- Title of notification shown after a MTP device is connected to Android. -->
|
||||
<string name="usb_mtp_launch_notification_title">Connected to <xliff:g id="product_name">%1$s</xliff:g></string>
|
||||
<!-- Description of notification shown after a MTP device is connected to Android. -->
|
||||
|
||||
@@ -2522,6 +2522,8 @@
|
||||
<java-symbol type="string" name="user_encrypted_title" />
|
||||
<java-symbol type="string" name="user_encrypted_message" />
|
||||
<java-symbol type="string" name="user_encrypted_detail" />
|
||||
<java-symbol type="string" name="profile_encrypted_detail" />
|
||||
<java-symbol type="string" name="profile_encrypted_message" />
|
||||
<java-symbol type="drawable" name="ic_user_secure" />
|
||||
|
||||
<java-symbol type="string" name="usb_mtp_launch_notification_title" />
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
@@ -34,6 +35,7 @@ import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
|
||||
import static android.content.Context.KEYGUARD_SERVICE;
|
||||
import static android.content.Context.USER_SERVICE;
|
||||
import static android.Manifest.permission.READ_CONTACTS;
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
|
||||
@@ -124,7 +126,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
@Override
|
||||
public void onBootPhase(int phase) {
|
||||
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
|
||||
mLockSettingsService.maybeShowEncryptionNotification(UserHandle.ALL);
|
||||
mLockSettingsService.maybeShowEncryptionNotifications();
|
||||
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
|
||||
// TODO
|
||||
}
|
||||
@@ -176,22 +178,48 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
* If the account is credential-encrypted, show notification requesting the user to unlock
|
||||
* the device.
|
||||
*/
|
||||
private void maybeShowEncryptionNotification(UserHandle userHandle) {
|
||||
if (UserHandle.ALL.equals(userHandle)) {
|
||||
final List<UserInfo> users = mUserManager.getUsers();
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
UserHandle user = users.get(i).getUserHandle();
|
||||
if (!mUserManager.isUserUnlocked(user)) {
|
||||
showEncryptionNotification(user);
|
||||
private void maybeShowEncryptionNotifications() {
|
||||
final List<UserInfo> users = mUserManager.getUsers();
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
UserInfo user = users.get(i);
|
||||
UserHandle userHandle = user.getUserHandle();
|
||||
if (!mUserManager.isUserUnlocked(userHandle)) {
|
||||
if (!user.isManagedProfile()) {
|
||||
showEncryptionNotification(userHandle);
|
||||
} else {
|
||||
UserInfo parent = mUserManager.getProfileParent(user.id);
|
||||
if (parent != null && mUserManager.isUserUnlocked(parent.getUserHandle())) {
|
||||
// Only show notifications for managed profiles once their parent
|
||||
// user is unlocked.
|
||||
showEncryptionNotificationForProfile(userHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!mUserManager.isUserUnlocked(userHandle)){
|
||||
showEncryptionNotification(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private void showEncryptionNotificationForProfile(UserHandle user) {
|
||||
Resources r = mContext.getResources();
|
||||
CharSequence title = r.getText(
|
||||
com.android.internal.R.string.user_encrypted_title);
|
||||
CharSequence message = r.getText(
|
||||
com.android.internal.R.string.profile_encrypted_message);
|
||||
CharSequence detail = r.getText(
|
||||
com.android.internal.R.string.profile_encrypted_detail);
|
||||
|
||||
final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
|
||||
final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, user.getIdentifier());
|
||||
if (unlockIntent == null) {
|
||||
return;
|
||||
}
|
||||
unlockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
|
||||
PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
showEncryptionNotification(user, title, message, detail, intent);
|
||||
}
|
||||
|
||||
private void showEncryptionNotification(UserHandle user) {
|
||||
if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
|
||||
Resources r = mContext.getResources();
|
||||
CharSequence title = r.getText(
|
||||
com.android.internal.R.string.user_encrypted_title);
|
||||
@@ -203,6 +231,12 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
PendingIntent intent = PendingIntent.getBroadcast(mContext, 0, ACTION_NULL,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
showEncryptionNotification(user, title, message, detail, intent);
|
||||
}
|
||||
|
||||
private void showEncryptionNotification(UserHandle user, CharSequence title, CharSequence message,
|
||||
CharSequence detail, PendingIntent intent) {
|
||||
if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
|
||||
Notification notification = new Notification.Builder(mContext)
|
||||
.setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
|
||||
.setWhen(0)
|
||||
@@ -230,8 +264,21 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
hideEncryptionNotification(new UserHandle(userId));
|
||||
}
|
||||
|
||||
public void onUnlockUser(int userHandle) {
|
||||
hideEncryptionNotification(new UserHandle(userHandle));
|
||||
public void onUnlockUser(int userId) {
|
||||
hideEncryptionNotification(new UserHandle(userId));
|
||||
|
||||
// Now we have unlocked the parent user we should show notifications
|
||||
// about any profiles that exist.
|
||||
List<UserInfo> profiles = mUserManager.getProfiles(userId);
|
||||
for (int i = 0; i < profiles.size(); i++) {
|
||||
UserInfo profile = profiles.get(i);
|
||||
if (profile.isManagedProfile()) {
|
||||
UserHandle userHandle = profile.getUserHandle();
|
||||
if (!mUserManager.isUserUnlocked(userHandle)) {
|
||||
showEncryptionNotificationForProfile(userHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
|
||||
@@ -1046,10 +1046,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
||||
}
|
||||
|
||||
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId) {
|
||||
return resolveIntent(intent, resolvedType, userId, 0);
|
||||
}
|
||||
|
||||
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
|
||||
try {
|
||||
return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
|
||||
PackageManager.MATCH_DEFAULT_ONLY
|
||||
| ActivityManagerService.STOCK_PM_FLAGS, userId);
|
||||
PackageManager.MATCH_DEFAULT_ONLY | flags
|
||||
| ActivityManagerService.STOCK_PM_FLAGS, userId);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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.server.am;
|
||||
|
||||
import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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.server.am;
|
||||
|
||||
import static android.app.Activity.RESULT_CANCELED;
|
||||
@@ -74,7 +90,9 @@ import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
@@ -84,6 +102,7 @@ import android.os.IBinder;
|
||||
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;
|
||||
@@ -582,6 +601,22 @@ class ActivityStarter {
|
||||
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);
|
||||
UserInfo parent = userManager.getProfileParent(userId);
|
||||
if (parent != null
|
||||
&& userManager.isUserUnlocked(parent.getUserHandle())
|
||||
&& !userManager.isUserUnlocked(userInfo.getUserHandle())) {
|
||||
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Collect information about the target of the Intent.
|
||||
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
|
||||
|
||||
|
||||
@@ -297,6 +297,22 @@ final class UserController {
|
||||
null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
|
||||
userId);
|
||||
|
||||
if (getUserInfo(userId).isManagedProfile()) {
|
||||
UserInfo parent = getUserManager().getProfileParent(userId);
|
||||
if (parent != null) {
|
||||
final Intent profileUnlockedIntent = new Intent(
|
||||
Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
|
||||
unlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
|
||||
unlockedIntent.addFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY
|
||||
| Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
mService.broadcastIntentLocked(null, null, profileUnlockedIntent,
|
||||
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
|
||||
null, false, false, MY_PID, SYSTEM_UID,
|
||||
parent.id);
|
||||
}
|
||||
}
|
||||
|
||||
final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
|
||||
bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
|
||||
bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
|
||||
|
||||
@@ -201,8 +201,7 @@ public class LauncherAppsService extends SystemService {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
|
||||
PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
|
||||
user.getIdentifier());
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
|
||||
return new ParceledListSlice<>(apps);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
@@ -220,7 +219,7 @@ public class LauncherAppsService extends SystemService {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
ResolveInfo app = mPm.resolveActivityAsUser(intent,
|
||||
PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
|
||||
return app;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
@@ -239,7 +238,7 @@ public class LauncherAppsService extends SystemService {
|
||||
try {
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
PackageInfo info = pm.getPackageInfo(packageName,
|
||||
PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
|
||||
return info != null && info.applicationInfo.enabled;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
@@ -277,7 +276,7 @@ public class LauncherAppsService extends SystemService {
|
||||
try {
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
ActivityInfo info = pm.getActivityInfo(component,
|
||||
PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
|
||||
return info != null;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
@@ -303,7 +302,7 @@ public class LauncherAppsService extends SystemService {
|
||||
try {
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
ActivityInfo info = pm.getActivityInfo(component,
|
||||
PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
|
||||
if (!info.exported) {
|
||||
throw new SecurityException("Cannot launch non-exported components "
|
||||
+ component);
|
||||
@@ -313,7 +312,7 @@ public class LauncherAppsService extends SystemService {
|
||||
// as calling startActivityAsUser ignores the category and just
|
||||
// resolves based on the component if present.
|
||||
List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
|
||||
PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
|
||||
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
|
||||
final int size = apps.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
ActivityInfo activityInfo = apps.get(i).activityInfo;
|
||||
|
||||
Reference in New Issue
Block a user