Update DPM.reboot with new restriction

DPM.reboot() should not be called when there is an ongoing call on the
device.

Bug:27531799
Change-Id: Idc1fa4c7aa79b20ec9c2afcccf855455ee316787
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ec1e3e6..c0d4a3e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -51,6 +51,7 @@
 import android.provider.Settings;
 import android.security.Credentials;
 import android.service.restrictions.RestrictionsReceiver;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -5566,7 +5567,10 @@
     }
 
     /**
-     * Called by device owner to reboot the device.
+     * Called by device owner to reboot the device. If there is an ongoing call on the device,
+     * throws an {@link IllegalStateException}.
+     * @throws IllegalStateException if device has an ongoing call.
+     * @see TelephonyManager#CALL_STATE_IDLE
      */
     public void reboot(@NonNull ComponentName admin) {
         try {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b48c185..6582b29 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -115,6 +115,7 @@
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
 import android.service.persistentdata.PersistentDataBlockManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -306,6 +307,7 @@
     final IPackageManager mIPackageManager;
     final UserManager mUserManager;
     final UserManagerInternal mUserManagerInternal;
+    final TelephonyManager mTelephonyManager;
     private final LockPatternUtils mLockPatternUtils;
 
     /**
@@ -1354,6 +1356,10 @@
             return LocalServices.getService(PowerManagerInternal.class);
         }
 
+        TelephonyManager getTelephonyManager() {
+            return TelephonyManager.from(mContext);
+        }
+
         IWindowManager getIWindowManager() {
             return IWindowManager.Stub
                     .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -1542,6 +1548,7 @@
         mUserManager = Preconditions.checkNotNull(injector.getUserManager());
         mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal());
         mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
+        mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
 
         mLocalService = new LocalService();
         mLockPatternUtils = injector.newLockPatternUtils();
@@ -8309,6 +8316,10 @@
         }
         long ident = mInjector.binderClearCallingIdentity();
         try {
+            // Make sure there are no ongoing calls on the device.
+            if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+                throw new IllegalStateException("Cannot be called with ongoing call on the device");
+            }
             mInjector.powerManagerReboot(PowerManager.REBOOT_REQUESTED_BY_DEVICE_OWNER);
         } finally {
             mInjector.binderRestoreCallingIdentity(ident);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index aaec1e9..35777ce 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -29,6 +29,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.os.storage.StorageManager;
+import android.telephony.TelephonyManager;
 import android.view.IWindowManager;
 
 import java.io.File;
@@ -322,5 +323,10 @@
         boolean securityLogIsLoggingEnabled() {
             return context.settings.securityLogIsLoggingEnabled();
         }
+
+        @Override
+        TelephonyManager getTelephonyManager() {
+            return context.telephonyManager;
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index e897e3d..6c2bdda 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -33,6 +33,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
@@ -1491,7 +1492,7 @@
         assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
     }
 
-    public void testRebootCanOnlyBeCalledByDeviceOwner() throws Exception {
+    public void testReboot() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
@@ -1524,6 +1525,29 @@
         dpm.clearProfileOwner(admin1);
         assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
 
+        // admin1 is DO.
+        // Set current call state of device to ringing.
+        when(mContext.telephonyManager.getCallState())
+                .thenReturn(TelephonyManager.CALL_STATE_RINGING);
+        try {
+            dpm.reboot(admin1);
+            fail("DPM.reboot() called when receiveing a call, should thrown IllegalStateException");
+        } catch (IllegalStateException expected) {
+            MoreAsserts.assertContainsRegex("ongoing call on the device", expected.getMessage());
+        }
+
+        // Set current call state of device to dialing/active.
+        when(mContext.telephonyManager.getCallState())
+                .thenReturn(TelephonyManager.CALL_STATE_OFFHOOK);
+        try {
+            dpm.reboot(admin1);
+            fail("DPM.reboot() called when dialing, should thrown IllegalStateException");
+        } catch (IllegalStateException expected) {
+            MoreAsserts.assertContainsRegex("ongoing call on the device", expected.getMessage());
+        }
+
+        // Set current call state of device to idle.
+        when(mContext.telephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE);
         dpm.reboot(admin1);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index b05309a..8e2ef70 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -40,6 +40,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.os.storage.StorageManager;
+import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
 import android.view.IWindowManager;
@@ -262,6 +263,7 @@
     public final WifiManager wifiManager;
     public final SettingsForMock settings;
     public final MockContentResolver contentResolver;
+    public final TelephonyManager telephonyManager;
 
     /** Note this is a partial mock, not a real mock. */
     public final PackageManager packageManager;
@@ -295,6 +297,7 @@
         storageManager = mock(StorageManagerForMock.class);
         wifiManager = mock(WifiManager.class);
         settings = mock(SettingsForMock.class);
+        telephonyManager = mock(TelephonyManager.class);
 
         // Package manager is huge, so we use a partial mock instead.
         packageManager = spy(context.getPackageManager());