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 package com.android.compatibility.common.util.enterprise; 17 18 import android.app.admin.DevicePolicyManager; 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.util.Log; 23 24 /** 25 * Helper class for {@link android.app.admin.DeviceAdminReceiver} implementations. 26 */ 27 public final class DeviceAdminReceiverUtils { 28 29 private static final String TAG = DeviceAdminReceiverUtils.class.getSimpleName(); 30 private static final boolean DEBUG = false; 31 32 private static final String ACTION_DISABLE_SELF = "disable_self"; 33 34 /** 35 * Disables itself as profile / owner upon receiving a {@value #ACTION_DISABLE_SELF} intent. 36 * 37 * <p>This is useful during {@code CTS} development, so the admin can be disabled without a 38 * factory reset, when for some reason the test fails to disable it. 39 * 40 * <p>Typical usage: 41 * <pre><code> 42 public void onReceive(Context context, Intent intent) { 43 if (DeviceAdminReceiverUtils.disableSelf(context, intent)) return; 44 super.onReceive(context, intent); 45 } 46 * </code></pre> 47 * 48 * <p>Then {@code adb shell am broadcast --user USER -a disable_self PACKAGE/RECEIVER}. 49 * <b>Note:</b> caller needs the {@code BIND_DEVICE_ADMIN} permission, so you need to call 50 * {@code adb root} first. 51 * 52 * @return whether the intent was processed or not. 53 */ disableSelf(Context context, Intent intent)54 public static boolean disableSelf(Context context, Intent intent) { 55 String action = intent.getAction(); 56 int userId = context.getUserId(); 57 if (!action.equals(ACTION_DISABLE_SELF)) { 58 if (DEBUG) Log.d(TAG, "Ignoring " + action + " for user " + userId); 59 return false; 60 } 61 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 62 String packageName = context.getPackageName(); 63 if (dpm.isDeviceOwnerApp(packageName)) { 64 Log.i(TAG, "Disabling " + packageName + " as device owner for user " + userId); 65 dpm.clearDeviceOwnerApp(packageName); 66 if (DEBUG) Log.d(TAG, "Disabled"); 67 } else if (dpm.isProfileOwnerApp(packageName)) { 68 ComponentName admin = dpm.getProfileOwner(); 69 Log.i(TAG, "Disabling " + admin.flattenToShortString() + " as profile owner for user " 70 + userId); 71 dpm.clearProfileOwner(admin); 72 if (DEBUG) Log.d(TAG, "Disabled"); 73 } else { 74 Log.e(TAG, "Package " + packageName + " is neither device nor profile owner for user " 75 + userId); 76 } 77 return true; 78 } 79 DeviceAdminReceiverUtils()80 private DeviceAdminReceiverUtils() { 81 throw new UnsupportedOperationException("contains only static methods"); 82 } 83 } 84