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

Commit 536a5f78 authored by Jacqueline Bronger's avatar Jacqueline Bronger
Browse files

Show a bottom sheet when the mic/camera is blocked

On mobile a normal dialog is shown when a sensor is blocked by the
global toggle.

Bug: 186720017
Test: manual
For one sensor and both sensors together:
1) Block sensor(s) in settings or with 'adb shell cmd sensor_privacy enable 0 microphone' (/camera)
2) open the Duo app
3) Try to access blocked sensor(s): 'adb shell appops start
com.google.android.apps.tachyon 27' (/26)
4) Sensor(s) should be unblocked if 'unblock' is selected or remain
blocked if cancelled (check in settings or 'adb shell dumpsys sensor_prvacy' where disabled means unblocked or privacy indicator will show up)

Change-Id: I69fb67478460d05acf6b1d570705dc4f73ca8d1e
parent 2463594f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -42,4 +42,8 @@

    <!-- Allow SystemUI to show the shutdown dialog -->
    <bool name="config_showSysuiShutdown">true</bool>

    <!-- Component name of the activity used to inform a user about a sensory being blocked because
     of privacy settings. -->
    <string name="config_sensorUseStartedActivity">com.android.systemui/com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity</string>
</resources>
+8 −0
Original line number Diff line number Diff line
@@ -454,6 +454,14 @@
                  android:finishOnCloseSystemDialogs="true">
        </activity>

        <!-- started from SensoryPrivacyService -->
        <activity android:name=".sensorprivacy.television.TvUnblockSensorActivity"
                  android:exported="true"
                  android:permission="android.permission.MANAGE_SENSOR_PRIVACY"
                  android:theme="@style/BottomSheet"
                  android:finishOnCloseSystemDialogs="true">
        </activity>


        <!-- started from UsbDeviceSettingsManager -->
        <activity android:name=".usb.UsbAccessoryUriActivity"
+7 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.screenrecord.ScreenRecordDialog;
import com.android.systemui.screenshot.LongScreenshotActivity;
import com.android.systemui.sensorprivacy.SensorUseStartedActivity;
import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity;
import com.android.systemui.settings.brightness.BrightnessDialog;
import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
import com.android.systemui.tuner.TunerActivity;
@@ -120,4 +121,10 @@ public abstract class DefaultActivityBinder {
    @IntoMap
    @ClassKey(SensorUseStartedActivity.class)
    public abstract Activity bindSensorUseStartedActivity(SensorUseStartedActivity activity);

    /** Inject into TvUnblockSensorActivity. */
    @Binds
    @IntoMap
    @ClassKey(TvUnblockSensorActivity.class)
    public abstract Activity bindTvUnblockSensorActivity(TvUnblockSensorActivity activity);
}
+145 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.sensorprivacy.television;

import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;

import android.hardware.SensorPrivacyManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.systemui.R;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.tv.TvBottomSheetActivity;

import javax.inject.Inject;

/**
 * Bottom sheet that is shown when the camera/mic sensors are blocked by the global toggle and
 * allows the user to re-enable them.
 */
public class TvUnblockSensorActivity extends TvBottomSheetActivity {

    private static final String TAG = TvUnblockSensorActivity.class.getSimpleName();

    private static final int ALL_SENSORS = Integer.MAX_VALUE;
    private int mSensor = -1;

    private final IndividualSensorPrivacyController mSensorPrivacyController;
    private IndividualSensorPrivacyController.Callback mSensorPrivacyCallback;

    @Inject
    public TvUnblockSensorActivity(
            IndividualSensorPrivacyController individualSensorPrivacyController) {
        mSensorPrivacyController = individualSensorPrivacyController;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        boolean allSensors = getIntent().getBooleanExtra(SensorPrivacyManager.EXTRA_ALL_SENSORS,
                false);
        if (allSensors) {
            mSensor = ALL_SENSORS;
        } else {
            mSensor = getIntent().getIntExtra(SensorPrivacyManager.EXTRA_SENSOR, -1);
        }

        if (mSensor == -1) {
            Log.v(TAG, "Invalid extras");
            finish();
            return;
        }

        mSensorPrivacyCallback = (sensor, blocked) -> {
            if (mSensor == ALL_SENSORS) {
                if (!mSensorPrivacyController.isSensorBlocked(CAMERA)
                        && !mSensorPrivacyController.isSensorBlocked(MICROPHONE)) {
                    finish();
                }
            } else if (this.mSensor == sensor && !blocked) {
                finish();
            }
        };

        initUI();
    }

    private void initUI() {
        TextView title = findViewById(R.id.bottom_sheet_title);
        TextView content = findViewById(R.id.bottom_sheet_body);
        ImageView icon = findViewById(R.id.bottom_sheet_icon);
        // mic icon if both icons are shown
        ImageView secondIcon = findViewById(R.id.bottom_sheet_second_icon);
        Button unblockButton = findViewById(R.id.bottom_sheet_positive_button);
        Button cancelButton = findViewById(R.id.bottom_sheet_negative_button);

        switch (mSensor) {
            case MICROPHONE:
                title.setText(R.string.sensor_privacy_start_use_mic_dialog_title);
                content.setText(R.string.sensor_privacy_start_use_mic_dialog_content);
                icon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
                secondIcon.setVisibility(View.GONE);
                break;
            case CAMERA:
                title.setText(R.string.sensor_privacy_start_use_camera_dialog_title);
                content.setText(R.string.sensor_privacy_start_use_camera_dialog_content);
                icon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
                secondIcon.setVisibility(View.GONE);
                break;
            case ALL_SENSORS:
            default:
                title.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_title);
                content.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_content);
                icon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
                secondIcon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
                break;
        }
        unblockButton.setText(
                com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button);
        unblockButton.setOnClickListener(v -> {
            if (mSensor == ALL_SENSORS) {
                mSensorPrivacyController.setSensorBlocked(CAMERA, false);
                mSensorPrivacyController.setSensorBlocked(MICROPHONE, false);
            } else {
                mSensorPrivacyController.setSensorBlocked(mSensor, false);
            }
        });

        cancelButton.setText(android.R.string.cancel);
        cancelButton.setOnClickListener(v -> finish());
    }

    @Override
    public void onResume() {
        super.onResume();
        mSensorPrivacyController.addCallback(mSensorPrivacyCallback);
    }

    @Override
    public void onPause() {
        mSensorPrivacyController.removeCallback(mSensorPrivacyCallback);
        super.onPause();
    }

}