1d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse/* 2d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Copyright 2014, The Android Open Source Project 3d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * 4d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Licensed under the Apache License, Version 2.0 (the "License"); 5d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * you may not use this file except in compliance with the License. 6d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * You may obtain a copy of the License at 7d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * 8d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * http://www.apache.org/licenses/LICENSE-2.0 9d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * 10d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Unless required by applicable law or agreed to in writing, software 11d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * distributed under the License is distributed on an "AS IS" BASIS, 12d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * See the License for the specific language governing permissions and 14d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * limitations under the License. 15d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse */ 16d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 17d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnsepackage com.android.managedprovisioning; 18d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 1984e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.app.admin.DevicePolicyManager; 20a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.content.BroadcastReceiver; 219a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.ComponentName; 220b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.Context; 239a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.Intent; 240b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.ActivityInfo; 25d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.ApplicationInfo; 26d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.IPackageManager; 270b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageInfo; 28d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.PackageManager; 290b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageManager.NameNotFoundException; 3084e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.content.pm.UserInfo; 319a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.graphics.drawable.Drawable; 32a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.os.AsyncTask; 3384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.os.Binder; 34a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.os.Bundle; 35d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.RemoteException; 36d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.ServiceManager; 37d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfinoimport android.os.UserHandle; 3884e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.os.UserManager; 39a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.provider.Settings.Global; 40a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.provider.Settings.Secure; 410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.text.TextUtils; 423efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnseimport android.util.Base64; 43d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 44a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport java.io.IOException; 45d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.HashSet; 469a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport java.util.List; 47d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.Set; 48d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 499a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME; 509a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME; 519a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 52a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.accounts.Account; 53a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.accounts.AccountManager; 54a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.accounts.AccountManagerFuture; 55a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.accounts.AuthenticatorException; 56a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.accounts.OperationCanceledException; 57a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 58d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse/** 59d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Class containing various auxiliary methods. 60d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse */ 61d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnsepublic class Utils { 629a42f2b64dada715248aec7c898f983375a395eeAlan Treadway private Utils() {} 639a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 64d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse public static Set<String> getCurrentSystemApps(int userId) { 65d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse IPackageManager ipm = IPackageManager.Stub.asInterface(ServiceManager 66d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse .getService("package")); 67d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse Set<String> apps = new HashSet<String>(); 68d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse List<ApplicationInfo> aInfos = null; 69d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse try { 70d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse aInfos = ipm.getInstalledApplications( 71d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse PackageManager.GET_UNINSTALLED_PACKAGES, userId).getList(); 72d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (RemoteException neverThrown) { 73d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.loge("This should not happen.", neverThrown); 74d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 75d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse for (ApplicationInfo aInfo : aInfos) { 76d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 77d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse apps.add(aInfo.packageName); 78d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 79d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 80d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse return apps; 81d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 82d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 83d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse public static void disableComponent(ComponentName toDisable, int userId) { 84d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse try { 85d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse IPackageManager ipm = IPackageManager.Stub.asInterface(ServiceManager 86d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse .getService("package")); 87d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 88d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ipm.setComponentEnabledSetting(toDisable, 89d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP, 90d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse userId); 91d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (RemoteException neverThrown) { 92d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.loge("This should not happen.", neverThrown); 93d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (Exception e) { 94d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.logw("Component not found, not disabling it: " 95d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse + toDisable.toShortString()); 96d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 97d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 980b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 990b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot /** 1000b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Exception thrown when the provisioning has failed completely. 1010b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1020b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * We're using a custom exception to avoid catching subsequent exceptions that might be 1030b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * significant. 1040b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot */ 1050b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot public static class IllegalProvisioningArgumentException extends Exception { 1060b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot public IllegalProvisioningArgumentException(String message) { 1070b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot super(message); 1080b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1090b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 1100b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot public IllegalProvisioningArgumentException(String message, Throwable t) { 1110b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot super(message, t); 1120b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1130b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1140b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 1150b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot /** 1160b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check the validity of the admin component name supplied, or try to infer this componentName 1170b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * from the package. 1180b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1190b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * We are supporting lookup by package name for legacy reasons. 1200b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1210b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * If mdmComponentName is supplied (not null): 1220b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * mdmPackageName is ignored. 1230b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check that the package of mdmComponentName is installed, that mdmComponentName is a 1240b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * receiver in this package, and return it. 1250b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1260b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Otherwise: 1270b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * mdmPackageName must be supplied (not null). 1280b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check that this package is installed, try to infer a potential device admin in this package, 1290b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * and return it. 1300b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot */ 1310b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot public static ComponentName findDeviceAdmin(String mdmPackageName, 1320b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ComponentName mdmComponentName, Context c) throws IllegalProvisioningArgumentException { 1330b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 1340b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot mdmPackageName = mdmComponentName.getPackageName(); 1350b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1360b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmPackageName == null) { 1370b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("Neither the package name nor the" 1380b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " component name of the admin are supplied"); 1390b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1400b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot PackageInfo pi; 1410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot try { 1420b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot pi = c.getPackageManager().getPackageInfo(mdmPackageName, 1430b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot PackageManager.GET_RECEIVERS); 1440b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } catch (NameNotFoundException e) { 1450b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("Mdm "+ mdmPackageName 1460b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " is not installed. ", e); 1470b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1480b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 1490b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot // If the component was specified in the intent: check that it is in the manifest. 1500b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot checkAdminComponent(mdmComponentName, pi); 1510b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return mdmComponentName; 1520b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } else { 1530b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot // Otherwise: try to find a potential device admin in the manifest. 1540b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return findDeviceAdminInPackage(mdmPackageName, pi); 1550b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1560b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1570b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 1580b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot private static void checkAdminComponent(ComponentName mdmComponentName, PackageInfo pi) 1590b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throws IllegalProvisioningArgumentException{ 1600b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot for (ActivityInfo ai : pi.receivers) { 1610b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName.getClassName().equals(ai.name)) { 1620b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return; 1630b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1640b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1650b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("The component " + mdmComponentName 1660b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " cannot be found"); 1670b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1680b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 1690b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot private static ComponentName findDeviceAdminInPackage(String mdmPackageName, PackageInfo pi) 1700b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throws IllegalProvisioningArgumentException { 1710b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ComponentName mdmComponentName = null; 1720b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot for (ActivityInfo ai : pi.receivers) { 1730b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (!TextUtils.isEmpty(ai.permission) && 1740b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ai.permission.equals(android.Manifest.permission.BIND_DEVICE_ADMIN)) { 1750b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 1760b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("There are several " 1770b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + "device admins in " + mdmPackageName + " but no one in specified"); 1780b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } else { 1790b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot mdmComponentName = new ComponentName(mdmPackageName, ai.name); 1800b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1810b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1820b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1830b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName == null) { 1840b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("There are no device admins in" 1850b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + mdmPackageName); 1860b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1870b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return mdmComponentName; 1880b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1899a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 1909a42f2b64dada715248aec7c898f983375a395eeAlan Treadway public static MdmPackageInfo getMdmPackageInfo(PackageManager pm, String packageName) { 1919a42f2b64dada715248aec7c898f983375a395eeAlan Treadway if (packageName != null) { 1929a42f2b64dada715248aec7c898f983375a395eeAlan Treadway try { 1939a42f2b64dada715248aec7c898f983375a395eeAlan Treadway ApplicationInfo ai = pm.getApplicationInfo(packageName, /* default flags */ 0); 1949a42f2b64dada715248aec7c898f983375a395eeAlan Treadway if (ai != null) { 1959a42f2b64dada715248aec7c898f983375a395eeAlan Treadway return new MdmPackageInfo(pm.getApplicationIcon(packageName), 1969a42f2b64dada715248aec7c898f983375a395eeAlan Treadway pm.getApplicationLabel(ai).toString()); 1979a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 1989a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } catch (PackageManager.NameNotFoundException e) { 1999a42f2b64dada715248aec7c898f983375a395eeAlan Treadway // Package does not exist, ignore. Should never happen. 2009a42f2b64dada715248aec7c898f983375a395eeAlan Treadway ProvisionLogger.loge("Package does not exist. Should never happen."); 2019a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 2029a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 2039a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 2049a42f2b64dada715248aec7c898f983375a395eeAlan Treadway return null; 2059a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 2069a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 2079a42f2b64dada715248aec7c898f983375a395eeAlan Treadway /** 2089a42f2b64dada715248aec7c898f983375a395eeAlan Treadway * Information relating to the currently installed MDM package manager. 2099a42f2b64dada715248aec7c898f983375a395eeAlan Treadway */ 2109a42f2b64dada715248aec7c898f983375a395eeAlan Treadway public static final class MdmPackageInfo { 2119a42f2b64dada715248aec7c898f983375a395eeAlan Treadway private final Drawable packageIcon; 2129a42f2b64dada715248aec7c898f983375a395eeAlan Treadway private final String appLabel; 2139a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 2149a42f2b64dada715248aec7c898f983375a395eeAlan Treadway private MdmPackageInfo(Drawable packageIcon, String appLabel) { 2159a42f2b64dada715248aec7c898f983375a395eeAlan Treadway this.packageIcon = packageIcon; 2169a42f2b64dada715248aec7c898f983375a395eeAlan Treadway this.appLabel = appLabel; 2179a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 2189a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 2199a42f2b64dada715248aec7c898f983375a395eeAlan Treadway public String getAppLabel() { 2209a42f2b64dada715248aec7c898f983375a395eeAlan Treadway return appLabel; 2219a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 2229a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 2239a42f2b64dada715248aec7c898f983375a395eeAlan Treadway public Drawable getPackageIcon() { 2249a42f2b64dada715248aec7c898f983375a395eeAlan Treadway return packageIcon; 2259a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 2269a42f2b64dada715248aec7c898f983375a395eeAlan Treadway } 227d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino 228d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino public static boolean isCurrentUserOwner() { 229d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino return UserHandle.myUserId() == UserHandle.USER_OWNER; 230d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino } 23184e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino 23284e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino public static boolean hasDeviceOwner(Context context) { 23384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino DevicePolicyManager dpm = 23484e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 23584e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino return !TextUtils.isEmpty(dpm.getDeviceOwner()); 23684e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino } 23784e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino 2380a7e766466a2c5ed6f12d30464099a582c31f00dCraig Lafayette public static boolean hasDeviceInitializer(Context context) { 2390a7e766466a2c5ed6f12d30464099a582c31f00dCraig Lafayette DevicePolicyManager dpm = 2400a7e766466a2c5ed6f12d30464099a582c31f00dCraig Lafayette (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 2410a7e766466a2c5ed6f12d30464099a582c31f00dCraig Lafayette return dpm != null && dpm.getDeviceInitializerApp() != null; 2420a7e766466a2c5ed6f12d30464099a582c31f00dCraig Lafayette } 2430a7e766466a2c5ed6f12d30464099a582c31f00dCraig Lafayette 24484e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino public static boolean isManagedProfile(Context context) { 24584e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 24684e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino UserInfo user = um.getUserInfo(UserHandle.myUserId()); 24784e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino return user != null ? user.isManagedProfile() : false; 24884e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino } 24984e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino 25074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse /** 25174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse * Returns true if the given package does not exist on the device or if its version code is less 25274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse * than the given version, and false otherwise. 25374d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse */ 25474d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse public static boolean packageRequiresUpdate(String packageName, int minSupportedVersion, 25574d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse Context context) { 25674d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse try { 25774d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); 25874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse if (packageInfo.versionCode >= minSupportedVersion) { 25974d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse return false; 26074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 26174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } catch (NameNotFoundException e) { 26274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse // Package not on device. 26374d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 26474d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse 26574d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse return true; 26674d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 26774d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse 2683efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse public static byte[] stringToByteArray(String s) 2693efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse throws NumberFormatException { 2703efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse try { 2713efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse return Base64.decode(s, Base64.URL_SAFE); 2723efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } catch (IllegalArgumentException e) { 2733efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse throw new NumberFormatException("Incorrect format. Should be Url-safe Base64 encoded."); 2743efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } 2753efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } 2763efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse 2773efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse public static String byteArrayToString(byte[] bytes) { 2783efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse return Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP); 2793efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } 280a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 281a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka public static void markDeviceProvisioned(Context context) { 282a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (isCurrentUserOwner()) { 283a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // This only needs to be set once per device 284a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka Global.putInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 1); 285a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 286a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 287a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // Setting this flag will either cause Setup Wizard to finish immediately when it starts (if 288a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // it is not already running), or when its next activity starts (if it is already running, 289a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // e.g. the non-NFC flow). 290a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // When either of these things happen, a home intent is fired. We catch that in 291a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // HomeReceiverActivity before sending the intent to notify the mdm that provisioning is 292a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // complete. 293a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // Note that, in the NFC flow or for secondary users, setting this flag will prevent the 294a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // user from seeing SUW, even if no other device initialization app was specified. 295a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka Secure.putInt(context.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1); 296a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 297a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 298a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka public static boolean isUserSetupCompleted(Context context) { 299a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return Secure.getInt(context.getContentResolver(), Secure.USER_SETUP_COMPLETE, 0) != 0; 300a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 301a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 302a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka public static UserHandle getManagedProfile(Context context) { 303a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 304a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka int currentUserId = userManager.getUserHandle(); 305a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka List<UserInfo> userProfiles = userManager.getProfiles(currentUserId); 306a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka for (UserInfo profile : userProfiles) { 307a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (profile.isManagedProfile()) { 308a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return new UserHandle(profile.id); 309a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 310a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 311a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return null; 312a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 313a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 314a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka /** 315a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka * @return The User id of an already existing managed profile or -1 if none 316a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka * exists 317a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka */ 318a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka public static int alreadyHasManagedProfile(Context context) { 319a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka UserHandle managedUser = getManagedProfile(context); 320a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (managedUser != null) { 321a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return managedUser.getIdentifier(); 322a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 323a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return -1; 324a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 325a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 326a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 327a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka public static void removeAccount(Context context, Account account) { 328a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka try { 329a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManager accountManager = 330a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); 331a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account, 332a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka null, null /* callback */, null /* handler */); 333a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // Block to get the result of the removeAccount operation 334a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (bundle.getResult().getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) { 335a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Account removed from the primary user."); 336a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 337a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka Intent removeIntent = (Intent) bundle.getResult().getParcelable( 338a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManager.KEY_INTENT); 339a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (removeIntent != null) { 340a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logi("Starting activity to remove account"); 3410ed8f62fcb0c35402ccee0b93679ace2dc96a03bRubin Xu TrampolineActivity.startActivity(context, removeIntent); 342a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 343a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Could not remove account from the primary user."); 344a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 345a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 346a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } catch (OperationCanceledException | AuthenticatorException | IOException e) { 347a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Exception removing account from the primary user.", e); 348a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 349a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 3506f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu 3516f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu public static boolean isFrpSupported(Context context) { 3526f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu Object pdbManager = context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); 3536f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu return pdbManager != null; 3546f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu } 3556f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu 356d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse} 357