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

Commit 3611889c authored by karthik bharadwaj's avatar karthik bharadwaj
Browse files

Add support for handling microphone disable by multiple users

Support handling the microphone toggle setting for multiple
foreground users, with possible dissimilar setting states.

Test: On a device with a guest user added by the owner in the system
settings UI (assume starting with the owner profile):
- Build CHRE with the audioworld static nanoapp to constantly request
audio data, load to device and reload CHRE.
- Enable the microphone privacy setting for the owner via the adb CLI,
verify that audio world is not getting data, and that the audio source
has been suspended.
- Switch to the guest user via the system UI, observe that the
audioworld nanoapp is now receiving data.
- Reset to initial state, repeat while starting from the guest profile
for a quick consistency check.

Bug: 174691697
Change-Id: If92170c82363356fcbb1ddc2abdcd25a5ed85039
parent a8621e85
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.util.Log;

@@ -51,4 +53,9 @@ class ContextHubSystemService extends SystemService {
            publishBinderService(Context.CONTEXTHUB_SERVICE, mContextHubService);
        }
    }

    @Override
    public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
        mContextHubService.onUserChanged();
    }
}
+55 −19
Original line number Diff line number Diff line
@@ -17,13 +17,16 @@
package com.android.server.location.contexthub;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManagerInternal;
import android.hardware.contexthub.V1_0.AsyncEventType;
import android.hardware.contexthub.V1_0.ContextHub;
import android.hardware.contexthub.V1_0.ContextHubMsg;
@@ -59,6 +62,7 @@ import android.util.Pair;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.location.ContextHubServiceProto;

import java.io.FileDescriptor;
@@ -127,6 +131,8 @@ public class ContextHubService extends IContextHubService.Stub {
    // Lock object for sendWifiSettingUpdate()
    private final Object mSendWifiSettingUpdateLock = new Object();

    private final SensorPrivacyManagerInternal mSensorPrivacyManagerInternal;

    /**
     * Class extending the callback to register with a Context Hub.
     */
@@ -186,6 +192,7 @@ public class ContextHubService extends IContextHubService.Stub {
        if (mContextHubWrapper == null) {
            mTransactionManager = null;
            mClientManager = null;
            mSensorPrivacyManagerInternal = null;
            mDefaultClientMap = Collections.emptyMap();
            mContextHubIdToInfoMap = Collections.emptyMap();
            mSupportedContextHubPerms = Collections.emptyList();
@@ -208,6 +215,8 @@ public class ContextHubService extends IContextHubService.Stub {
        mClientManager = new ContextHubClientManager(mContext, mContextHubWrapper);
        mTransactionManager = new ContextHubTransactionManager(
                mContextHubWrapper.getHub(), mClientManager, mNanoAppStateManager);
        mSensorPrivacyManagerInternal =
                LocalServices.getService(SensorPrivacyManagerInternal.class);

        HashMap<Integer, IContextHubClient> defaultClientMap = new HashMap<>();
        for (int contextHubId : mContextHubIdToInfoMap.keySet()) {
@@ -284,18 +293,16 @@ public class ContextHubService extends IContextHubService.Stub {
        }

        if (mContextHubWrapper.supportsMicrophoneDisableSettingNotifications()) {
            sendMicrophoneDisableSettingUpdate();
            sendMicrophoneDisableSettingUpdateForCurrentUser();

            SensorPrivacyManager.OnSensorPrivacyChangedListener listener =
                    new SensorPrivacyManager.OnSensorPrivacyChangedListener() {
                    @Override
                    public void onSensorPrivacyChanged(boolean enabled) {
                        sendMicrophoneDisableSettingUpdate();
            mSensorPrivacyManagerInternal.addSensorPrivacyListenerForAllUsers(
                    SensorPrivacyManager.Sensors.MICROPHONE, (userId, enabled) -> {
                        if (userId == getCurrentUserId()) {
                            Log.d(TAG, "User: " + userId + " enabled: " + enabled);
                            sendMicrophoneDisableSettingUpdate(enabled);
                        }
                };
            SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
            manager.addSensorPrivacyListener(
                    SensorPrivacyManager.Sensors.MICROPHONE, listener);
                });

        }
    }

@@ -1074,19 +1081,48 @@ public class ContextHubService extends IContextHubService.Stub {
    }

    /**
     * Obtains the latest microphone disable setting value and notifies the
     * Context Hub.
     * Notifies a microphone disable settings change to the Context Hub.
     */
    private void sendMicrophoneDisableSettingUpdate(boolean enabled) {
        Log.d(TAG, "Mic Disabled Setting: " + enabled);
        mContextHubWrapper.onMicrophoneDisableSettingChanged(enabled);
    }

    /**
     * Obtains the latest microphone disabled setting for the current user
     * and notifies the Context Hub.
     */
    private void sendMicrophoneDisableSettingUpdate() {
        SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
        boolean disabled = manager.isSensorPrivacyEnabled(
                SensorPrivacyManager.Sensors.MICROPHONE);
        Log.d(TAG, "Mic Disabled Setting: " + disabled);
        mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
    private void sendMicrophoneDisableSettingUpdateForCurrentUser() {
        boolean isEnabled = mSensorPrivacyManagerInternal.isSensorPrivacyEnabled(
                getCurrentUserId(), SensorPrivacyManager.Sensors.MICROPHONE);
        sendMicrophoneDisableSettingUpdate(isEnabled);
    }


    private String getCallingPackageName() {
        return mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
    }

    private int getCurrentUserId() {
        final long id = Binder.clearCallingIdentity();
        try {
            UserInfo currentUser = ActivityManager.getService().getCurrentUser();
            return currentUser.id;
        } catch (RemoteException e) {
            // Activity manager not running, nothing we can do - assume user 0.
        } finally {
            Binder.restoreCallingIdentity(id);
        }
        return UserHandle.USER_SYSTEM;
    }

    /**
     * Send a microphone disable settings update whenever the foreground user changes.
     * We always send a settings update regardless of the previous state for the same user
     * since the CHRE framework is expected to handle repeated identical setting update.
     */
    public void onUserChanged() {
        Log.d(TAG, "User changed to id: " + getCurrentUserId());
        sendMicrophoneDisableSettingUpdateForCurrentUser();
    }
}