DO NOT MERGE Revise security requirements for TelephonyManager#endCall.

Note: This fix will be applied up to and including O, but no further
since the P release includes an appropriate substitute API.
There are multiple apps using reflection to call TelephonyManager#endCall.
Although reliance on reflection to call internal implementation methods is
a bad practice, our previous fix for this method rendered a number of
popular apps in the ecosystem broken.
This patch relaxes the security restrictions surrounding the endCall method
and re-instates the ability for a caller holding CALL_PHONE permission
to end non-emergency calls.
In Android P, the new MODIFY_PHONE_STATE restriction remains in place as
the new TelecomManager#endCall API provides a supported means for apps to
reject or end calls.

Test: Use test app to ensure emergency calls cannot be terminated.
Test: Use test app to ensure calls can't be terminated in ECM mode.
Test: Use test app to ensure calls can be rejected/ended with CALL_PHONE
permission.
Test: Use test app to ensure calls cannot be rejected/ended without
CALL_PHONE permission.
Bug: 67862398
Change-Id: Ibac8f4f91402c91176f58fd951be122b513a4cc0
(cherry picked from commit 84101e8a0f89a97f79919debe181223384c97ba6)
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index b11418f..f5621e9 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1172,12 +1172,22 @@
      * @return true is a call was ended
      */
     public boolean endCallForSubscriber(int subId) {
-        if (mApp.checkCallingOrSelfPermission(permission.MODIFY_PHONE_STATE)
-                != PackageManager.PERMISSION_GRANTED) {
-            Log.i(LOG_TAG, "endCall: called without modify phone state.");
+        Phone phone = getPhone(subId);
+        CallManager callManager = PhoneGlobals.getInstance().getCallManager();
+
+        // When device is in emergency callback mode or there is an active emergency call, do not
+        // allow the caller to end the call unless they hold modify phone state permission.
+        if (phone != null && callManager != null
+                && (phone.isInEcm() || PhoneUtils.isInEmergencyCall(callManager))
+                && mApp.checkCallingOrSelfPermission(permission.MODIFY_PHONE_STATE)
+                        != PackageManager.PERMISSION_GRANTED) {
+
+            Log.i(LOG_TAG, "endCall: called without modify phone state for emergency call.");
             EventLog.writeEvent(0x534e4554, "67862398", -1, "");
-            throw new SecurityException("MODIFY_PHONE_STATE permission required.");
+            throw new SecurityException(
+                    "MODIFY_PHONE_STATE permission required to end an emergency call.");
         }
+        enforceCallPermission();
         return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId));
     }