Binding Pwr+VolDown to take screenshot.
Change-Id: I77b018538f6bc870f59df0b5336ba95f4582beec
This commit is contained in:
@@ -25,6 +25,11 @@
|
||||
android:exported="true"
|
||||
/>
|
||||
|
||||
<!-- started from PhoneWindowManager
|
||||
TODO: Should have an android:permission attribute -->
|
||||
<service android:name=".screenshot.TakeScreenshotService"
|
||||
android:exported="false" />
|
||||
|
||||
<activity android:name=".usb.UsbPreferenceActivity"
|
||||
android:theme="@*android:style/Theme.Holo.Dialog.Alert"
|
||||
android:excludeFromRecents="true">
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 358 B |
Binary file not shown.
|
After Width: | Height: | Size: 358 B |
40
packages/SystemUI/res/layout/global_screenshot.xml
Normal file
40
packages/SystemUI/res/layout/global_screenshot.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 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.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ImageView android:id="@+id/global_screenshot_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FF000000"
|
||||
android:visibility="gone" />
|
||||
<FrameLayout
|
||||
android:id="@+id/global_screenshot_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/global_screenshot_background"
|
||||
android:visibility="gone">
|
||||
<ImageView android:id="@+id/global_screenshot"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true" />
|
||||
</FrameLayout>
|
||||
<ImageView android:id="@+id/global_screenshot_flash"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFFFFFFF"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
@@ -165,4 +165,9 @@
|
||||
<string name="use_ptp_button_title">Mount as a camera (PTP)</string>
|
||||
<!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
|
||||
<string name="installer_cd_button_title">Install Android File Transfer application for Mac</string>
|
||||
|
||||
<!-- toast message displayed when a screenshot is saved to the Gallery. -->
|
||||
<string name="screenshot_saving_toast">Screenshot saved to Gallery</string>
|
||||
<!-- toast message displayed when we fail to take a screenshot. -->
|
||||
<string name="screenshot_failed_toast">Could not save screenshot</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.screenshot;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Binder;
|
||||
import android.os.Environment;
|
||||
import android.os.ServiceManager;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.Thread;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* POD used in the AsyncTask which saves an image in the background.
|
||||
*/
|
||||
class SaveImageInBackgroundData {
|
||||
Context context;
|
||||
Bitmap image;
|
||||
int result;
|
||||
}
|
||||
|
||||
/**
|
||||
* An AsyncTask that saves an image to the media store in the background.
|
||||
*/
|
||||
class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
|
||||
SaveImageInBackgroundData> {
|
||||
private static final String TAG = "SaveImageInBackgroundTask";
|
||||
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
|
||||
private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/Screenshot_%s-%d.png";
|
||||
|
||||
@Override
|
||||
protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
|
||||
if (params.length != 1) return null;
|
||||
|
||||
Context context = params[0].context;
|
||||
Bitmap image = params[0].image;
|
||||
|
||||
try{
|
||||
long currentTime = System.currentTimeMillis();
|
||||
String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime));
|
||||
String imageDir = Environment.getExternalStoragePublicDirectory(
|
||||
Environment.DIRECTORY_PICTURES).getAbsolutePath();
|
||||
String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE,
|
||||
imageDir, SCREENSHOTS_DIR_NAME,
|
||||
date, currentTime % 1000);
|
||||
|
||||
// Save the screenshot to the MediaStore
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath);
|
||||
values.put(MediaStore.Images.ImageColumns.TITLE, "Screenshot");
|
||||
values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "Screenshot");
|
||||
values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime);
|
||||
values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime);
|
||||
values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime);
|
||||
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
|
||||
Uri uri = context.getContentResolver().insert(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
||||
|
||||
OutputStream out = context.getContentResolver().openOutputStream(uri);
|
||||
image.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
params[0].result = 0;
|
||||
}catch(IOException e){
|
||||
params[0].result = 1;
|
||||
}
|
||||
|
||||
return params[0];
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(SaveImageInBackgroundData params) {
|
||||
if (params.result > 0) {
|
||||
// Show a message that we've failed to save the image to disk
|
||||
Toast.makeText(params.context, R.string.screenshot_failed_toast,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
// Show a message that we've saved the screenshot to disk
|
||||
Toast.makeText(params.context, R.string.screenshot_saving_toast,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* - Performance when over gl surfaces? Ie. Gallery
|
||||
* - what do we say in the Toast? Which icon do we get if the user uses another
|
||||
* type of gallery?
|
||||
*/
|
||||
class GlobalScreenshot {
|
||||
private static final String TAG = "GlobalScreenshot";
|
||||
private static final int SCREENSHOT_FADE_IN_DURATION = 900;
|
||||
private static final int SCREENSHOT_FADE_OUT_DELAY = 1000;
|
||||
private static final int SCREENSHOT_FADE_OUT_DURATION = 450;
|
||||
private static final int TOAST_FADE_IN_DURATION = 500;
|
||||
private static final int TOAST_FADE_OUT_DELAY = 1000;
|
||||
private static final int TOAST_FADE_OUT_DURATION = 500;
|
||||
private static final float BACKGROUND_ALPHA = 0.65f;
|
||||
private static final float SCREENSHOT_SCALE = 0.85f;
|
||||
private static final float SCREENSHOT_MIN_SCALE = 0.7f;
|
||||
private static final float SCREENSHOT_ROTATION = -6.75f; // -12.5f;
|
||||
|
||||
private Context mContext;
|
||||
private LayoutInflater mLayoutInflater;
|
||||
private IWindowManager mIWindowManager;
|
||||
private WindowManager mWindowManager;
|
||||
private WindowManager.LayoutParams mWindowLayoutParams;
|
||||
private Display mDisplay;
|
||||
private DisplayMetrics mDisplayMetrics;
|
||||
private Matrix mDisplayMatrix;
|
||||
|
||||
private Bitmap mScreenBitmap;
|
||||
private View mScreenshotLayout;
|
||||
private ImageView mBackgroundView;
|
||||
private FrameLayout mScreenshotContainerView;
|
||||
private ImageView mScreenshotView;
|
||||
|
||||
private AnimatorSet mScreenshotAnimation;
|
||||
|
||||
// General use cubic interpolator
|
||||
final TimeInterpolator mCubicInterpolator = new TimeInterpolator() {
|
||||
public float getInterpolation(float t) {
|
||||
return t*t*t;
|
||||
}
|
||||
};
|
||||
// The interpolator used to control the background alpha at the start of the animation
|
||||
final TimeInterpolator mBackgroundViewAlphaInterpolator = new TimeInterpolator() {
|
||||
public float getInterpolation(float t) {
|
||||
float tStep = 0.35f;
|
||||
if (t < tStep) {
|
||||
return t * (1f / tStep);
|
||||
} else {
|
||||
return 1f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param context everything needs a context :(
|
||||
*/
|
||||
public GlobalScreenshot(Context context) {
|
||||
mContext = context;
|
||||
mLayoutInflater = (LayoutInflater)
|
||||
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
// Inflate the screenshot layout
|
||||
mDisplayMetrics = new DisplayMetrics();
|
||||
mDisplayMatrix = new Matrix();
|
||||
mScreenshotLayout = mLayoutInflater.inflate(R.layout.global_screenshot, null);
|
||||
mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
|
||||
mScreenshotContainerView = (FrameLayout) mScreenshotLayout.findViewById(R.id.global_screenshot_container);
|
||||
mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
|
||||
mScreenshotLayout.setFocusable(true);
|
||||
mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
// Intercept and ignore all touch events
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Setup the window that we are going to use
|
||||
mIWindowManager = IWindowManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.WINDOW_SERVICE));
|
||||
mWindowLayoutParams = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
|
||||
WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
|
||||
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED_SYSTEM
|
||||
| WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
mWindowLayoutParams.token = new Binder();
|
||||
mWindowLayoutParams.setTitle("ScreenshotAnimation");
|
||||
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
mDisplay = mWindowManager.getDefaultDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new worker thread and saves the screenshot to the media store.
|
||||
*/
|
||||
private void saveScreenshotInWorkerThread() {
|
||||
SaveImageInBackgroundData data = new SaveImageInBackgroundData();
|
||||
data.context = mContext;
|
||||
data.image = mScreenBitmap;
|
||||
new SaveImageInBackgroundTask().execute(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current display rotation in degrees
|
||||
*/
|
||||
private float getDegreesForRotation(int value) {
|
||||
switch (value) {
|
||||
case Surface.ROTATION_90:
|
||||
return 90f;
|
||||
case Surface.ROTATION_180:
|
||||
return 180f;
|
||||
case Surface.ROTATION_270:
|
||||
return 270f;
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a screenshot of the current display and shows an animation.
|
||||
*/
|
||||
void takeScreenshot() {
|
||||
// We need to orient the screenshot correctly (and the Surface api seems to take screenshots
|
||||
// only in the natural orientation of the device :!)
|
||||
mDisplay.getRealMetrics(mDisplayMetrics);
|
||||
float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
|
||||
float degrees = getDegreesForRotation(mDisplay.getRotation());
|
||||
boolean requiresRotation = (degrees > 0);
|
||||
if (requiresRotation) {
|
||||
// Get the dimensions of the device in its native orientation
|
||||
mDisplayMatrix.reset();
|
||||
mDisplayMatrix.preRotate(-degrees);
|
||||
mDisplayMatrix.mapPoints(dims);
|
||||
dims[0] = Math.abs(dims[0]);
|
||||
dims[1] = Math.abs(dims[1]);
|
||||
}
|
||||
mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
|
||||
if (requiresRotation) {
|
||||
// Rotate the screenshot to the current orientation
|
||||
Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
|
||||
mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(ss);
|
||||
c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
|
||||
c.rotate(360f - degrees);
|
||||
c.translate(-dims[0] / 2, -dims[1] / 2);
|
||||
c.drawBitmap(mScreenBitmap, 0, 0, null);
|
||||
mScreenBitmap = ss;
|
||||
}
|
||||
|
||||
// If we couldn't take the screenshot, notify the user
|
||||
if (mScreenBitmap == null) {
|
||||
Toast.makeText(mContext, R.string.screenshot_failed_toast,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the post-screenshot animation
|
||||
startAnimation();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts the animation after taking the screenshot
|
||||
*/
|
||||
private void startAnimation() {
|
||||
// Add the view for the animation
|
||||
mScreenshotView.setImageBitmap(mScreenBitmap);
|
||||
mScreenshotLayout.requestFocus();
|
||||
|
||||
// Setup the animation with the screenshot just taken
|
||||
if (mScreenshotAnimation != null) {
|
||||
mScreenshotAnimation.end();
|
||||
}
|
||||
|
||||
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
|
||||
ValueAnimator screenshotFadeInAnim = createScreenshotFadeInAnimation();
|
||||
ValueAnimator screenshotFadeOutAnim = createScreenshotFadeOutAnimation();
|
||||
mScreenshotAnimation = new AnimatorSet();
|
||||
mScreenshotAnimation.play(screenshotFadeInAnim).before(screenshotFadeOutAnim);
|
||||
mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Save the screenshot once we have a bit of time now
|
||||
saveScreenshotInWorkerThread();
|
||||
|
||||
mWindowManager.removeView(mScreenshotLayout);
|
||||
}
|
||||
});
|
||||
mScreenshotAnimation.start();
|
||||
}
|
||||
private ValueAnimator createScreenshotFadeInAnimation() {
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
|
||||
anim.setInterpolator(mCubicInterpolator);
|
||||
anim.setDuration(SCREENSHOT_FADE_IN_DURATION);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mBackgroundView.setVisibility(View.VISIBLE);
|
||||
mScreenshotContainerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener(new AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float t = ((Float) animation.getAnimatedValue()).floatValue();
|
||||
mBackgroundView.setAlpha(mBackgroundViewAlphaInterpolator.getInterpolation(t) *
|
||||
BACKGROUND_ALPHA);
|
||||
float scaleT = SCREENSHOT_SCALE + (1f - t) * SCREENSHOT_SCALE;
|
||||
mScreenshotContainerView.setAlpha(t*t*t*t);
|
||||
mScreenshotContainerView.setScaleX(scaleT);
|
||||
mScreenshotContainerView.setScaleY(scaleT);
|
||||
mScreenshotContainerView.setRotation(t * SCREENSHOT_ROTATION);
|
||||
}
|
||||
});
|
||||
return anim;
|
||||
}
|
||||
private ValueAnimator createScreenshotFadeOutAnimation() {
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
|
||||
anim.setInterpolator(mCubicInterpolator);
|
||||
anim.setStartDelay(SCREENSHOT_FADE_OUT_DELAY);
|
||||
anim.setDuration(SCREENSHOT_FADE_OUT_DURATION);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mBackgroundView.setVisibility(View.GONE);
|
||||
mScreenshotContainerView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener(new AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float t = ((Float) animation.getAnimatedValue()).floatValue();
|
||||
float scaleT = SCREENSHOT_MIN_SCALE +
|
||||
t*(SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE);
|
||||
mScreenshotContainerView.setAlpha(t);
|
||||
mScreenshotContainerView.setScaleX(scaleT);
|
||||
mScreenshotContainerView.setScaleY(scaleT);
|
||||
mBackgroundView.setAlpha(t * t * BACKGROUND_ALPHA);
|
||||
}
|
||||
});
|
||||
return anim;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.screenshot;
|
||||
|
||||
import android.app.Service;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.hardware.usb.UsbAccessory;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.app.AlertActivity;
|
||||
import com.android.internal.app.AlertController;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
public class TakeScreenshotService extends Service {
|
||||
private static final String TAG = "TakeScreenshotService";
|
||||
|
||||
private static GlobalScreenshot mScreenshot;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (mScreenshot == null) {
|
||||
mScreenshot = new GlobalScreenshot(this);
|
||||
}
|
||||
mScreenshot.takeScreenshot();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
@@ -372,6 +373,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// What we do when the user long presses on home
|
||||
private int mLongPressOnHomeBehavior = -1;
|
||||
|
||||
// Screenshot trigger states
|
||||
private boolean mVolumeDownTriggered;
|
||||
private boolean mPowerDownTriggered;
|
||||
|
||||
ShortcutManager mShortcutManager;
|
||||
PowerManager.WakeLock mBroadcastWakeLock;
|
||||
|
||||
@@ -2339,6 +2344,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
private void takeScreenshot() {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ComponentName cn = new ComponentName("com.android.systemui",
|
||||
"com.android.systemui.screenshot.TakeScreenshotService");
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(cn);
|
||||
ServiceConnection conn = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {}
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {}
|
||||
};
|
||||
mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
|
||||
mContext.unbindService(conn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
|
||||
@@ -2398,6 +2423,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// Handle special keys.
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
if (down) {
|
||||
// If the power key down was already triggered, take the screenshot
|
||||
if (mPowerDownTriggered) {
|
||||
// Dismiss the power-key longpress
|
||||
mHandler.removeCallbacks(mPowerLongPress);
|
||||
mPowerKeyHandled = true;
|
||||
|
||||
// Take the screenshot
|
||||
takeScreenshot();
|
||||
|
||||
// Prevent the event from being passed through to the current activity
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
break;
|
||||
}
|
||||
mVolumeDownTriggered = true;
|
||||
} else {
|
||||
mVolumeDownTriggered = false;
|
||||
}
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||
if (down) {
|
||||
@@ -2478,6 +2521,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
case KeyEvent.KEYCODE_POWER: {
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
if (down) {
|
||||
// If the volume down key has been triggered, then just take the screenshot
|
||||
if (mVolumeDownTriggered) {
|
||||
// Take the screenshot
|
||||
takeScreenshot();
|
||||
mPowerKeyHandled = true;
|
||||
|
||||
// Prevent the event from being passed through to the current activity
|
||||
break;
|
||||
}
|
||||
mPowerDownTriggered = true;
|
||||
|
||||
|
||||
ITelephony telephonyService = getTelephonyService();
|
||||
boolean hungUp = false;
|
||||
if (telephonyService != null) {
|
||||
@@ -2499,6 +2554,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
interceptPowerKeyDown(!isScreenOn || hungUp);
|
||||
} else {
|
||||
mPowerDownTriggered = false;
|
||||
if (interceptPowerKeyUp(canceled)) {
|
||||
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user