1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.bedstead.nene.devicepolicy; 18 19 import static android.cts.testapisreflection.TestApisReflectionKt.setProfileOwnerOnOrganizationOwnedDevice; 20 import static android.cts.testapisreflection.TestApisReflectionKt.forceRemoveActiveAdmin; 21 import static android.cts.testapisreflection.TestApisReflectionKt.isRemovingAdmin; 22 import static android.cts.testapisreflection.TestApisReflectionKt.setDeviceOwnerType; 23 import static android.os.Build.VERSION_CODES.R; 24 import static android.os.Build.VERSION_CODES.TIRAMISU; 25 26 import static com.android.bedstead.permissions.CommonPermissions.MANAGE_PROFILE_AND_DEVICE_OWNERS; 27 28 import android.annotation.TargetApi; 29 import android.app.admin.DevicePolicyManager; 30 import android.content.ComponentName; 31 import android.os.Build; 32 33 import com.android.bedstead.nene.TestApis; 34 import com.android.bedstead.nene.exceptions.AdbException; 35 import com.android.bedstead.nene.exceptions.NeneException; 36 import com.android.bedstead.nene.packages.Package; 37 import com.android.bedstead.nene.users.UserReference; 38 import com.android.bedstead.nene.utils.Poll; 39 import com.android.bedstead.nene.utils.ShellCommand; 40 import com.android.bedstead.nene.utils.ShellCommandUtils; 41 import com.android.bedstead.nene.utils.Versions; 42 import com.android.bedstead.permissions.PermissionContext; 43 44 import java.util.Objects; 45 46 /** 47 * A reference to a Profile Owner. 48 */ 49 public final class ProfileOwner extends DevicePolicyController { 50 ProfileOwner(UserReference user, Package pkg, ComponentName componentName)51 ProfileOwner(UserReference user, 52 Package pkg, 53 ComponentName componentName) { 54 super(user, pkg, componentName); 55 } 56 57 /** Returns whether the current profile is organization owned. */ 58 @TargetApi(R) isOrganizationOwned()59 public boolean isOrganizationOwned() { 60 if (!Versions.meetsMinimumSdkVersionRequirement(R)) { 61 return false; 62 } 63 64 DevicePolicyManager devicePolicyManager = 65 TestApis.context().androidContextAsUser(mUser).getSystemService( 66 DevicePolicyManager.class); 67 return devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile(); 68 } 69 70 /** Sets whether the current profile is organization owned. */ 71 @TargetApi(TIRAMISU) setIsOrganizationOwned(boolean isOrganizationOwned)72 public void setIsOrganizationOwned(boolean isOrganizationOwned) { 73 if (isOrganizationOwned() == isOrganizationOwned) { 74 return; // Nothing to do 75 } 76 77 Versions.requireMinimumVersion(TIRAMISU); 78 79 DevicePolicyManager devicePolicyManager = 80 TestApis.context().androidContextAsUser(mUser).getSystemService( 81 DevicePolicyManager.class); 82 83 UserReference user = TestApis.users().system(); 84 boolean userSetupComplete = user.getSetupComplete(); 85 try { 86 user.setSetupComplete(false); 87 88 try (PermissionContext p = TestApis.permissions().withPermission( 89 MANAGE_PROFILE_AND_DEVICE_OWNERS)) { 90 setProfileOwnerOnOrganizationOwnedDevice( 91 devicePolicyManager, mComponentName, isOrganizationOwned); 92 } 93 } finally { 94 user.setSetupComplete(userSetupComplete); 95 } 96 } 97 98 @Override remove()99 public void remove() { 100 if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S) 101 || TestApis.packages().instrumented().isInstantApp()) { 102 removePreS(); 103 return; 104 } 105 106 DevicePolicyManager devicePolicyManager = 107 TestApis.context().androidContextAsUser(mUser).getSystemService( 108 DevicePolicyManager.class); 109 110 try (PermissionContext p = 111 TestApis.permissions().withPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)) { 112 forceRemoveActiveAdmin(devicePolicyManager, mComponentName, mUser.id()); 113 } catch (SecurityException e) { 114 if (e.getMessage().contains("Attempt to remove non-test admin") 115 && TEST_APP_APP_COMPONENT_FACTORY.equals(mPackage.appComponentFactory()) 116 && user().parent() == null) { 117 removeTestApp(); 118 } else { 119 throw e; 120 } 121 } 122 123 Poll.forValue("Profile Owner", 124 () -> TestApis.devicePolicy().getProfileOwner(mUser)) 125 .toBeNull() 126 .errorOnFail().await(); 127 } 128 removePreS()129 private void removePreS() { 130 try { 131 ShellCommand.builderForUser(mUser, "dpm remove-active-admin") 132 .addOperand(componentName().flattenToShortString()) 133 .validate(ShellCommandUtils::startsWithSuccess) 134 .execute(); 135 } catch (AdbException e) { 136 if (TEST_APP_APP_COMPONENT_FACTORY.equals(mPackage.appComponentFactory()) 137 && user().parent() == null) { 138 // We can't see why it failed so we'll try the test app version 139 removeTestApp(); 140 } else { 141 throw new NeneException("Error removing profile owner " + this, e); 142 } 143 } 144 } 145 146 @Override toString()147 public String toString() { 148 StringBuilder stringBuilder = new StringBuilder("ProfileOwner{"); 149 stringBuilder.append("user=").append(user()); 150 stringBuilder.append(", package=").append(pkg()); 151 stringBuilder.append(", componentName=").append(componentName()); 152 stringBuilder.append("}"); 153 154 return stringBuilder.toString(); 155 } 156 157 @Override equals(Object obj)158 public boolean equals(Object obj) { 159 if (!(obj instanceof ProfileOwner)) { 160 return false; 161 } 162 163 ProfileOwner other = (ProfileOwner) obj; 164 165 return Objects.equals(other.mUser, mUser) 166 && Objects.equals(other.mPackage, mPackage) 167 && Objects.equals(other.mComponentName, mComponentName); 168 } 169 } 170