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 1772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzpackage com.android.managedprovisioning.common; 18d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 193128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ngimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; 213128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 223128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE; 233128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; 243128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC; 253128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED; 263128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 273128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.Account; 283128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AccountManager; 293128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AccountManagerFuture; 303128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AuthenticatorException; 313128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.OperationCanceledException; 32945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franzimport android.annotation.NonNull; 33945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franzimport android.annotation.Nullable; 3484e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.app.admin.DevicePolicyManager; 359a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.ComponentName; 360b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.Context; 379a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.Intent; 380b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.ActivityInfo; 39d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.ApplicationInfo; 40d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.IPackageManager; 410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageInfo; 42d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.PackageManager; 430b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageManager.NameNotFoundException; 44ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franzimport android.content.pm.ResolveInfo; 4584e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.content.pm.UserInfo; 46b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevotimport android.graphics.Color; 47ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franzimport android.net.ConnectivityManager; 48ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franzimport android.net.NetworkInfo; 49ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franzimport android.net.wifi.WifiManager; 50ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franzimport android.os.Build; 51a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.os.Bundle; 52d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.RemoteException; 53d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.ServiceManager; 54ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franzimport android.os.SystemProperties; 55d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfinoimport android.os.UserHandle; 5684e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.os.UserManager; 57fce5147b7dbf266e9724dfb494cca88524b06bf8Ricky Waiimport android.os.storage.StorageManager; 580b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.text.TextUtils; 593fee5b87a1d3bbace3932937520b238d1b8923efBenjamin Franz 603fee5b87a1d3bbace3932937520b238d1b8923efBenjamin Franzimport com.android.internal.annotations.VisibleForTesting; 613fee5b87a1d3bbace3932937520b238d1b8923efBenjamin Franzimport com.android.managedprovisioning.TrampolineActivity; 623fee5b87a1d3bbace3932937520b238d1b8923efBenjamin Franzimport com.android.managedprovisioning.model.PackageDownloadInfo; 63d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 64974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevotimport java.io.FileInputStream; 65a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport java.io.IOException; 66974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevotimport java.io.InputStream; 67974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevotimport java.security.MessageDigest; 68974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevotimport java.security.NoSuchAlgorithmException; 69d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.HashSet; 709a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport java.util.List; 71d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.Set; 7272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz 73d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse/** 74d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Class containing various auxiliary methods. 75d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse */ 76d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnsepublic class Utils { 77974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot public static final String SHA256_TYPE = "SHA-256"; 78974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot public static final String SHA1_TYPE = "SHA-1"; 79974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot 803cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak // value chosen to match UX designs; when updating check status bar icon colors 813cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak private static final int THRESHOLD_BRIGHT_COLOR = 190; 82b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot 8372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public Utils() {} 849a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 8572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 8672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns the currently installed system apps on a given user. 8772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 8872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>Calls into the {@link IPackageManager} to retrieve all installed packages on the given 8972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * user and returns the package names of all system apps. 9072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 9172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param ipm an {@link IPackageManager} object 9272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param userId the id of the user we are interested in 9372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 9472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public Set<String> getCurrentSystemApps(IPackageManager ipm, int userId) { 95d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse Set<String> apps = new HashSet<String>(); 96d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse List<ApplicationInfo> aInfos = null; 97d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse try { 98d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse aInfos = ipm.getInstalledApplications( 99d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse PackageManager.GET_UNINSTALLED_PACKAGES, userId).getList(); 100d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (RemoteException neverThrown) { 101d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.loge("This should not happen.", neverThrown); 102d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 103d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse for (ApplicationInfo aInfo : aInfos) { 104d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 105d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse apps.add(aInfo.packageName); 106d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 107d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 108d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse return apps; 109d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 110d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 11172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 11272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Disables a given component in a given user. 11372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 11472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param toDisable the component that should be disabled 11572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param userId the id of the user where the component should be disabled. 11672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 11772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void disableComponent(ComponentName toDisable, int userId) { 1180a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz setComponentEnabledSetting( 1190a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz IPackageManager.Stub.asInterface(ServiceManager.getService("package")), 1200a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz toDisable, 1210a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 1220a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz userId); 1230a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz } 1240a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz 1250a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz /** 1260a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz * Enables a given component in a given user. 1270a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz * 1280a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz * @param toEnable the component that should be enabled 1290a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz * @param userId the id of the user where the component should be disabled. 1300a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz */ 1310a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz public void enableComponent(ComponentName toEnable, int userId) { 1320a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz setComponentEnabledSetting( 1330a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz IPackageManager.Stub.asInterface(ServiceManager.getService("package")), 1340a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz toEnable, 1350a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 1360a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz userId); 13772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz } 138d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 13972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 14072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Disables a given component in a given user. 14172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 14272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param ipm an {@link IPackageManager} object 14372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param toDisable the component that should be disabled 14472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param userId the id of the user where the component should be disabled. 14572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 1460a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz @VisibleForTesting 1470a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz void setComponentEnabledSetting(IPackageManager ipm, ComponentName toDisable, 1480a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz int enabledSetting, int userId) { 14972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz try { 150d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ipm.setComponentEnabledSetting(toDisable, 1510a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz enabledSetting, PackageManager.DONT_KILL_APP, 152d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse userId); 153d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (RemoteException neverThrown) { 154d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.loge("This should not happen.", neverThrown); 155d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (Exception e) { 1560a964a32b7e8e7b2207416530f8f4575e1cde46eBenjamin Franz ProvisionLogger.logw("Component not found, not changing enabled setting: " 157d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse + toDisable.toShortString()); 158d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 159d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 1600b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 1610b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot /** 1620b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check the validity of the admin component name supplied, or try to infer this componentName 1630b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * from the package. 1640b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1650b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * We are supporting lookup by package name for legacy reasons. 1660b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 167945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * If dpcComponentName is supplied (not null): dpcPackageName is ignored. 168945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * Check that the package of dpcComponentName is installed, that dpcComponentName is a 169a1db3cc833895803213b1dab55b917ad8ab0359fTony Mak * receiver in this package, and return it. The receiver can be in disabled state. 1700b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 171945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * Otherwise: dpcPackageName must be supplied (not null). 1720b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check that this package is installed, try to infer a potential device admin in this package, 1730b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * and return it. 1740b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot */ 175945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz @NonNull 176945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz public ComponentName findDeviceAdmin(String dpcPackageName, ComponentName dpcComponentName, 177945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz Context context) throws IllegalProvisioningArgumentException { 178945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz if (dpcComponentName != null) { 179945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz dpcPackageName = dpcComponentName.getPackageName(); 1800b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 181945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz if (dpcPackageName == null) { 1820b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("Neither the package name nor the" 1830b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " component name of the admin are supplied"); 1840b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1850b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot PackageInfo pi; 1860b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot try { 187945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz pi = context.getPackageManager().getPackageInfo(dpcPackageName, 188a1db3cc833895803213b1dab55b917ad8ab0359fTony Mak PackageManager.GET_RECEIVERS | PackageManager.MATCH_DISABLED_COMPONENTS); 1890b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } catch (NameNotFoundException e) { 190945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz throw new IllegalProvisioningArgumentException("Dpc "+ dpcPackageName 1910b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " is not installed. ", e); 1920b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 193945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz 194be71433cf40426a420be70cd6388b198403e423dVictor Chang final ComponentName componentName = findDeviceAdminInPackageInfo(dpcPackageName, 195be71433cf40426a420be70cd6388b198403e423dVictor Chang dpcComponentName, pi); 196be71433cf40426a420be70cd6388b198403e423dVictor Chang if (componentName == null) { 197be71433cf40426a420be70cd6388b198403e423dVictor Chang throw new IllegalProvisioningArgumentException("Cannot find any admin receiver in " 198be71433cf40426a420be70cd6388b198403e423dVictor Chang + "package " + dpcPackageName + " with component " + dpcComponentName); 199be71433cf40426a420be70cd6388b198403e423dVictor Chang } 200be71433cf40426a420be70cd6388b198403e423dVictor Chang return componentName; 201be71433cf40426a420be70cd6388b198403e423dVictor Chang } 202be71433cf40426a420be70cd6388b198403e423dVictor Chang 203be71433cf40426a420be70cd6388b198403e423dVictor Chang /** 204be71433cf40426a420be70cd6388b198403e423dVictor Chang * If dpcComponentName is not null: dpcPackageName is ignored. 205be71433cf40426a420be70cd6388b198403e423dVictor Chang * Check that the package of dpcComponentName is installed, that dpcComponentName is a 206be71433cf40426a420be70cd6388b198403e423dVictor Chang * receiver in this package, and return it. The receiver can be in disabled state. 207be71433cf40426a420be70cd6388b198403e423dVictor Chang * 208be71433cf40426a420be70cd6388b198403e423dVictor Chang * Otherwise, try to infer a potential device admin component in this package info. 209be71433cf40426a420be70cd6388b198403e423dVictor Chang * 210be71433cf40426a420be70cd6388b198403e423dVictor Chang * @return infered device admin component in package info. Otherwise, null 211be71433cf40426a420be70cd6388b198403e423dVictor Chang */ 212be71433cf40426a420be70cd6388b198403e423dVictor Chang @Nullable 213be71433cf40426a420be70cd6388b198403e423dVictor Chang public ComponentName findDeviceAdminInPackageInfo(@NonNull String dpcPackageName, 214be71433cf40426a420be70cd6388b198403e423dVictor Chang @Nullable ComponentName dpcComponentName, @NonNull PackageInfo pi) { 21580d4103fd2d75be562bfe81c558033c327b379e9Victor Chang if (dpcComponentName != null) { 21680d4103fd2d75be562bfe81c558033c327b379e9Victor Chang if (!isComponentInPackageInfo(dpcComponentName, pi)) { 217be71433cf40426a420be70cd6388b198403e423dVictor Chang ProvisionLogger.logw("The component " + dpcComponentName + " isn't registered in " 218be71433cf40426a420be70cd6388b198403e423dVictor Chang + "the apk"); 219be71433cf40426a420be70cd6388b198403e423dVictor Chang return null; 22080d4103fd2d75be562bfe81c558033c327b379e9Victor Chang } 221be71433cf40426a420be70cd6388b198403e423dVictor Chang return dpcComponentName; 22280d4103fd2d75be562bfe81c558033c327b379e9Victor Chang } else { 223be71433cf40426a420be70cd6388b198403e423dVictor Chang return findDeviceAdminInPackage(dpcPackageName, pi); 2240b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2250b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2260b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 22772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 228945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * Finds a device admin in a given {@link PackageInfo} object. 22972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 230945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * <p>This function returns {@code null} if no or multiple admin receivers were found, and if 231945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * the package name does not match dpcPackageName.</p> 232945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * @param packageName packge name that should match the {@link PackageInfo} object. 233945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * @param packageInfo package info to be examined. 234945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz * @return admin receiver or null in case of error. 23572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 236945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz @Nullable 237be71433cf40426a420be70cd6388b198403e423dVictor Chang private ComponentName findDeviceAdminInPackage(String packageName, PackageInfo packageInfo) { 238945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz if (packageInfo == null || !TextUtils.equals(packageInfo.packageName, packageName)) { 239945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz return null; 2400b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 2420b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ComponentName mdmComponentName = null; 243945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz for (ActivityInfo ai : packageInfo.receivers) { 244945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz if (TextUtils.equals(ai.permission, android.Manifest.permission.BIND_DEVICE_ADMIN)) { 2450b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 246be71433cf40426a420be70cd6388b198403e423dVictor Chang ProvisionLogger.logw("more than 1 device admin component are found"); 247945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz return null; 2480b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } else { 249945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz mdmComponentName = new ComponentName(packageName, ai.name); 2500b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2510b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2520b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2530b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return mdmComponentName; 2540b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2559a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 25680d4103fd2d75be562bfe81c558033c327b379e9Victor Chang private boolean isComponentInPackageInfo(ComponentName dpcComponentName, 25780d4103fd2d75be562bfe81c558033c327b379e9Victor Chang PackageInfo pi) { 25880d4103fd2d75be562bfe81c558033c327b379e9Victor Chang for (ActivityInfo ai : pi.receivers) { 25980d4103fd2d75be562bfe81c558033c327b379e9Victor Chang if (dpcComponentName.getClassName().equals(ai.name)) { 26080d4103fd2d75be562bfe81c558033c327b379e9Victor Chang return true; 26180d4103fd2d75be562bfe81c558033c327b379e9Victor Chang } 26280d4103fd2d75be562bfe81c558033c327b379e9Victor Chang } 26380d4103fd2d75be562bfe81c558033c327b379e9Victor Chang return false; 26480d4103fd2d75be562bfe81c558033c327b379e9Victor Chang } 26580d4103fd2d75be562bfe81c558033c327b379e9Victor Chang 2669a42f2b64dada715248aec7c898f983375a395eeAlan Treadway /** 2672ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * Return if a given package has testOnly="true", in which case we'll relax certain rules 2682ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * for CTS. 2692ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * 2702ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * The system allows this flag to be changed when an app is updated. But 2712ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * {@link DevicePolicyManager} uses the persisted version to do actual checks for relevant 2722ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * dpm command. 2732ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * 2742ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * @see DevicePolicyManagerService#isPackageTestOnly for more info 2752ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang */ 2762ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang public boolean isPackageTestOnly(PackageManager pm, String packageName, int userHandle) { 2772ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang if (TextUtils.isEmpty(packageName)) { 2782ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang return false; 2792ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang } 2802ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang 2812ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang try { 2822ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang final ApplicationInfo ai = pm.getApplicationInfoAsUser(packageName, 2832ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang PackageManager.MATCH_DIRECT_BOOT_AWARE 2842ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle); 2852ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang return ai != null && (ai.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0; 2862ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang } catch (PackageManager.NameNotFoundException e) { 2872ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang return false; 2882ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang } 2892ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang 2902ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang } 2912ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang 2922ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang /** 2932ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * Returns whether the current user is the system user. 2942ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang */ 2952ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang public boolean isCurrentUserSystem() { 2962ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang return UserHandle.myUserId() == UserHandle.USER_SYSTEM; 2972ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang } 2982ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang 2992ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang /** 3002ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang * Returns whether the device is currently managed. 3012ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang */ 3022ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang public boolean isDeviceManaged(Context context) { 3032ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang DevicePolicyManager dpm = 3042ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 3052ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang return dpm.isDeviceManaged(); 3062ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang } 3072ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang 3082ecfc6315b527e62bd5a303cd726a4d7009f774aVictor Chang /** 30972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns true if the given package requires an update. 31072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 31172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>There are two cases where an update is required: 31272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 1. The package is not currently present on the device. 31372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 2. The package is present, but the version is below the minimum supported version. 31472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 31572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param packageName the package to be checked for updates 31672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param minSupportedVersion the minimum supported version 31772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 31874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse */ 31972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean packageRequiresUpdate(String packageName, int minSupportedVersion, 32074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse Context context) { 32174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse try { 32274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); 323d1784bd4d917bb36125e6faf125a2425c343838bSteven Ng // Always download packages if no minimum version given. 324d1784bd4d917bb36125e6faf125a2425c343838bSteven Ng if (minSupportedVersion != PackageDownloadInfo.DEFAULT_MINIMUM_VERSION 325d1784bd4d917bb36125e6faf125a2425c343838bSteven Ng && packageInfo.versionCode >= minSupportedVersion) { 32674d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse return false; 32774d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 32874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } catch (NameNotFoundException e) { 32974d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse // Package not on device. 33074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 33174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse 33274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse return true; 33374d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 33474d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse 33572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 33672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns the first existing managed profile if any present, null otherwise. 33772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 33872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>Note that we currently only support one managed profile per device. 33972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 340ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Add unit tests 34172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public UserHandle getManagedProfile(Context context) { 342a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 343a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka int currentUserId = userManager.getUserHandle(); 344a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka List<UserInfo> userProfiles = userManager.getProfiles(currentUserId); 345a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka for (UserInfo profile : userProfiles) { 346a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (profile.isManagedProfile()) { 347a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return new UserHandle(profile.id); 348a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 349a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 350a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return null; 351a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 352a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 353a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka /** 35472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns the user id of an already existing managed profile or -1 if none exists. 355a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka */ 356ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Add unit tests 35772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public int alreadyHasManagedProfile(Context context) { 358a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka UserHandle managedUser = getManagedProfile(context); 359a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (managedUser != null) { 360a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return managedUser.getIdentifier(); 361a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 362a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return -1; 363a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 364a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 365a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 36672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 36772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Removes an account. 36872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 36972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>This removes the given account from the calling user's list of accounts. 37072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 37172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 37272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param account the account to be removed 37372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 374ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Add unit tests 37572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void removeAccount(Context context, Account account) { 376a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka try { 377a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManager accountManager = 378a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); 379a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account, 380a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka null, null /* callback */, null /* handler */); 381a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // Block to get the result of the removeAccount operation 382a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (bundle.getResult().getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) { 383a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Account removed from the primary user."); 384a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 385a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka Intent removeIntent = (Intent) bundle.getResult().getParcelable( 386a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManager.KEY_INTENT); 387a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (removeIntent != null) { 388a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logi("Starting activity to remove account"); 3890ed8f62fcb0c35402ccee0b93679ace2dc96a03bRubin Xu TrampolineActivity.startActivity(context, removeIntent); 390a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 391a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Could not remove account from the primary user."); 392a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 393a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 394a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } catch (OperationCanceledException | AuthenticatorException | IOException e) { 395a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Exception removing account from the primary user.", e); 396a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 397a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 3986f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu 39972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 40072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether FRP is supported on the device. 40172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 40272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isFrpSupported(Context context) { 4036f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu Object pdbManager = context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); 4046f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu return pdbManager != null; 4056f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu } 4066f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu 4073128ba4542f3c4c90790af0564e75950c8900961Alan Treadway /** 408eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * Translates a given managed provisioning intent to its corresponding provisioning flow, using 409eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * the action from the intent. 410eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * 411eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * <p/>This is necessary because, unlike other provisioning actions which has 1:1 mapping, there 412eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * are multiple actions that can trigger the device owner provisioning flow. This includes 413eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link ACTION_NDEF_DISCOVERED} and 414eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * {@link ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}. These 3 actions are equivalent 415eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * excepts they are sent from a different source. 416eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * 417eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * @return the appropriate DevicePolicyManager declared action for the given incoming intent. 4183128ba4542f3c4c90790af0564e75950c8900961Alan Treadway * @throws IllegalProvisioningArgumentException if intent is malformed 4193128ba4542f3c4c90790af0564e75950c8900961Alan Treadway */ 420ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Add unit tests 42172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public String mapIntentToDpmAction(Intent intent) 4223128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throws IllegalProvisioningArgumentException { 4233128ba4542f3c4c90790af0564e75950c8900961Alan Treadway if (intent == null || intent.getAction() == null) { 4243128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throw new IllegalProvisioningArgumentException("Null intent action."); 4253128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 4263128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 4273128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // Map the incoming intent to a DevicePolicyManager.ACTION_*, as there is a N:1 mapping in 4283128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // some cases. 4293128ba4542f3c4c90790af0564e75950c8900961Alan Treadway String dpmProvisioningAction; 4303128ba4542f3c4c90790af0564e75950c8900961Alan Treadway switch (intent.getAction()) { 4313128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // Trivial cases. 4323128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_DEVICE: 4333128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE: 4343128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_USER: 4353128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_PROFILE: 4363128ba4542f3c4c90790af0564e75950c8900961Alan Treadway dpmProvisioningAction = intent.getAction(); 4373128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 4383128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 4393128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // NFC cases which need to take mime-type into account. 4403128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_NDEF_DISCOVERED: 4413128ba4542f3c4c90790af0564e75950c8900961Alan Treadway String mimeType = intent.getType(); 442f373bd83d4b4afdc51b1cf43987521723246c19dMahaver Chopra if (mimeType == null) { 443f373bd83d4b4afdc51b1cf43987521723246c19dMahaver Chopra throw new IllegalProvisioningArgumentException( 444f373bd83d4b4afdc51b1cf43987521723246c19dMahaver Chopra "Unknown NFC bump mime-type: " + mimeType); 445f373bd83d4b4afdc51b1cf43987521723246c19dMahaver Chopra } 4463128ba4542f3c4c90790af0564e75950c8900961Alan Treadway switch (mimeType) { 4473128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case MIME_TYPE_PROVISIONING_NFC: 4483128ba4542f3c4c90790af0564e75950c8900961Alan Treadway dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE; 4493128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 4503128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 4513128ba4542f3c4c90790af0564e75950c8900961Alan Treadway default: 4523128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throw new IllegalProvisioningArgumentException( 4533128ba4542f3c4c90790af0564e75950c8900961Alan Treadway "Unknown NFC bump mime-type: " + mimeType); 4543128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 4553128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 4563128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 457eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng // Device owner provisioning from a trusted app. 458eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng // TODO (b/27217042): review for new management modes in split system-user model 459eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng case ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE: 460eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE; 461eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng break; 462eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng 4633128ba4542f3c4c90790af0564e75950c8900961Alan Treadway default: 4643128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throw new IllegalProvisioningArgumentException("Unknown intent action " 4653128ba4542f3c4c90790af0564e75950c8900961Alan Treadway + intent.getAction()); 4663128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 4673128ba4542f3c4c90790af0564e75950c8900961Alan Treadway return dpmProvisioningAction; 4683128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 4693128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 4703128ba4542f3c4c90790af0564e75950c8900961Alan Treadway /** 47172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Sends an intent to trigger a factory reset. 47272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 473ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Move the FR intent into a Globals class. 47472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void sendFactoryResetBroadcast(Context context, String reason) { 4756b7d9a2e5439546b8b843b1fb95e47550a251d5dLenka Trochtova Intent intent = new Intent(Intent.ACTION_FACTORY_RESET); 476ab61c63584885391568944257108a7e50972fe6aVictor Chang // Send explicit broadcast due to Broadcast Limitations 477ab61c63584885391568944257108a7e50972fe6aVictor Chang intent.setPackage("android"); 478aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 479aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka intent.putExtra(Intent.EXTRA_REASON, reason); 480aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka context.sendBroadcast(intent); 481aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka } 482e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot 48372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 48472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the given provisioning action is a profile owner action. 48572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 486ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Move the list of device owner actions into a Globals class. 487c79c4bc4e83edd3938e13dc4a434d5a1bb638498Benjamin Franz public final boolean isProfileOwnerAction(String action) { 488e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot return action.equals(ACTION_PROVISION_MANAGED_PROFILE) 489e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot || action.equals(ACTION_PROVISION_MANAGED_USER); 490e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot } 491e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot 49272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 49372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the given provisioning action is a device owner action. 49472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 495ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Move the list of device owner actions into a Globals class. 496c79c4bc4e83edd3938e13dc4a434d5a1bb638498Benjamin Franz public final boolean isDeviceOwnerAction(String action) { 497e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot return action.equals(ACTION_PROVISION_MANAGED_DEVICE) 498e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot || action.equals(ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE); 499e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot } 500e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot 501ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 502ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether the device currently has connectivity. 503ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 504ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public boolean isConnectedToNetwork(Context context) { 505ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz NetworkInfo info = getActiveNetworkInfo(context); 506ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return info != null && info.isConnected(); 507ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 508ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 509ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 510ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether the device is currently connected to a wifi. 511ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 512ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public boolean isConnectedToWifi(Context context) { 513ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz NetworkInfo info = getActiveNetworkInfo(context); 514ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return info != null 515ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz && info.isConnected() 516ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz && info.getType() == ConnectivityManager.TYPE_WIFI; 517ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 518ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 51905d5528f0accab78785b2719f4762ea91d76f681Mahaver Chopra /** 52005d5528f0accab78785b2719f4762ea91d76f681Mahaver Chopra * Returns the active network info of the device. 52105d5528f0accab78785b2719f4762ea91d76f681Mahaver Chopra */ 52205d5528f0accab78785b2719f4762ea91d76f681Mahaver Chopra public NetworkInfo getActiveNetworkInfo(Context context) { 523ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz ConnectivityManager cm = 524ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 52505d5528f0accab78785b2719f4762ea91d76f681Mahaver Chopra return cm.getActiveNetworkInfo(); 526ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 527ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 528ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 529ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether encryption is required on this device. 530ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * 531ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * <p>Encryption is required if the device is not currently encrypted and the persistent 532ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * system flag {@code persist.sys.no_req_encrypt} is not set. 533ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 534ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public boolean isEncryptionRequired() { 535ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return !isPhysicalDeviceEncrypted() 536ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz && !SystemProperties.getBoolean("persist.sys.no_req_encrypt", false); 537ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 538ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 539ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 540ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether the device is currently encrypted. 541ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 542ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public boolean isPhysicalDeviceEncrypted() { 543fce5147b7dbf266e9724dfb494cca88524b06bf8Ricky Wai return StorageManager.isEncrypted(); 544ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 545ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 546ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 547ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns the wifi pick intent. 548ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 549ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // TODO: Move this intent into a Globals class. 550ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public Intent getWifiPickIntent() { 551ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz Intent wifiIntent = new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK); 552ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz wifiIntent.putExtra("extra_prefs_show_button_bar", true); 553ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz wifiIntent.putExtra("wifi_enable_next_on_connect", true); 554ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return wifiIntent; 555ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 556ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 557ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 558ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether the device has a split system user. 559ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * 560ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * <p>Split system user means that user 0 is system only and all meat users are separate from 561ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * the system user. 562ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 563ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public boolean isSplitSystemUser() { 564ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return UserManager.isSplitSystemUser(); 565ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 566ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 567ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 568ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether the currently chosen launcher supports managed profiles. 569ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * 570ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * <p>A launcher is deemed to support managed profiles when its target API version is at least 571ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * {@link Build.VERSION_CODES#LOLLIPOP}. 572ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 573ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz public boolean currentLauncherSupportsManagedProfiles(Context context) { 574ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz Intent intent = new Intent(Intent.ACTION_MAIN); 575ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz intent.addCategory(Intent.CATEGORY_HOME); 576ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 577ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz PackageManager pm = context.getPackageManager(); 578ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz ResolveInfo launcherResolveInfo = pm.resolveActivity(intent, 579ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz PackageManager.MATCH_DEFAULT_ONLY); 580ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz if (launcherResolveInfo == null) { 581ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return false; 582ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 583ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz try { 584ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // If the user has not chosen a default launcher, then launcherResolveInfo will be 585ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // referring to the resolver activity. It is fine to create a managed profile in 586ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // this case since there will always be at least one launcher on the device that 587ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz // supports managed profile feature. 588ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz ApplicationInfo launcherAppInfo = pm.getApplicationInfo( 589ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz launcherResolveInfo.activityInfo.packageName, 0 /* default flags */); 590ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return versionNumberAtLeastL(launcherAppInfo.targetSdkVersion); 591ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } catch (PackageManager.NameNotFoundException e) { 592ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return false; 593ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 594ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 595ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz 596ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz /** 597ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * Returns whether the given version number is at least lollipop. 598ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * 599ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz * @param versionNumber the version number to be verified. 600ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz */ 601ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz private boolean versionNumberAtLeastL(int versionNumber) { 602ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz return versionNumber >= Build.VERSION_CODES.LOLLIPOP; 603ea821b26fc845efa8058c883b0210432e9619f77Benjamin Franz } 604974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot 605974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot /** 606974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot * Computes the sha 256 hash of a byte array. 607974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot */ 608945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz @Nullable 609945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz public byte[] computeHashOfByteArray(byte[] bytes) { 610945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz try { 611945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz MessageDigest md = MessageDigest.getInstance(SHA256_TYPE); 612945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz md.update(bytes); 613945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz return md.digest(); 614945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz } catch (NoSuchAlgorithmException e) { 615945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz ProvisionLogger.loge("Hashing algorithm " + SHA256_TYPE + " not supported.", e); 616945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz return null; 617945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz } 618974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 619974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot 620974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot /** 621974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot * Computes a hash of a file with a spcific hash algorithm. 622974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot */ 623945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz // TODO: Add unit tests 624945e609e967c33897df9e5f53b86e0eaa6e53e2eBenjamin Franz @Nullable 625974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot public byte[] computeHashOfFile(String fileLocation, String hashType) { 626974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot InputStream fis = null; 627974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot MessageDigest md; 628974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot byte hash[] = null; 629974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot try { 630974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot md = MessageDigest.getInstance(hashType); 631974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } catch (NoSuchAlgorithmException e) { 632974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot ProvisionLogger.loge("Hashing algorithm " + hashType + " not supported.", e); 633974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot return null; 634974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 635974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot try { 636974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot fis = new FileInputStream(fileLocation); 637974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot 638974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot byte[] buffer = new byte[256]; 639974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot int n = 0; 640974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot while (n != -1) { 641974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot n = fis.read(buffer); 642974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot if (n > 0) { 643974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot md.update(buffer, 0, n); 644974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 645974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 646974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot hash = md.digest(); 647974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } catch (IOException e) { 648974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot ProvisionLogger.loge("IO error.", e); 649974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } finally { 650974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot // Close input stream quietly. 651974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot try { 652974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot if (fis != null) { 653974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot fis.close(); 654974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 655974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } catch (IOException e) { 656974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot // Ignore. 657974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 658974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 659974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot return hash; 660974f02ac4952ba596665c71d1e71717cf8f6ef7aNicolas Prevot } 661b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot 662b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot public boolean isBrightColor(int color) { 663b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot // This comes from the YIQ transformation. We're using the formula: 664b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot // Y = .299 * R + .587 * G + .114 * B 665b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot return Color.red(color) * 299 + Color.green(color) * 587 + Color.blue(color) * 114 666b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot >= 1000 * THRESHOLD_BRIGHT_COLOR; 667b38680c8eebfaf0af71efaf042383d06a2a8350aNicolas Prevot } 668cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra 669cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra /** 670cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra * Returns whether given intent can be resolved for the user. 671cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra */ 672cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra public boolean canResolveIntentAsUser(Context context, Intent intent, int userId) { 673cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra return intent != null 674cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra && context.getPackageManager().resolveActivityAsUser(intent, 0, userId) != null; 675cb4628e81cf01fa83b92a68b6313282efc176d48Mahaver Chopra } 67680ae370242ebd15119d1a6e9e5026e036bfe1cf7Victor Chang 67780ae370242ebd15119d1a6e9e5026e036bfe1cf7Victor Chang public boolean isPackageDeviceOwner(DevicePolicyManager dpm, String packageName) { 67880ae370242ebd15119d1a6e9e5026e036bfe1cf7Victor Chang final ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnCallingUser(); 67980ae370242ebd15119d1a6e9e5026e036bfe1cf7Victor Chang return deviceOwner != null && deviceOwner.getPackageName().equals(packageName); 68080ae370242ebd15119d1a6e9e5026e036bfe1cf7Victor Chang } 6816b7d9a2e5439546b8b843b1fb95e47550a251d5dLenka Trochtova} 682