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

Commit 630225ca authored by Beth Thibodeau's avatar Beth Thibodeau
Browse files

Add custom start dialog with options

Use a custom dialog with options for recording audio and taps, instead
of the standard media projection permissions dialog. Options will not be saved
and both default to off. Since system audio isn't implemented yet the audio
switch just shows the text for microphone audio.

Also updated ongoing notification text to reflect whether audio is being
recorded.

Bug: 147490562
Test: manual, screenshots at https://drive.google.com/drive/folders/1jIyzmPDwt6oxVGAw319awdSafnoz8nmI?usp=sharing
Change-Id: I2b012a6b8b6611c0d6fcada79ed5bdc009e24b17
parent 6e67cfc2
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
<!--
Copyright (C) 2020 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.
-->
<!-- maybe need android:fillType="evenOdd" -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M9,7.5V11.24C7.79,10.43 7,9.06 7,7.5C7,5.01 9.01,3 11.5,3C13.99,3 16,5.01 16,7.5C16,9.06 15.21,10.43 14,11.24V7.5C14,6.12 12.88,5 11.5,5C10.12,5 9,6.12 9,7.5ZM14.3,13.61L18.84,15.87C19.37,16.09 19.75,16.63 19.75,17.25C19.75,17.31 19.74,17.38 19.73,17.45L18.98,22.72C18.87,23.45 18.29,24 17.54,24H10.75C10.34,24 9.96,23.83 9.69,23.56L4.75,18.62L5.54,17.82C5.74,17.62 6.02,17.49 6.33,17.49C6.39,17.49 6.4411,17.4989 6.4922,17.5078C6.5178,17.5122 6.5433,17.5167 6.57,17.52L10,18.24V7.5C10,6.67 10.67,6 11.5,6C12.33,6 13,6.67 13,7.5V13.5H13.76C13.95,13.5 14.13,13.54 14.3,13.61Z"
    />
</vector>
+142 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright (C) 2020 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.
  -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/rounded_bg_full">

    <!-- Header -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center"
        android:padding="@dimen/screenrecord_dialog_padding">
        <ImageView
            android:layout_width="@dimen/screenrecord_logo_size"
            android:layout_height="@dimen/screenrecord_logo_size"
            android:src="@drawable/ic_screenrecord"
            android:tint="@color/GM2_red_500"
            android:layout_marginBottom="@dimen/screenrecord_dialog_padding"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="@string/screenrecord_start_label"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/screenrecord_description"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:paddingTop="@dimen/screenrecord_dialog_padding"
            android:paddingBottom="@dimen/screenrecord_dialog_padding"/>

        <!-- Options -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <ImageView
                android:layout_width="@dimen/screenrecord_logo_size"
                android:layout_height="@dimen/screenrecord_logo_size"
                android:src="@drawable/ic_mic_26dp"
                android:tint="@color/GM2_grey_700"
                android:layout_gravity="center"
                android:layout_weight="0"
                android:layout_marginRight="@dimen/screenrecord_dialog_padding"/>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_weight="1">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center_vertical"
                    android:text="@string/screenrecord_audio_label"
                    android:textColor="?android:attr/textColorPrimary"
                    android:textAppearance="?android:attr/textAppearanceMedium"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/audio_type"
                    android:text="@string/screenrecord_mic_label"
                    android:textAppearance="?android:attr/textAppearanceSmall"/>
            </LinearLayout>
            <Switch
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:layout_weight="0"
                android:id="@+id/screenrecord_audio_switch"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <ImageView
                android:layout_width="@dimen/screenrecord_logo_size"
                android:layout_height="@dimen/screenrecord_logo_size"
                android:src="@drawable/ic_touch"
                android:tint="@color/GM2_grey_700"
                android:layout_gravity="center"
                android:layout_marginRight="@dimen/screenrecord_dialog_padding"/>
            <Switch
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:id="@+id/screenrecord_taps_switch"
                android:text="@string/screenrecord_taps_label"
                android:textColor="?android:attr/textColorPrimary"
                android:textAppearance="?android:attr/textAppearanceMedium"/>
        </LinearLayout>
    </LinearLayout>

    <!-- hr -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/GM2_grey_300"/>

    <!-- Buttons -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="@dimen/screenrecord_dialog_padding">
        <Button
            android:id="@+id/button_cancel"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="0"
            android:layout_gravity="start"
            android:text="@string/cancel"
            style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/>
        <Space
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:id="@+id/button_start"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="0"
            android:layout_gravity="end"
            android:text="@string/screenrecord_start"
            style="@android:style/Widget.DeviceDefault.Button.Colored"/>
    </LinearLayout>
</LinearLayout>
 No newline at end of file
+3 −1
Original line number Diff line number Diff line
@@ -1209,5 +1209,7 @@

    <dimen name="controls_card_margin">2dp</dimen>


    <!-- Screen Record -->
    <dimen name="screenrecord_dialog_padding">18dp</dimen>
    <dimen name="screenrecord_logo_size">24dp</dimen>
</resources>
+24 −6
Original line number Diff line number Diff line
@@ -217,15 +217,31 @@
        your organization</string>

    <!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
    <string name="screenrecord_name">Screen Recording</string>
    <string name="screenrecord_name">Screen Recorder</string>
    <!-- Description of the screen recording notification channel [CHAR LIMIT=NONE]-->
    <string name="screenrecord_channel_description">Ongoing notification for a screen record session</string>
    <!-- Label for the button to begin screen recording [CHAR LIMIT=NONE]-->
    <string name="screenrecord_start_label">Start Recording</string>
    <!-- Label for the checkbox to enable microphone input during screen recording [CHAR LIMIT=NONE]-->
    <string name="screenrecord_mic_label">Record voiceover</string>
    <!-- Title for the screen prompting the user to begin recording their screen [CHAR LIMIT=NONE]-->
    <string name="screenrecord_start_label">Start Recording?</string>
    <!-- Message reminding the user that sensitive information may be captured during a screen recording [CHAR_LIMIT=NONE]-->
    <string name="screenrecord_description">While recording, Android System can capture any sensitive information that\u2019s visible on your screen or played on your device. This includes passwords, payment info, photos, messages, and audio.</string>
    <!-- Label for a switch to enable recording audio [CHAR LIMIT=NONE]-->
    <string name="screenrecord_audio_label">Record audio</string>
    <!-- Label for the option to record audio from the device [CHAR LIMIT=NONE]-->
    <string name="screenrecord_device_audio_label">Device audio</string>
    <!-- Description of what audio may be captured from the device [CHAR LIMIT=NONE]-->
    <string name="screenrecord_device_audio_description">Sound from your device, like music, calls, and ringtones</string>
    <!-- Label for the option to enable microphone input during screen recording [CHAR LIMIT=NONE]-->
    <string name="screenrecord_mic_label">Microphone</string>
    <!-- Label for an option to record audio from both device and microphone [CHAR LIMIT=NONE]-->
    <string name="screenrecord_device_audio_and_mic_label">Device audio and microphone</string>
    <!-- Button to start a screen recording [CHAR LIMIT=50]-->
    <string name="screenrecord_start">Start</string>
    <!-- Notification text displayed when we are recording the screen [CHAR LIMIT=100]-->
    <string name="screenrecord_ongoing_screen_only">Recording screen</string>
    <!-- Notification text displayed when we are recording both the screen and audio [CHAR LIMIT=100]-->
    <string name="screenrecord_ongoing_screen_and_audio">Recording screen and audio</string>
    <!-- Label for the checkbox to enable showing location of touches during screen recording [CHAR LIMIT=NONE]-->
    <string name="screenrecord_taps_label">Show taps</string>
    <string name="screenrecord_taps_label">Show touches on screen</string>
    <!-- Label for notification that the user can tap to stop and save the screen recording [CHAR LIMIT=NONE] -->
    <string name="screenrecord_stop_text">Tap to stop</string>
    <!-- Label for notification action to stop and save the screen recording [CHAR LIMIT=35] -->
@@ -250,6 +266,8 @@
    <string name="screenrecord_delete_error">Error deleting screen recording</string>
    <!-- A toast message shown when the screen recording cannot be started due to insufficient permissions [CHAR LIMIT=NONE] -->
    <string name="screenrecord_permission_error">Failed to get permissions</string>
    <!-- A toast message shown when the screen recording cannot be started due to a generic error [CHAR LIMIT=NONE] -->
    <string name="screenrecord_start_error">Error starting screen recording</string>

    <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
    <string name="usb_preference_title">USB file transfer options</string>
+34 −13
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.systemui.screenrecord;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -26,16 +25,21 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionManager;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.DisplayMetrics;
@@ -83,7 +87,6 @@ public class RecordingService extends Service {
    private static final int AUDIO_SAMPLE_RATE = 44100;

    private final RecordingController mController;
    private MediaProjectionManager mMediaProjectionManager;
    private MediaProjection mMediaProjection;
    private Surface mInputSurface;
    private VirtualDisplay mVirtualDisplay;
@@ -134,13 +137,30 @@ public class RecordingService extends Service {

        switch (action) {
            case ACTION_START:
                int resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, Activity.RESULT_CANCELED);
                mUseAudio = intent.getBooleanExtra(EXTRA_USE_AUDIO, false);
                mShowTaps = intent.getBooleanExtra(EXTRA_SHOW_TAPS, false);
                Intent data = intent.getParcelableExtra(EXTRA_DATA);
                if (data != null) {
                    mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
                try {
                    IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
                    IMediaProjectionManager mediaService =
                            IMediaProjectionManager.Stub.asInterface(b);
                    IMediaProjection proj = mediaService.createProjection(getUserId(),
                            getPackageName(),
                            MediaProjectionManager.TYPE_SCREEN_CAPTURE, false);
                    IBinder projection = proj.asBinder();
                    if (projection == null) {
                        Log.e(TAG, "Projection was null");
                        Toast.makeText(this, R.string.screenrecord_start_error, Toast.LENGTH_LONG)
                                .show();
                        return Service.START_NOT_STICKY;
                    }
                    mMediaProjection = new MediaProjection(getApplicationContext(),
                            IMediaProjection.Stub.asInterface(projection));
                    startRecording();
                } catch (RemoteException e) {
                    e.printStackTrace();
                    Toast.makeText(this, R.string.screenrecord_start_error, Toast.LENGTH_LONG)
                            .show();
                    return Service.START_NOT_STICKY;
                }
                break;

@@ -195,9 +215,6 @@ public class RecordingService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();

        mMediaProjectionManager =
                (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    }

    /**
@@ -269,6 +286,7 @@ public class RecordingService extends Service {
    }

    private void createRecordingNotification() {
        Resources res = getResources();
        NotificationChannel channel = new NotificationChannel(
                CHANNEL_ID,
                getString(R.string.screenrecord_name),
@@ -281,11 +299,15 @@ public class RecordingService extends Service {

        Bundle extras = new Bundle();
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
                getResources().getString(R.string.screenrecord_name));
                res.getString(R.string.screenrecord_name));

        String notificationTitle = mUseAudio
                ? res.getString(R.string.screenrecord_ongoing_screen_and_audio)
                : res.getString(R.string.screenrecord_ongoing_screen_only);

        mRecordingNotificationBuilder = new Notification.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_screenrecord)
                .setContentTitle(getResources().getString(R.string.screenrecord_name))
                .setContentTitle(notificationTitle)
                .setContentText(getResources().getString(R.string.screenrecord_stop_text))
                .setUsesChronometer(true)
                .setColorized(true)
@@ -332,8 +354,7 @@ public class RecordingService extends Service {

        Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_screenrecord)
                .setContentTitle(getResources().getString(R.string.screenrecord_name))
                .setContentText(getResources().getString(R.string.screenrecord_save_message))
                .setContentTitle(getResources().getString(R.string.screenrecord_save_message))
                .setContentIntent(PendingIntent.getActivity(
                        this,
                        REQUEST_CODE,
Loading