Merge "Trigger policy check when profile turned on with apps suspended" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-05-01 10:48:07 +00:00
committed by Android (Google) Code Review
3 changed files with 318 additions and 308 deletions

View File

@@ -22,6 +22,7 @@ import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
@@ -409,6 +410,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION =
"com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
/** Broadcast action invoked when the user taps a notification to turn the profile on. */
@VisibleForTesting
static final String ACTION_TURN_PROFILE_ON_NOTIFICATION =
"com.android.server.ACTION_TURN_PROFILE_ON_NOTIFICATION";
/** Broadcast action for tracking managed profile maximum time off. */
@VisibleForTesting
static final String ACTION_PROFILE_OFF_DEADLINE =
"com.android.server.ACTION_PROFILE_OFF_DEADLINE";
@@ -951,7 +958,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
if (isManagedProfile(userHandle)) {
Slog.d(LOG_TAG, "Managed profile became unlocked");
updatePersonalAppsSuspension(userHandle, true /* unlocked */);
if (updatePersonalAppsSuspension(userHandle, true /* unlocked */)
== PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT) {
triggerPolicyComplianceCheck(userHandle);
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
handlePackagesChanged(null /* check all admins */, userHandle);
@@ -982,6 +992,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} else {
Slog.wtf(LOG_TAG, "Got deadline alarm for nonexistent profile");
}
} else if (ACTION_TURN_PROFILE_ON_NOTIFICATION.equals(action)) {
Slog.i(LOG_TAG, "requesting to turn on the profile: " + userHandle);
mUserManager.requestQuietModeEnabled(false, UserHandle.of(userHandle));
}
}
@@ -2568,6 +2581,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
filter.addAction(ACTION_TURN_PROFILE_ON_NOTIFICATION);
filter.addAction(ACTION_PROFILE_OFF_DEADLINE);
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_REMOVED);
@@ -15950,14 +15964,29 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.write();
}
/** Starts an activity to check policy compliance in the DPC. */
private void triggerPolicyComplianceCheck(int profileUserId) {
final Intent intent = new Intent(ACTION_CHECK_POLICY_COMPLIANCE);
synchronized (getLockObject()) {
final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(profileUserId);
if (profileOwner == null) {
Slog.wtf(LOG_TAG, "Profile owner not found for compliance check");
return;
}
intent.setPackage(profileOwner.info.getPackageName());
}
mContext.startActivityAsUser(intent, UserHandle.of(profileUserId));
}
/**
* Checks whether personal apps should be suspended according to the policy and applies the
* change if needed.
*
* @param unlocked whether the profile is currently running unlocked.
*/
private void updatePersonalAppsSuspension(int profileUserId, boolean unlocked) {
final boolean suspended;
private @PersonalAppsSuspensionReason int updatePersonalAppsSuspension(
int profileUserId, boolean unlocked) {
final boolean suspendedExplicitly;
final int deadlineState;
final String poPackage;
synchronized (getLockObject()) {
@@ -15965,26 +15994,28 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (profileOwner != null) {
deadlineState =
updateProfileOffDeadlineLocked(profileUserId, profileOwner, unlocked);
suspended = profileOwner.mSuspendPersonalApps
|| deadlineState == PROFILE_OFF_DEADLINE_REACHED;
suspendedExplicitly = profileOwner.mSuspendPersonalApps;
poPackage = profileOwner.info.getPackageName();
} else {
poPackage = null;
suspended = false;
suspendedExplicitly = false;
deadlineState = PROFILE_OFF_DEADLINE_DEFAULT;
}
}
Slog.d(LOG_TAG, String.format("Personal apps suspended: %b, deadline state: %d",
suspended, deadlineState));
Slog.d(LOG_TAG, String.format("Personal apps suspended explicitly: %b, deadline state: %d",
suspendedExplicitly, deadlineState));
if (poPackage != null) {
final int notificationState = unlocked ? PROFILE_OFF_DEADLINE_DEFAULT : deadlineState;
updateProfileOffDeadlineNotification(profileUserId, poPackage, notificationState);
}
final boolean suspendedByTimeout = deadlineState == PROFILE_OFF_DEADLINE_REACHED;
final int parentUserId = getProfileParentId(profileUserId);
suspendPersonalAppsInternal(parentUserId, suspended);
suspendPersonalAppsInternal(parentUserId, suspendedExplicitly || suspendedByTimeout);
return makeSuspensionReasons(suspendedExplicitly, suspendedByTimeout);
}
/**
@@ -16044,8 +16075,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final AlarmManager am = mInjector.getAlarmManager();
final Intent intent = new Intent(ACTION_PROFILE_OFF_DEADLINE);
intent.setPackage(mContext.getPackageName());
final PendingIntent pi = mInjector.pendingIntentGetBroadcast(
mContext, REQUEST_PROFILE_OFF_DEADLINE, new Intent(ACTION_PROFILE_OFF_DEADLINE),
mContext, REQUEST_PROFILE_OFF_DEADLINE, intent,
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
if (alarmTime == 0) {
@@ -16094,23 +16127,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
final Intent intent = new Intent(DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE);
intent.setPackage(profileOwnerPackage);
final Intent intent = new Intent(ACTION_TURN_PROFILE_ON_NOTIFICATION);
intent.setPackage(mContext.getPackageName());
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
final PendingIntent pendingIntent = mInjector.pendingIntentGetActivityAsUser(mContext,
0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT,
null /* options */, UserHandle.of(profileUserId));
final PendingIntent pendingIntent = mInjector.pendingIntentGetBroadcast(mContext,
0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// TODO(b/149075510): Only the first of the notifications should be dismissible.
final String text = mContext.getString(
notificationState == PROFILE_OFF_DEADLINE_WARNING
? R.string.personal_apps_suspension_tomorrow_text
: R.string.personal_apps_suspension_text);
final boolean ongoing = notificationState == PROFILE_OFF_DEADLINE_REACHED;
final Notification notification =
new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
.setSmallIcon(android.R.drawable.stat_sys_warning)
.setOngoing(true)
.setOngoing(ongoing)
.setContentTitle(mContext.getString(
R.string.personal_apps_suspension_title))
.setContentText(text)

View File

@@ -482,4 +482,9 @@ public class DpmMockContext extends MockContext {
public int checkCallingPermission(String permission) {
return spiedContext.checkCallingPermission(permission);
}
@Override
public void startActivityAsUser(Intent intent, UserHandle userHandle) {
spiedContext.startActivityAsUser(intent, userHandle);
}
}