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

Commit 8e75b865 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Ensure TeleComm tracks carrier privileged apps using mic" into sc-dev

parents c4c7a6be 4b0ef448
Loading
Loading
Loading
Loading
+85 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.telecom;

import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO;
import static android.os.Process.myUid;

import android.Manifest;
@@ -80,7 +81,8 @@ import java.util.stream.Collectors;
 * can send updates to the in-call app. This class is created and owned by CallsManager and retains
 * a binding to the {@link IInCallService} (implemented by the in-call app).
 */
public class InCallController extends CallsManagerListenerBase {
public class InCallController extends CallsManagerListenerBase implements
        AppOpsManager.OnOpActiveChangedListener {
    public static final int IN_CALL_SERVICE_NOTIFICATION_ID = 3;
    public static final String NOTIFICATION_TAG = InCallController.class.getSimpleName();

@@ -1008,6 +1010,9 @@ public class InCallController extends CallsManagerListenerBase {
     */
    private ArrayList<String> mCallsUsingCamera = new ArrayList<>();

    private ArraySet<String> mAllCarrierPrivilegedApps = new ArraySet<>();
    private ArraySet<String> mActiveCarrierPrivilegedApps = new ArraySet<>();

    public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
            SystemStateHelper systemStateHelper, DefaultDialerCache defaultDialerCache,
            Timeouts.Adapter timeoutsAdapter, EmergencyCallHelper emergencyCallHelper,
@@ -1036,6 +1041,65 @@ public class InCallController extends CallsManagerListenerBase {
                mToken, packageRestriction, UserHandle.USER_ALL);
    }

    @Override
    public void onOpActiveChanged(@androidx.annotation.NonNull String op, int uid,
            @androidx.annotation.NonNull String packageName, boolean active) {
        synchronized (mLock) {
            if (!mAllCarrierPrivilegedApps.contains(packageName)) {
                return;
            }

            if (active) {
                mActiveCarrierPrivilegedApps.add(packageName);
            } else {
                mActiveCarrierPrivilegedApps.remove(packageName);
            }
            maybeTrackMicrophoneUse(isMuted());
        }
    }

    private void updateAllCarrierPrivilegedUsingMic() {
        mActiveCarrierPrivilegedApps.clear();
        UserManager userManager = mContext.getSystemService(UserManager.class);
        PackageManager pkgManager = mContext.getPackageManager();
        for (String pkg : mAllCarrierPrivilegedApps) {
            boolean isActive = mActiveCarrierPrivilegedApps.contains(pkg);
            List<UserHandle> users = userManager.getUserHandles(true);
            for (UserHandle user : users) {
                if (isActive) {
                    break;
                }

                int uid;
                try {
                    uid = pkgManager.getPackageUidAsUser(pkg, user.getIdentifier());
                } catch (PackageManager.NameNotFoundException e) {
                    continue;
                }
                List<AppOpsManager.PackageOps> pkgOps = mAppOpsManager.getOpsForPackage(
                        uid, pkg, OPSTR_RECORD_AUDIO);
                for (int j = 0; j < pkgOps.size(); j++) {
                    List<AppOpsManager.OpEntry> opEntries = pkgOps.get(j).getOps();
                    for (int k = 0; k < opEntries.size(); k++) {
                        AppOpsManager.OpEntry entry = opEntries.get(k);
                        if (entry.isRunning()) {
                            mActiveCarrierPrivilegedApps.add(pkg);
                            break;
                        }
                    }
                }
            }
        }
    }

    private void updateAllCarrierPrivileged() {
        mAllCarrierPrivilegedApps.clear();
        for (Call call : mCallIdMapper.getCalls()) {
            mAllCarrierPrivilegedApps.add(call.getConnectionManagerPhoneAccount()
                    .getComponentName().getPackageName());
        }
    }

    @Override
    public void onCallAdded(Call call) {
        if (!isBoundAndConnectedToServices()) {
@@ -1116,6 +1180,10 @@ public class InCallController extends CallsManagerListenerBase {
        }
        call.removeListener(mCallListener);
        mCallIdMapper.removeCall(call);
        if (mCallIdMapper.getCalls().isEmpty()) {
            mActiveCarrierPrivilegedApps.clear();
            mAppOpsManager.stopWatchingActive(this);
        }
        maybeTrackMicrophoneUse(isMuted());
        onSetCamera(call, null);
    }
@@ -1269,6 +1337,7 @@ public class InCallController extends CallsManagerListenerBase {
    public void onIsVoipAudioModeChanged(Call call) {
        Log.d(this, "onIsVoipAudioModeChanged %s", call);
        updateCall(call);
        maybeTrackMicrophoneUse(isMuted());
    }

    @Override
@@ -1898,10 +1967,18 @@ public class InCallController extends CallsManagerListenerBase {
     * @param call The call to add.
     */
    private void addCall(Call call) {
        if (mCallIdMapper.getCalls().size() == 0) {
            mAppOpsManager.startWatchingActive(new String[] { OPSTR_RECORD_AUDIO },
                    java.lang.Runnable::run, this);
            updateAllCarrierPrivileged();
            updateAllCarrierPrivilegedUsingMic();
        }

        if (mCallIdMapper.getCallId(call) == null) {
            mCallIdMapper.addCall(call);
            call.addListener(mCallListener);
        }

        maybeTrackMicrophoneUse(isMuted());
    }

@@ -2140,7 +2217,8 @@ public class InCallController extends CallsManagerListenerBase {
     */
    private void maybeTrackMicrophoneUse(boolean isMuted) {
        boolean wasTrackingManagedCall = mIsCallUsingMicrophone;
        mIsCallUsingMicrophone = isTrackingManagedAliveCall() && !isMuted;
        mIsCallUsingMicrophone = isTrackingManagedAliveCall() && !isMuted
                && !carrierPrivilegedUsingMicDuringVoipCall();
        if (wasTrackingManagedCall != mIsCallUsingMicrophone) {
            if (mIsCallUsingMicrophone) {
                mAppOpsManager.startOp(AppOpsManager.OP_PHONE_CALL_MICROPHONE, myUid(),
@@ -2162,6 +2240,11 @@ public class InCallController extends CallsManagerListenerBase {
                c.getState()));
    }

    private boolean carrierPrivilegedUsingMicDuringVoipCall() {
        return !mActiveCarrierPrivilegedApps.isEmpty() &&
                mCallIdMapper.getCalls().stream().anyMatch(Call::getIsVoipAudioMode);
    }

    /**
     * @return {@code true} if the audio is currently muted, {@code false} otherwise.
     */
+1 −1
Original line number Diff line number Diff line
@@ -514,7 +514,7 @@ public class InCallControllerTests extends TelecomTestCase {
        // Pretend that the call has gone away.
        when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
        mInCallController.onCallRemoved(mMockCall);
        waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT);
        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);

        verify(mMockPackageManager).revokeRuntimePermission(eq(SYS_PKG),
                eq(Manifest.permission.ACCESS_FINE_LOCATION), eq(mUserHandle));