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

Commit a2cd19e3 authored by Alison Cichowlas's avatar Alison Cichowlas
Browse files

Screenshot global actions item.

Refactor TakeScreenshot code out of PhoneWindowManager;
add power menu item for Screenshot.

Test: runtest systemui

Change-Id: Ie8602386cd59f8fd991369d2117f7c4d76f65e41
parent 2cd5144d
Loading
Loading
Loading
Loading
+128 −0
Original line number Diff line number Diff line
package com.android.internal.util;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;

public class ScreenshotHelper {
    private static final String TAG = "ScreenshotHelper";

    private static final String SYSUI_PACKAGE = "com.android.systemui";
    private static final String SYSUI_SCREENSHOT_SERVICE =
            "com.android.systemui.screenshot.TakeScreenshotService";
    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";

    // Time until we give up on the screenshot & show an error instead.
    private final int SCREENSHOT_TIMEOUT_MS = 10000;

    private final Object mScreenshotLock = new Object();
    private ServiceConnection mScreenshotConnection = null;
    private final Context mContext;

    public ScreenshotHelper(Context context) {
        mContext = context;
    }

    public void takeScreenshot(final int screenshotType, final boolean hasStatus,
            final boolean hasNav, Handler handler) {
        synchronized (mScreenshotLock) {
            if (mScreenshotConnection != null) {
                return;
            }
            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
                    SYSUI_SCREENSHOT_SERVICE);
            final Intent serviceIntent = new Intent();

            final Runnable mScreenshotTimeout = new Runnable() {
                @Override public void run() {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != null) {
                            mContext.unbindService(mScreenshotConnection);
                            mScreenshotConnection = null;
                            notifyScreenshotError();
                        }
                    }
                }
            };

            serviceIntent.setComponent(serviceComponent);
            ServiceConnection conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != this) {
                            return;
                        }
                        Messenger messenger = new Messenger(service);
                        Message msg = Message.obtain(null, screenshotType);
                        final ServiceConnection myConn = this;
                        Handler h = new Handler(handler.getLooper()) {
                            @Override
                            public void handleMessage(Message msg) {
                                synchronized (mScreenshotLock) {
                                    if (mScreenshotConnection == myConn) {
                                        mContext.unbindService(mScreenshotConnection);
                                        mScreenshotConnection = null;
                                        handler.removeCallbacks(mScreenshotTimeout);
                                    }
                                }
                            }
                        };
                        msg.replyTo = new Messenger(h);
                        msg.arg1 = hasStatus ? 1: 0;
                        msg.arg2 = hasNav ? 1: 0;
                        try {
                            messenger.send(msg);
                        } catch (RemoteException e) {
                            Log.e(TAG, "Couldn't take screenshot: " + e);
                        }
                    }
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != null) {
                            mContext.unbindService(mScreenshotConnection);
                            mScreenshotConnection = null;
                            handler.removeCallbacks(mScreenshotTimeout);
                            notifyScreenshotError();
                        }
                    }
                }
            };
            if (mContext.bindServiceAsUser(serviceIntent, conn,
                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                    UserHandle.CURRENT)) {
                mScreenshotConnection = conn;
                handler.postDelayed(mScreenshotTimeout, SCREENSHOT_TIMEOUT_MS);
            }
        }
    }

    /**
     * Notifies the screenshot service to show an error.
     */
    private void notifyScreenshotError() {
        // If the service process is killed, then ask it to clean up after itself
        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
                SYSUI_SCREENSHOT_ERROR_RECEIVER);
        // Broadcast needs to have a valid action.  We'll just pick
        // a generic one, since the receiver here doesn't care.
        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
        errorIntent.setComponent(errorComponent);
        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
                Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
    }

}
+33 −0
Original line number Diff line number Diff line
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24.0dp"
    android:height="24.0dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:pathData="M0,0h24v24H0V0z"
        android:fillColor="#00000000"/>
    <path
        android:fillColor="#FF000000"
        android:pathData="M17.0,1.0L7.0,1.0C5.9,1.0 5.0,1.9 5.0,3.0l0.0,18.0c0.0,1.1 0.9,2.0 2.0,2.0l10.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L19.0,3.0C19.0,1.9 18.1,1.0 17.0,1.0zM17.0,20.0L7.0,20.0L7.0,4.0l10.0,0.0L17.0,20.0z"/>
    <path
        android:fillColor="#FF000000"
        android:pathData="M13.0,6.0l-4.0,0.0 0.0,4.0 1.5,0.0 0.0,-2.5 2.5,0.0z"/>
    <path
        android:fillColor="#FF000000"
        android:pathData="M11.0,18.0l4.0,0.0 0.0,-4.0 -1.5,0.0 0.0,2.5 -2.5,0.0z"/>
</vector>
+1 −0
Original line number Diff line number Diff line
@@ -2481,6 +2481,7 @@
    <string-array translatable="false" name="config_globalActionsList">
        <item>power</item>
        <item>restart</item>
        <item>screenshot</item>
        <item>logout</item>
        <item>bugreport</item>
        <item>users</item>
+3 −3
Original line number Diff line number Diff line
@@ -484,6 +484,9 @@
    <!-- label for item that logouts the current user -->
    <string name="global_action_logout">End session</string>

    <!-- label for screenshot item in power menu -->
    <string name="global_action_screenshot">Screenshot</string>

    <!-- Take bug report menu title [CHAR LIMIT=NONE] -->
    <string name="bugreport_title">Take bug report</string>
    <!-- Message in bugreport dialog describing what it does [CHAR LIMIT=NONE] -->
@@ -4800,13 +4803,10 @@
    <!--Battery saver warning. STOPSHIP: Remove it eventually. -->
    <string name="battery_saver_warning_title" translatable="false">Extreme battery saver</string>


    <!-- Label for the uninstall button on the harmful app warning dialog. -->
    <string name="harmful_app_warning_uninstall">Uninstall</string>
    <!-- Label for the launch anyway button on the harmful app warning dialog. -->
    <string name="harmful_app_warning_launch_anyway">Launch anyway</string>
    <!-- Title for the harmful app warning dialog. -->
    <string name="harmful_app_warning_title">Uninstall harmful app?</string>


</resources>
+3 −1
Original line number Diff line number Diff line
@@ -1722,6 +1722,7 @@
  <java-symbol type="string" name="global_action_lockdown" />
  <java-symbol type="string" name="global_action_voice_assist" />
  <java-symbol type="string" name="global_action_assist" />
  <java-symbol type="string" name="global_action_screenshot" />
  <java-symbol type="string" name="invalidPuk" />
  <java-symbol type="string" name="lockscreen_carrier_default" />
  <java-symbol type="style" name="Animation.LockScreen" />
@@ -2889,8 +2890,9 @@

  <java-symbol type="bool" name="config_permissionReviewRequired" />


  <!-- Global actions icons -->
  <java-symbol type="drawable" name="ic_restart" />
  <java-symbol type="drawable" name="ic_screenshot" />

  <java-symbol type="drawable" name="emergency_icon" />

Loading