| /* |
| * 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.cts.verifier.managedprovisioning; |
| |
| import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME; |
| import static android.app.admin.DevicePolicyManager.MAKE_USER_EPHEMERAL; |
| import static android.app.admin.DevicePolicyManager.SKIP_SETUP_WIZARD; |
| |
| import android.Manifest; |
| import android.app.Activity; |
| import android.app.KeyguardManager; |
| import android.app.PendingIntent; |
| import android.app.admin.DevicePolicyManager; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageInstaller; |
| import android.content.pm.PackageManager; |
| import android.content.pm.ResolveInfo; |
| import android.graphics.BitmapFactory; |
| import android.net.ProxyInfo; |
| import android.os.Bundle; |
| import android.os.PersistableBundle; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.provider.ContactsContract; |
| import android.provider.MediaStore; |
| import android.provider.Settings; |
| import android.util.Log; |
| import android.view.inputmethod.InputMethodInfo; |
| import android.view.inputmethod.InputMethodManager; |
| import android.widget.Toast; |
| |
| import com.android.bedstead.dpmwrapper.TestAppSystemServiceFactory; |
| import com.android.cts.verifier.R; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.concurrent.TimeUnit; |
| import java.util.stream.Collectors; |
| |
| public class CommandReceiverActivity extends Activity { |
| private static final String TAG = "CommandReceiverActivity"; |
| |
| public static final String ACTION_EXECUTE_COMMAND = |
| "com.android.cts.verifier.managedprovisioning.action.EXECUTE_COMMAND"; |
| public static final String EXTRA_COMMAND = |
| "com.android.cts.verifier.managedprovisioning.extra.COMMAND"; |
| |
| public static final String COMMAND_SET_USER_RESTRICTION = "set-user_restriction"; |
| public static final String COMMAND_DISALLOW_KEYGUARD_UNREDACTED_NOTIFICATIONS = |
| "disallow-keyguard-unredacted-notifications"; |
| public static final String COMMAND_SET_AUTO_TIME_REQUIRED = "set-auto-time-required"; |
| public static final String COMMAND_SET_GLOBAL_SETTING = |
| "set-global-setting"; |
| public static final String COMMAND_SET_MAXIMUM_TO_LOCK = "set-maximum-time-to-lock"; |
| public static final String COMMAND_SET_KEYGUARD_DISABLED = "set-keyguard-disabled"; |
| public static final String COMMAND_SET_LOCK_SCREEN_INFO = "set-lock-screen-info"; |
| public static final String COMMAND_SET_STATUSBAR_DISABLED = "set-statusbar-disabled"; |
| public static final String COMMAND_SET_LOCK_TASK_FEATURES = "set-lock-task-features"; |
| public static final String COMMAND_ALLOW_ONLY_SYSTEM_INPUT_METHODS = |
| "allow-only-system-input-methods"; |
| public static final String COMMAND_ALLOW_ONLY_SYSTEM_ACCESSIBILITY_SERVICES = |
| "allow-only-system-accessibility-services"; |
| public static final String COMMAND_CLEAR_POLICIES = "clear-policies"; |
| public static final String COMMAND_REMOVE_DEVICE_OWNER = "remove-device-owner"; |
| public static final String COMMAND_REQUEST_BUGREPORT = "request-bugreport"; |
| public static final String COMMAND_SET_USER_ICON = "set-user-icon"; |
| public static final String COMMAND_RETRIEVE_NETWORK_LOGS = "retrieve-network-logs"; |
| public static final String COMMAND_RETRIEVE_SECURITY_LOGS = "retrieve-security-logs"; |
| public static final String COMMAND_SET_ORGANIZATION_NAME = "set-organization-name"; |
| public static final String COMMAND_ENABLE_NETWORK_LOGGING = "enable-network-logging"; |
| public static final String COMMAND_DISABLE_NETWORK_LOGGING = "disable-network-logging"; |
| public static final String COMMAND_INSTALL_HELPER_PACKAGE = "install-helper-package"; |
| public static final String COMMAND_UNINSTALL_HELPER_PACKAGE = "uninstall-helper-package"; |
| public static final String COMMAND_SET_PERMISSION_GRANT_STATE = "set-permission-grant-state"; |
| public static final String COMMAND_ADD_PERSISTENT_PREFERRED_ACTIVITIES = |
| "add-persistent-preferred-activities"; |
| public static final String COMMAND_CLEAR_PERSISTENT_PREFERRED_ACTIVITIES = |
| "clear-persistent-preferred-activities"; |
| public static final String COMMAND_CREATE_MANAGED_PROFILE = "create-managed-profile"; |
| public static final String COMMAND_REMOVE_MANAGED_PROFILE = "remove-managed-profile"; |
| public static final String COMMAND_SET_ALWAYS_ON_VPN = "set-always-on-vpn"; |
| public static final String COMMAND_CLEAR_ALWAYS_ON_VPN = "clear-always-on-vpn"; |
| public static final String COMMAND_SET_GLOBAL_HTTP_PROXY = "set-global-http-proxy"; |
| public static final String COMMAND_CLEAR_GLOBAL_HTTP_PROXY = "clear-global-http-proxy"; |
| public static final String COMMAND_INSTALL_CA_CERT = "install-ca-cert"; |
| public static final String COMMAND_CLEAR_CA_CERT = "clear-ca-cert"; |
| public static final String COMMAND_SET_MAXIMUM_PASSWORD_ATTEMPTS = |
| "set-maximum-password-attempts"; |
| public static final String COMMAND_CLEAR_MAXIMUM_PASSWORD_ATTEMPTS = |
| "clear-maximum-password-attempts"; |
| public static final String COMMAND_SET_DEFAULT_IME = "set-default-ime"; |
| public static final String COMMAND_CLEAR_DEFAULT_IME = "clear-default-ime"; |
| public static final String COMMAND_CREATE_MANAGED_USER = "create-managed-user"; |
| public static final String COMMAND_CREATE_MANAGED_USER_WITHOUT_SETUP = |
| "create-managed-user-without-setup"; |
| public static final String COMMAND_REMOVE_SECONDARY_USERS = "remove-secondary-users"; |
| public static final String COMMAND_WITH_USER_SWITCHER_MESSAGE = "with-user-switcher-message"; |
| public static final String COMMAND_WITHOUT_USER_SWITCHER_MESSAGE = |
| "without-user-switcher-message"; |
| public static final String COMMAND_ENABLE_LOGOUT = "enable-logout"; |
| public static final String COMMAND_DISABLE_USB_DATA_SIGNALING = "disable-usb-data-signaling"; |
| public static final String COMMAND_ENABLE_USB_DATA_SIGNALING = "enable-usb-data-signaling"; |
| public static final String COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY = |
| "set-required-password-complexity"; |
| |
| public static final String EXTRA_USER_RESTRICTION = |
| "com.android.cts.verifier.managedprovisioning.extra.USER_RESTRICTION"; |
| public static final String EXTRA_USE_CURRENT_USER_DPM = |
| "com.android.cts.verifier.managedprovisioning.extra.USE_CURRENT_USER_DPM"; |
| public static final String EXTRA_SETTING = |
| "com.android.cts.verifier.managedprovisioning.extra.SETTING"; |
| // This extra can be used along with a command extra to set policy to |
| // specify if that policy is enforced or not. |
| public static final String EXTRA_ENFORCED = |
| "com.android.cts.verifier.managedprovisioning.extra.ENFORCED"; |
| public static final String EXTRA_VALUE = |
| "com.android.cts.verifier.managedprovisioning.extra.VALUE"; |
| public static final String EXTRA_ORGANIZATION_NAME = |
| "com.android.cts.verifier.managedprovisioning.extra.ORGANIZATION_NAME"; |
| public static final String EXTRA_PERMISSION = |
| "com.android.cts.verifier.managedprovisioning.extra.PERMISSION"; |
| public static final String EXTRA_GRANT_STATE = |
| "com.android.cts.verifier.managedprovisioning.extra.GRANT_STATE"; |
| |
| // We care about installing and uninstalling only. It does not matter what apk is used. |
| // NotificationBot.apk is a good choice because it comes bundled with the CTS verifier. |
| protected static final String HELPER_APP_LOCATION = "/sdcard/NotificationBot.apk"; |
| protected static final String HELPER_APP_PKG = "com.android.cts.robot"; |
| |
| public static final String ACTION_INSTALL_COMPLETE = |
| "com.android.cts.verifier.managedprovisioning.action.ACTION_INSTALL_COMPLETE"; |
| public static final String ACTION_UNINSTALL_COMPLETE = |
| "com.android.cts.verifier.managedprovisioning.action.ACTION_UNINSTALL_COMPLETE"; |
| |
| /* |
| * The CA cert below is the content of cacert.pem as generated by: |
| * |
| * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem |
| */ |
| private static final String TEST_CA = |
| "-----BEGIN CERTIFICATE-----\n" + |
| "MIIDXTCCAkWgAwIBAgIJAK9Tl/F9V8kSMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n" + |
| "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n" + |
| "aWRnaXRzIFB0eSBMdGQwHhcNMTUwMzA2MTczMjExWhcNMjUwMzAzMTczMjExWjBF\n" + |
| "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n" + |
| "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + |
| "CgKCAQEAvItOutsE75WBTgTyNAHt4JXQ3JoseaGqcC3WQij6vhrleWi5KJ0jh1/M\n" + |
| "Rpry7Fajtwwb4t8VZa0NuM2h2YALv52w1xivql88zce/HU1y7XzbXhxis9o6SCI+\n" + |
| "oVQSbPeXRgBPppFzBEh3ZqYTVhAqw451XhwdA4Aqs3wts7ddjwlUzyMdU44osCUg\n" + |
| "kVg7lfPf9sTm5IoHVcfLSCWH5n6Nr9sH3o2ksyTwxuOAvsN11F/a0mmUoPciYPp+\n" + |
| "q7DzQzdi7akRG601DZ4YVOwo6UITGvDyuAAdxl5isovUXqe6Jmz2/myTSpAKxGFs\n" + |
| "jk9oRoG6WXWB1kni490GIPjJ1OceyQIDAQABo1AwTjAdBgNVHQ4EFgQUH1QIlPKL\n" + |
| "p2OQ/AoLOjKvBW4zK3AwHwYDVR0jBBgwFoAUH1QIlPKLp2OQ/AoLOjKvBW4zK3Aw\n" + |
| "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcMi4voMMJHeQLjtq8Oky\n" + |
| "Azpyk8moDwgCd4llcGj7izOkIIFqq/lyqKdtykVKUWz2bSHO5cLrtaOCiBWVlaCV\n" + |
| "DYAnnVLM8aqaA6hJDIfaGs4zmwz0dY8hVMFCuCBiLWuPfiYtbEmjHGSmpQTG6Qxn\n" + |
| "ZJlaK5CZyt5pgh5EdNdvQmDEbKGmu0wpCq9qjZImwdyAul1t/B0DrsWApZMgZpeI\n" + |
| "d2od0VBrCICB1K4p+C51D93xyQiva7xQcCne+TAnGNy9+gjQ/MyR8MRpwRLv5ikD\n" + |
| "u0anJCN8pXo6IMglfMAsoton1J6o5/ae5uhC6caQU8bNUsCK570gpNfjkzo6rbP0\n" + |
| "wQ==\n" + |
| "-----END CERTIFICATE-----"; |
| |
| private ComponentName mAdmin; |
| private DevicePolicyManager mDpm; |
| private UserManager mUm; |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| final Intent intent = getIntent(); |
| try { |
| // On phones, the test runs on user 0, which is the Device Owner, but on headless system |
| // user mode it runs in a different user. |
| // Most DPM operations must be set on device owner user, but a few - like adding user |
| // restrictions - must be set in the current user. |
| boolean forDeviceOwner = !intent.getBooleanExtra(EXTRA_USE_CURRENT_USER_DPM, false); |
| mDpm = TestAppSystemServiceFactory.getDevicePolicyManager(this, |
| DeviceAdminTestReceiver.class, forDeviceOwner); |
| |
| mUm = (UserManager) getSystemService(Context.USER_SERVICE); |
| mAdmin = DeviceAdminTestReceiver.getReceiverComponentName(); |
| final String command = intent.getStringExtra(EXTRA_COMMAND); |
| Log.i(TAG, "Command: " + command); |
| switch (command) { |
| case COMMAND_SET_USER_RESTRICTION: { |
| String restrictionKey = intent.getStringExtra(EXTRA_USER_RESTRICTION); |
| boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); |
| Log.i(TAG, "Setting '" + restrictionKey + "'=" + enforced |
| + " using " + mDpm + " for user " |
| + (forDeviceOwner ? UserHandle.SYSTEM : UserHandle.myUserId())); |
| if (enforced) { |
| mDpm.addUserRestriction(mAdmin, restrictionKey); |
| } else { |
| mDpm.clearUserRestriction(mAdmin, restrictionKey); |
| } |
| } break; |
| case COMMAND_DISALLOW_KEYGUARD_UNREDACTED_NOTIFICATIONS: { |
| boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); |
| mDpm.setKeyguardDisabledFeatures(mAdmin, enforced |
| ? DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS |
| : 0); |
| } break; |
| case COMMAND_SET_AUTO_TIME_REQUIRED: { |
| mDpm.setAutoTimeRequired(mAdmin, |
| intent.getBooleanExtra(EXTRA_ENFORCED, false)); |
| break; |
| } |
| case COMMAND_SET_LOCK_SCREEN_INFO: { |
| mDpm.setDeviceOwnerLockScreenInfo(mAdmin, intent.getStringExtra(EXTRA_VALUE)); |
| break; |
| } |
| case COMMAND_SET_MAXIMUM_TO_LOCK: { |
| final long timeInSeconds = Long.parseLong(intent.getStringExtra(EXTRA_VALUE)); |
| mDpm.setMaximumTimeToLock(mAdmin, |
| TimeUnit.SECONDS.toMillis(timeInSeconds) /* in milliseconds */); |
| } break; |
| case COMMAND_SET_KEYGUARD_DISABLED: { |
| boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); |
| KeyguardManager km = this.getSystemService(KeyguardManager.class); |
| if (km.isKeyguardSecure()) { |
| Toast.makeText(this, getString(R.string.device_owner_lockscreen_secure), |
| Toast.LENGTH_SHORT).show(); |
| } else { |
| mDpm.setKeyguardDisabled(mAdmin, enforced); |
| } |
| } break; |
| case COMMAND_SET_STATUSBAR_DISABLED: { |
| boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); |
| Log.d(TAG, "calling setStatusBarDisabled(" |
| + ComponentName.flattenToShortString(mAdmin) + ", " + enforced |
| + ") using " + mDpm + " on user " + UserHandle.myUserId()); |
| mDpm.setStatusBarDisabled(mAdmin, enforced); |
| } break; |
| case COMMAND_SET_LOCK_TASK_FEATURES: { |
| int flags = intent.getIntExtra(EXTRA_VALUE, |
| DevicePolicyManager.LOCK_TASK_FEATURE_NONE); |
| mDpm.setLockTaskFeatures(mAdmin, flags); |
| // If feature HOME is used, we need to allow the current launcher |
| if ((flags & LOCK_TASK_FEATURE_HOME) != 0) { |
| mDpm.setLockTaskPackages(mAdmin, |
| new String[] {getPackageName(), getCurrentLauncherPackage()}); |
| } else { |
| mDpm.setLockTaskPackages(mAdmin, new String[] {getPackageName()}); |
| } |
| } break; |
| case COMMAND_ALLOW_ONLY_SYSTEM_INPUT_METHODS: { |
| boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); |
| mDpm.setPermittedInputMethods(mAdmin, |
| enforced ? getEnabledNonSystemImes() : null); |
| } break; |
| case COMMAND_ALLOW_ONLY_SYSTEM_ACCESSIBILITY_SERVICES: { |
| boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); |
| mDpm.setPermittedAccessibilityServices(mAdmin, |
| enforced ? new ArrayList() : null); |
| } break; |
| case COMMAND_SET_GLOBAL_SETTING: { |
| final String setting = intent.getStringExtra(EXTRA_SETTING); |
| final String value = intent.getStringExtra(EXTRA_VALUE); |
| mDpm.setGlobalSetting(mAdmin, setting, value); |
| } break; |
| case COMMAND_REMOVE_DEVICE_OWNER: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| Log.e(TAG, COMMAND_REMOVE_DEVICE_OWNER + ": " + getPackageName() |
| + " is not DO for user " + UserHandle.myUserId()); |
| return; |
| } |
| clearAllPoliciesAndRestrictions(); |
| mDpm.clearDeviceOwnerApp(getPackageName()); |
| |
| // TODO(b/179100903): temporarily removing PO, should be done automatically |
| if (UserManager.isHeadlessSystemUserMode()) { |
| Log.i(TAG, "Disabling PO on user " + UserHandle.myUserId()); |
| DevicePolicyManager localDpm = getSystemService(DevicePolicyManager.class); |
| localDpm.clearProfileOwner(mAdmin); |
| } |
| |
| } break; |
| case COMMAND_REQUEST_BUGREPORT: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| final boolean bugreportStarted = mDpm.requestBugreport(mAdmin); |
| if (!bugreportStarted) { |
| Utils.showBugreportNotification(this, getString( |
| R.string.bugreport_already_in_progress), |
| Utils.BUGREPORT_NOTIFICATION_ID); |
| } |
| } break; |
| case COMMAND_CLEAR_POLICIES: { |
| int mode = intent.getIntExtra(PolicyTransparencyTestListActivity.EXTRA_MODE, |
| PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER); |
| if (mode == PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER) { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| clearAllPoliciesAndRestrictions(); |
| } else if (mode == PolicyTransparencyTestListActivity.MODE_MANAGED_PROFILE |
| || mode == PolicyTransparencyTestListActivity.MODE_MANAGED_USER) { |
| if (!mDpm.isProfileOwnerApp(getPackageName())) { |
| return; |
| } |
| clearProfileOwnerRelatedPoliciesAndRestrictions(mode); |
| } |
| // No policies need to be cleared for COMP at the moment. |
| } break; |
| case COMMAND_SET_USER_ICON: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| int iconRes = intent.getIntExtra(EXTRA_VALUE, |
| com.android.cts.verifier.R.drawable.icon); |
| mDpm.setUserIcon(mAdmin, BitmapFactory.decodeResource(getResources(), iconRes)); |
| } break; |
| case COMMAND_RETRIEVE_NETWORK_LOGS: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setNetworkLoggingEnabled(mAdmin, true); |
| mDpm.retrieveNetworkLogs(mAdmin, 0 /* batchToken */); |
| mDpm.setNetworkLoggingEnabled(mAdmin, false); |
| } break; |
| case COMMAND_RETRIEVE_SECURITY_LOGS: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setSecurityLoggingEnabled(mAdmin, true); |
| mDpm.retrieveSecurityLogs(mAdmin); |
| mDpm.setSecurityLoggingEnabled(mAdmin, false); |
| } break; |
| case COMMAND_SET_ORGANIZATION_NAME: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setOrganizationName(mAdmin, |
| intent.getStringExtra(EXTRA_ORGANIZATION_NAME)); |
| } break; |
| case COMMAND_ENABLE_NETWORK_LOGGING: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setNetworkLoggingEnabled(mAdmin, true); |
| } break; |
| case COMMAND_DISABLE_NETWORK_LOGGING: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setNetworkLoggingEnabled(mAdmin, false); |
| } break; |
| case COMMAND_INSTALL_HELPER_PACKAGE: { |
| installHelperPackage(); |
| } break; |
| case COMMAND_UNINSTALL_HELPER_PACKAGE: { |
| uninstallHelperPackage(); |
| } break; |
| case COMMAND_SET_PERMISSION_GRANT_STATE: { |
| mDpm.setPermissionGrantState(mAdmin, getPackageName(), |
| intent.getStringExtra(EXTRA_PERMISSION), |
| intent.getIntExtra(EXTRA_GRANT_STATE, |
| DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT)); |
| } break; |
| case COMMAND_ADD_PERSISTENT_PREFERRED_ACTIVITIES: { |
| final ComponentName componentName = |
| EnterprisePrivacyTestDefaultAppActivity.COMPONENT_NAME; |
| IntentFilter filter; |
| // Camera |
| filter = new IntentFilter(); |
| filter.addAction(MediaStore.ACTION_IMAGE_CAPTURE); |
| filter.addAction(MediaStore.ACTION_VIDEO_CAPTURE); |
| mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName); |
| // Map |
| filter = new IntentFilter(); |
| filter.addAction(Intent.ACTION_VIEW); |
| filter.addDataScheme("geo"); |
| mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName); |
| // E-mail |
| filter = new IntentFilter(); |
| filter.addAction(Intent.ACTION_SENDTO); |
| filter.addAction(Intent.ACTION_SEND); |
| filter.addAction(Intent.ACTION_SEND_MULTIPLE); |
| mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName); |
| // Calendar |
| filter = new IntentFilter(); |
| filter.addAction(Intent.ACTION_INSERT); |
| filter.addDataType("vnd.android.cursor.dir/event"); |
| mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName); |
| // Contacts |
| filter = new IntentFilter(); |
| filter.addAction(Intent.ACTION_PICK); |
| filter.addDataType(ContactsContract.Contacts.CONTENT_TYPE); |
| mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName); |
| // Dialer |
| filter = new IntentFilter(); |
| filter.addAction(Intent.ACTION_DIAL); |
| filter.addAction(Intent.ACTION_CALL); |
| mDpm.addPersistentPreferredActivity(mAdmin, filter, componentName); |
| getPackageManager().setComponentEnabledSetting(componentName, |
| PackageManager.COMPONENT_ENABLED_STATE_ENABLED, |
| PackageManager.DONT_KILL_APP); |
| } break; |
| case COMMAND_CLEAR_PERSISTENT_PREFERRED_ACTIVITIES: { |
| mDpm.clearPackagePersistentPreferredActivities(mAdmin, getPackageName()); |
| getPackageManager().setComponentEnabledSetting( |
| EnterprisePrivacyTestDefaultAppActivity.COMPONENT_NAME, |
| PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, |
| PackageManager.DONT_KILL_APP); |
| } break; |
| case COMMAND_SET_ALWAYS_ON_VPN: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setAlwaysOnVpnPackage(mAdmin, getPackageName(), |
| false /* lockdownEnabled */); |
| } break; |
| case COMMAND_CLEAR_ALWAYS_ON_VPN: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setAlwaysOnVpnPackage(mAdmin, null /* vpnPackage */, |
| false /* lockdownEnabled */); |
| } break; |
| case COMMAND_SET_GLOBAL_HTTP_PROXY: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setRecommendedGlobalProxy(mAdmin, |
| ProxyInfo.buildDirectProxy("example.com", 123)); |
| } break; |
| case COMMAND_CLEAR_GLOBAL_HTTP_PROXY: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setRecommendedGlobalProxy(mAdmin, null); |
| } break; |
| case COMMAND_INSTALL_CA_CERT: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.installCaCert(mAdmin, TEST_CA.getBytes()); |
| } break; |
| case COMMAND_CLEAR_CA_CERT: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.uninstallCaCert(mAdmin, TEST_CA.getBytes()); |
| } break; |
| case COMMAND_SET_MAXIMUM_PASSWORD_ATTEMPTS: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setMaximumFailedPasswordsForWipe(mAdmin, 100); |
| } break; |
| case COMMAND_CLEAR_MAXIMUM_PASSWORD_ATTEMPTS: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setMaximumFailedPasswordsForWipe(mAdmin, 0); |
| } break; |
| case COMMAND_SET_DEFAULT_IME: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setSecureSetting(mAdmin, Settings.Secure.DEFAULT_INPUT_METHOD, |
| getPackageName()); |
| } break; |
| case COMMAND_CLEAR_DEFAULT_IME: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setSecureSetting(mAdmin, Settings.Secure.DEFAULT_INPUT_METHOD, null); |
| } break; |
| case COMMAND_CREATE_MANAGED_USER:{ |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| PersistableBundle extras = new PersistableBundle(); |
| extras.putBoolean(DeviceAdminTestReceiver.EXTRA_MANAGED_USER_TEST, true); |
| UserHandle userHandle = mDpm.createAndManageUser(mAdmin, "managed user", mAdmin, |
| extras, |
| SKIP_SETUP_WIZARD | MAKE_USER_EPHEMERAL); |
| mDpm.setAffiliationIds(mAdmin, |
| Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID)); |
| mDpm.startUserInBackground(mAdmin, userHandle); |
| } break; |
| case COMMAND_CREATE_MANAGED_USER_WITHOUT_SETUP:{ |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| PersistableBundle extras = new PersistableBundle(); |
| extras.putBoolean(DeviceAdminTestReceiver.EXTRA_MANAGED_USER_TEST, true); |
| mDpm.createAndManageUser(mAdmin, "managed user", mAdmin, extras, /* flags */ 0); |
| } break; |
| case COMMAND_REMOVE_SECONDARY_USERS: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| for (UserHandle secondaryUser : mDpm.getSecondaryUsers(mAdmin)) { |
| mDpm.removeUser(mAdmin, secondaryUser); |
| } |
| } break; |
| case COMMAND_WITH_USER_SWITCHER_MESSAGE: { |
| createAndSwitchUserWithMessage("Start user session", "End user session"); |
| } break; |
| case COMMAND_WITHOUT_USER_SWITCHER_MESSAGE: { |
| createAndSwitchUserWithMessage(null, null); |
| } break; |
| case COMMAND_ENABLE_LOGOUT: { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.addUserRestriction(mAdmin, UserManager.DISALLOW_USER_SWITCH); |
| mDpm.setLogoutEnabled(mAdmin, true); |
| UserHandle userHandle = mDpm.createAndManageUser(mAdmin, "managed user", mAdmin, |
| null, SKIP_SETUP_WIZARD | MAKE_USER_EPHEMERAL); |
| mDpm.switchUser(mAdmin, userHandle); |
| } break; |
| case COMMAND_DISABLE_USB_DATA_SIGNALING: { |
| mDpm.setUsbDataSignalingEnabled(false); |
| break; |
| } |
| case COMMAND_ENABLE_USB_DATA_SIGNALING: { |
| mDpm.setUsbDataSignalingEnabled(true); |
| break; |
| } |
| case COMMAND_SET_REQUIRED_PASSWORD_COMPLEXITY: { |
| int complexity = intent.getIntExtra(EXTRA_VALUE, |
| DevicePolicyManager.PASSWORD_COMPLEXITY_NONE); |
| mDpm.setRequiredPasswordComplexity(complexity); |
| } |
| } |
| } catch (Exception e) { |
| Log.e(TAG, "Failed to execute command: " + intent, e); |
| } finally { |
| finish(); |
| } |
| } |
| |
| private void installHelperPackage() throws Exception { |
| LogAndSelfUnregisterBroadcastReceiver.register(this, ACTION_INSTALL_COMPLETE); |
| final PackageInstaller packageInstaller = getPackageManager().getPackageInstaller(); |
| final PackageInstaller.Session session = packageInstaller.openSession( |
| packageInstaller.createSession(new PackageInstaller.SessionParams( |
| PackageInstaller.SessionParams.MODE_FULL_INSTALL))); |
| final File file = new File(HELPER_APP_LOCATION); |
| Log.i(TAG, "installing helper package from " + file); |
| final InputStream in = new FileInputStream(file); |
| final OutputStream out = session.openWrite("CommandReceiverActivity", 0, file.length()); |
| final byte[] buffer = new byte[65536]; |
| int count; |
| while ((count = in.read(buffer)) != -1) { |
| out.write(buffer, 0, count); |
| } |
| session.fsync(out); |
| in.close(); |
| out.close(); |
| session.commit(PendingIntent |
| .getBroadcast(this, 0, new Intent(ACTION_INSTALL_COMPLETE), |
| PendingIntent.FLAG_MUTABLE_UNAUDITED) |
| .getIntentSender()); |
| } |
| |
| private void uninstallHelperPackage() { |
| LogAndSelfUnregisterBroadcastReceiver.register(this, ACTION_UNINSTALL_COMPLETE); |
| PackageInstaller packageInstaller = getPackageManager().getPackageInstaller(); |
| Log.i(TAG, "Uninstalling package " + HELPER_APP_PKG + " using " + packageInstaller); |
| try { |
| packageInstaller.uninstall(HELPER_APP_PKG, PendingIntent.getBroadcast(this, |
| /* requestCode= */ 0, new Intent(ACTION_UNINSTALL_COMPLETE), |
| PendingIntent.FLAG_MUTABLE_UNAUDITED).getIntentSender()); |
| } catch (IllegalArgumentException e) { |
| // The package is not installed: that's fine |
| } |
| } |
| |
| private void clearAllPoliciesAndRestrictions() throws Exception { |
| clearProfileOwnerRelatedPolicies(); |
| clearPolicyTransparencyUserRestriction( |
| PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER); |
| |
| // There are a few user restrictions that are used, but not for policy transparency |
| mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_CONFIG_BLUETOOTH); |
| mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_CONFIG_VPN); |
| mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_DATA_ROAMING); |
| mDpm.clearUserRestriction(mAdmin, UserManager.DISALLOW_USER_SWITCH); |
| |
| mDpm.setDeviceOwnerLockScreenInfo(mAdmin, null); |
| mDpm.setKeyguardDisabled(mAdmin, false); |
| mDpm.setAutoTimeRequired(mAdmin, false); |
| mDpm.setStatusBarDisabled(mAdmin, false); |
| mDpm.setOrganizationName(mAdmin, null); |
| mDpm.setNetworkLoggingEnabled(mAdmin, false); |
| mDpm.setSecurityLoggingEnabled(mAdmin, false); |
| mDpm.setPermissionGrantState(mAdmin, getPackageName(), |
| Manifest.permission.ACCESS_FINE_LOCATION, |
| DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT); |
| mDpm.setPermissionGrantState(mAdmin, getPackageName(), Manifest.permission.RECORD_AUDIO, |
| DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT); |
| mDpm.setPermissionGrantState(mAdmin, getPackageName(), Manifest.permission.CAMERA, |
| DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT); |
| mDpm.clearPackagePersistentPreferredActivities(mAdmin, getPackageName()); |
| mDpm.setAlwaysOnVpnPackage(mAdmin, null, false); |
| mDpm.setRecommendedGlobalProxy(mAdmin, null); |
| mDpm.uninstallCaCert(mAdmin, TEST_CA.getBytes()); |
| mDpm.setMaximumFailedPasswordsForWipe(mAdmin, 0); |
| mDpm.setSecureSetting(mAdmin, Settings.Secure.DEFAULT_INPUT_METHOD, null); |
| mDpm.setStartUserSessionMessage(mAdmin, null); |
| mDpm.setEndUserSessionMessage(mAdmin, null); |
| mDpm.setLogoutEnabled(mAdmin, false); |
| |
| uninstallHelperPackage(); |
| |
| // Must wait until package is uninstalled to reset affiliation ids, otherwise the package |
| // cannot be removed on headless system user mode (as caller must be an affiliated PO) |
| mDpm.setAffiliationIds(mAdmin, Collections.emptySet()); |
| |
| removeManagedProfile(); |
| getPackageManager().setComponentEnabledSetting( |
| EnterprisePrivacyTestDefaultAppActivity.COMPONENT_NAME, |
| PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, |
| PackageManager.DONT_KILL_APP); |
| } |
| |
| private void clearProfileOwnerRelatedPoliciesAndRestrictions(int mode) { |
| clearPolicyTransparencyUserRestriction(mode); |
| clearProfileOwnerRelatedPolicies(); |
| } |
| |
| private void clearProfileOwnerRelatedPolicies() { |
| mDpm.setKeyguardDisabledFeatures(mAdmin, 0); |
| mDpm.setPasswordQuality(mAdmin, 0); |
| mDpm.setMaximumTimeToLock(mAdmin, 0); |
| mDpm.setPermittedAccessibilityServices(mAdmin, null); |
| mDpm.setPermittedInputMethods(mAdmin, null); |
| } |
| |
| private void clearPolicyTransparencyUserRestriction(int mode) { |
| for (String userRestriction : UserRestrictions.getUserRestrictionsForPolicyTransparency( |
| mode)) { |
| mDpm.clearUserRestriction(mAdmin, userRestriction); |
| } |
| } |
| |
| private void removeManagedProfile() { |
| for (final UserHandle userHandle : mUm.getUserProfiles()) { |
| mDpm.removeUser(mAdmin, userHandle); |
| } |
| } |
| |
| /** |
| * Creates an intent to set the given user restriction using the device owner's {@code dpm}. |
| */ |
| public static Intent createSetDeviceOwnerUserRestrictionIntent(String restriction, |
| boolean enforced) { |
| return createSetUserRestrictionIntent(restriction, enforced, /* currentUserDpm= */ false); |
| } |
| |
| /** |
| * Creates an intent to set the given user restriction using the current user's {@code dpm}. |
| */ |
| public static Intent createSetCurrentUserRestrictionIntent(String restriction, |
| boolean enforced) { |
| return createSetUserRestrictionIntent(restriction, enforced, /* currentUserDpm= */ true); |
| } |
| |
| private static Intent createSetUserRestrictionIntent(String restriction, boolean enforced, |
| boolean forceCurrentUserDpm) { |
| Intent intent = new Intent(ACTION_EXECUTE_COMMAND); |
| if (forceCurrentUserDpm) { |
| intent.putExtra(EXTRA_USE_CURRENT_USER_DPM, true); |
| } |
| return intent |
| .putExtra(EXTRA_COMMAND, COMMAND_SET_USER_RESTRICTION) |
| .putExtra(EXTRA_USER_RESTRICTION, restriction) |
| .putExtra(EXTRA_ENFORCED, enforced); |
| } |
| |
| private List<String> getEnabledNonSystemImes() { |
| InputMethodManager inputMethodManager = getSystemService(InputMethodManager.class); |
| final List<InputMethodInfo> inputMethods = inputMethodManager.getEnabledInputMethodList(); |
| return inputMethods.stream() |
| .filter(inputMethodInfo -> !isSystemInputMethodInfo(inputMethodInfo)) |
| .map(inputMethodInfo -> inputMethodInfo.getPackageName()) |
| .filter(packageName -> !packageName.equals(getPackageName())) |
| .distinct() |
| .collect(Collectors.toList()); |
| } |
| |
| private boolean isSystemInputMethodInfo(InputMethodInfo inputMethodInfo) { |
| final ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo; |
| return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; |
| } |
| |
| private void createAndSwitchUserWithMessage(String startUserSessionMessage, |
| String endUserSessionMessage) { |
| if (!mDpm.isDeviceOwnerApp(getPackageName())) { |
| return; |
| } |
| mDpm.setStartUserSessionMessage(mAdmin, startUserSessionMessage); |
| mDpm.setEndUserSessionMessage(mAdmin, endUserSessionMessage); |
| mDpm.setAffiliationIds(mAdmin, |
| Collections.singleton(DeviceAdminTestReceiver.AFFILIATION_ID)); |
| |
| PersistableBundle extras = new PersistableBundle(); |
| extras.putBoolean(DeviceAdminTestReceiver.EXTRA_LOGOUT_ON_START, true); |
| UserHandle userHandle = mDpm.createAndManageUser(mAdmin, "managed user", mAdmin, |
| extras, |
| SKIP_SETUP_WIZARD | MAKE_USER_EPHEMERAL); |
| mDpm.switchUser(mAdmin, userHandle); |
| } |
| |
| private String getCurrentLauncherPackage() { |
| ResolveInfo resolveInfo = getPackageManager() |
| .resolveActivity(new Intent(Intent.ACTION_MAIN) |
| .addCategory(Intent.CATEGORY_HOME), PackageManager.MATCH_DEFAULT_ONLY); |
| if (resolveInfo == null || resolveInfo.activityInfo == null) { |
| return null; |
| } |
| |
| return resolveInfo.activityInfo.packageName; |
| } |
| } |