Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5baccc81 authored by Ruijie Bai's avatar Ruijie Bai Committed by takeshi tanigawa
Browse files

Revoke the location permission properly after the emergency calls

There is a 2 second delay to unbind the in-call services after all the
calls are removed. If customize the delay to a longer value(eg:5s), and
make more than one emergency calls within the delay, then the location
permission won't be revoked.

When the delay of the first emergency call expires, it doesn't revoke
the permission because permission flag mHadFineLocation was wrongly
updated to true. When the delay of the second emergency call expires,
it also doesn't revoke the permission because permission flag
mLocationPermissionGrantedToUser was wrongly updated to null.

The change is to update the permission flags properly, and only keep
the latest delay timer to revoke the permission after all the calls
end.

Bug: 345386002
Test: manual
Test: atest InCallControllerTests
Test: atest EmergencyCallHelperTest
Change-Id: I1a451ea9a752f83f27ff1e65d05fc0fb52f75b84
parent 5e5a06b4
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
package: "com.android.server.telecom.flags"
container: "system"

flag {
  name: "prevent_redundant_location_permission_grant_and_revoke"
  namespace: "telecom"
  description: "avoid redundant action of grant and revoke location permission for multiple emergency calls"
  bug: "345386002"
}

flag {
  name: "transactional_cs_verifier"
  namespace: "telecom"
+9 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.telecom.Log;
import android.telecom.PhoneAccountHandle;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.flags.FeatureFlags;

/**
 * Helps with emergency calls by:
@@ -51,19 +52,25 @@ public class EmergencyCallHelper {
    private long mLastEmergencyCallTimestampMillis;
    private long mLastOutgoingEmergencyCallTimestampMillis;

    private final FeatureFlags mFeatureFlags;

    @VisibleForTesting
    public EmergencyCallHelper(
            Context context,
            DefaultDialerCache defaultDialerCache,
            Timeouts.Adapter timeoutsAdapter) {
            Timeouts.Adapter timeoutsAdapter,
            FeatureFlags featureFlags) {
        mContext = context;
        mDefaultDialerCache = defaultDialerCache;
        mTimeoutsAdapter = timeoutsAdapter;
        mFeatureFlags = featureFlags;
    }

    @VisibleForTesting
    public void maybeGrantTemporaryLocationPermission(Call call, UserHandle userHandle) {
        if (shouldGrantTemporaryLocationPermission(call)) {
        if (shouldGrantTemporaryLocationPermission(call) && (
                !mFeatureFlags.preventRedundantLocationPermissionGrantAndRevoke()
                || !wasGrantedTemporaryLocationPermission())) {
            grantLocationPermission(userHandle);
        }
        if (call != null && call.isEmergencyCall()) {
+11 −3
Original line number Diff line number Diff line
@@ -1263,6 +1263,8 @@ public class InCallController extends CallsManagerListenerBase implements
    private ArraySet<String> mAllCarrierPrivilegedApps = new ArraySet<>();
    private ArraySet<String> mActiveCarrierPrivilegedApps = new ArraySet<>();

    private java.lang.Runnable mCallRemovedRunnable;

    public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
            SystemStateHelper systemStateHelper, DefaultDialerCache defaultDialerCache,
            Timeouts.Adapter timeoutsAdapter, EmergencyCallHelper emergencyCallHelper,
@@ -1476,7 +1478,11 @@ public class InCallController extends CallsManagerListenerBase implements
            /** Let's add a 2 second delay before we send unbind to the services to hopefully
             *  give them enough time to process all the pending messages.
             */
            mHandler.postDelayed(new Runnable("ICC.oCR", mLock) {
            if (mCallRemovedRunnable != null
                    && mFeatureFlags.preventRedundantLocationPermissionGrantAndRevoke()) {
                mHandler.removeCallbacks(mCallRemovedRunnable);
            }
            mCallRemovedRunnable = new Runnable("ICC.oCR", mLock) {
                @Override
                public void loggedRun() {
                    // Check again to make sure there are no active calls for the associated user.
@@ -1490,7 +1496,9 @@ public class InCallController extends CallsManagerListenerBase implements
                        mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
                    }
                }
            }.prepare(), mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
            }.prepare();
            mHandler.postDelayed(mCallRemovedRunnable,
                    mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
                            mContext.getContentResolver()));
        }
        call.removeListener(mCallListener);
+1 −1
Original line number Diff line number Diff line
@@ -288,7 +288,7 @@ public class TelecomSystem {
                            mContactsAsyncHelper, mLock);

            EmergencyCallHelper emergencyCallHelper = new EmergencyCallHelper(mContext,
                    defaultDialerCache, timeoutsAdapter);
                    defaultDialerCache, timeoutsAdapter, mFeatureFlags);

            InCallControllerFactory inCallControllerFactory = new InCallControllerFactory() {
                @Override
+56 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ public class EmergencyCallHelperTest extends TelecomTestCase {
    mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
    when(mContext.getPackageManager()).thenReturn(mPackageManager);
    mEmergencyCallHelper = new EmergencyCallHelper(mContext, mDefaultDialerCache,
        mTimeoutsAdapter);
        mTimeoutsAdapter, mFeatureFlags);
    when(mDefaultDialerCache.getSystemDialerApplication()).thenReturn(SYSTEM_DIALER_PACKAGE);

    //start with no perms
@@ -183,6 +183,61 @@ public class EmergencyCallHelperTest extends TelecomTestCase {
    verifyRevokeNotInvokedFor(ACCESS_FINE_LOCATION);
  }

  @SmallTest
  @Test
  public void testPermGrantAndRevokeForEmergencyCall() {

    when(mFeatureFlags.preventRedundantLocationPermissionGrantAndRevoke()).thenReturn(true);

    mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
    mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();

    //permissions should be granted then revoked
    verifyGrantInvokedFor(ACCESS_BACKGROUND_LOCATION);
    verifyGrantInvokedFor(ACCESS_FINE_LOCATION);
    verifyRevokeInvokedFor(ACCESS_BACKGROUND_LOCATION);
    verifyRevokeInvokedFor(ACCESS_FINE_LOCATION);
  }

  @SmallTest
  @Test
  public void testPermGrantAndRevokeForMultiEmergencyCall() {

    when(mFeatureFlags.preventRedundantLocationPermissionGrantAndRevoke()).thenReturn(true);

    //first call is emergency call
    mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
    //second call is emergency call
    mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
    mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();

    //permissions should be granted then revoked
    verifyGrantInvokedFor(ACCESS_BACKGROUND_LOCATION);
    verifyGrantInvokedFor(ACCESS_FINE_LOCATION);
    verifyRevokeInvokedFor(ACCESS_BACKGROUND_LOCATION);
    verifyRevokeInvokedFor(ACCESS_FINE_LOCATION);
  }

  @SmallTest
  @Test
  public void testPermGrantAndRevokeForEmergencyCallAndNormalCall() {

    when(mFeatureFlags.preventRedundantLocationPermissionGrantAndRevoke()).thenReturn(true);

    //first call is emergency call
    mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
    //second call is normal call
    when(mCall.isEmergencyCall()).thenReturn(false);
    mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
    mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();

    //permissions should be granted then revoked
    verifyGrantInvokedFor(ACCESS_BACKGROUND_LOCATION);
    verifyGrantInvokedFor(ACCESS_FINE_LOCATION);
    verifyRevokeInvokedFor(ACCESS_BACKGROUND_LOCATION);
    verifyRevokeInvokedFor(ACCESS_FINE_LOCATION);
  }

  @SmallTest
  @Test
  public void testNoPermGrantForNonEmergencyCall() {
Loading