summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2015-03-16 17:15:53 -0700
committerDianne Hackborn <hackbod@google.com>2015-03-17 16:45:51 -0700
commit27eac1d58fe0b7ca3a2e27f5ed64eff232745f45 (patch)
treec1f0dc2a368ab1c7db1be81dc02b020eea0d1628 /services
parent7438f814f16ff1ced53d93a2fe9e3973490f3843 (diff)
downloadframeworks_base-27eac1d58fe0b7ca3a2e27f5ed64eff232745f45.zip
frameworks_base-27eac1d58fe0b7ca3a2e27f5ed64eff232745f45.tar.gz
frameworks_base-27eac1d58fe0b7ca3a2e27f5ed64eff232745f45.tar.bz2
Add ability to get a screenshot for assist.
New flag you pass in to startSession() to say you want it, new callback on VoiceInteractionSession to receive it. Change-Id: I61fdcfdee41a60d46036a2ef16681a9b4181115a
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java75
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java100
3 files changed, 125 insertions, 54 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4bb265d..b102a07 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -132,8 +132,6 @@ final class ActivityStack {
// convertToTranslucent().
static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
- static final boolean SCREENSHOT_FORCE_565 = ActivityManager.isLowRamDeviceStatic();
-
enum ActivityState {
INITIALIZING,
RESUMED,
@@ -790,7 +788,7 @@ final class ActivityStack {
if (w > 0) {
if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tTaking screenshot");
return mWindowManager.screenshotApplications(who.appToken, Display.DEFAULT_DISPLAY,
- w, h, SCREENSHOT_FORCE_565);
+ w, h);
}
Slog.e(TAG, "Invalid thumbnail dimensions: " + w + "x" + h);
return null;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 99bad07..9a97a2d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -29,6 +29,7 @@ import android.view.IWindowId;
import android.view.IWindowSessionCallback;
import android.view.WindowContentFrameStats;
+import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
@@ -38,6 +39,7 @@ import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AttributeCache;
import com.android.server.DisplayThread;
import com.android.server.EventLogTags;
+import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.Watchdog;
@@ -5997,26 +5999,57 @@ public class WindowManagerService extends IWindowManager.Stub
* Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
* In portrait mode, it grabs the upper region of the screen based on the vertical dimension
* of the target image.
+ */
+ @Override
+ public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
+ if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
+ "requestAssistScreenshot()")) {
+ throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+ }
+
+ FgThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1,
+ true);
+ try {
+ receiver.send(bm);
+ } catch (RemoteException e) {
+ }
+ }
+ });
+
+ return true;
+ }
+
+ /**
+ * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
+ * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
+ * of the target image.
*
* @param displayId the Display to take a screenshot of.
* @param width the width of the target bitmap
* @param height the height of the target bitmap
- * @param force565 if true the returned bitmap will be RGB_565, otherwise it
- * will be the same config as the surface
*/
@Override
- public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
- int height, boolean force565) {
+ public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
"screenshotApplications()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
+ return screenshotApplicationsInner(appToken, displayId, width, height, false);
+ }
- final DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent == null) {
- if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
- + ": returning null. No Display for displayId=" + displayId);
- return null;
+ Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
+ boolean includeFullDisplay) {
+ final DisplayContent displayContent;
+ synchronized(mWindowMap) {
+ displayContent = getDisplayContentLocked(displayId);
+ if (displayContent == null) {
+ if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
+ + ": returning null. No Display for displayId=" + displayId);
+ return null;
+ }
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
int dw = displayInfo.logicalWidth;
@@ -6033,9 +6066,6 @@ public class WindowManagerService extends IWindowManager.Stub
final Rect frame = new Rect();
final Rect stackBounds = new Rect();
- float scale = 0;
- int rot = Surface.ROTATION_0;
-
boolean screenshotReady;
int minLayer;
if (appToken == null) {
@@ -6116,7 +6146,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
// Don't include wallpaper in bounds calculation
- if (!ws.mIsWallpaper) {
+ if (!includeFullDisplay && !ws.mIsWallpaper) {
final Rect wf = ws.mFrame;
final Rect cr = ws.mContentInsets;
int left = wf.left + cr.left;
@@ -6170,8 +6200,21 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
- // Constrain frame to the screen size.
- frame.intersect(0, 0, dw, dh);
+ if (!includeFullDisplay) {
+ // Constrain frame to the screen size.
+ frame.intersect(0, 0, dw, dh);
+ } else {
+ // Caller just wants entire display.
+ frame.set(0, 0, dw, dh);
+ }
+
+
+ if (width < 0) {
+ width = frame.width();
+ }
+ if (height < 0) {
+ height = frame.height();
+ }
// Tell surface flinger what part of the image to crop. Take the top
// right part of the application, and crop the larger dimension to fit.
@@ -6185,7 +6228,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
// The screenshot API does not apply the current screen rotation.
- rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
+ int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 30d97b9..7a379c2 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -26,6 +26,7 @@ import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -39,6 +40,7 @@ import android.service.voice.VoiceInteractionService;
import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;
+import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
@@ -70,6 +72,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
IVoiceInteractor mInteractor;
boolean mHaveAssistData;
Bundle mAssistData;
+ boolean mHaveScreenshot;
+ Bitmap mScreenshot;
public interface Callback {
public void sessionConnectionGone(VoiceInteractionSessionConnection connection);
@@ -91,7 +95,20 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
if (mShown) {
mHaveAssistData = true;
mAssistData = resultData;
- deliverAssistData();
+ deliverSessionDataLocked();
+ }
+ }
+ }
+ };
+
+ final IAssistScreenshotReceiver mScreenshotReceiver = new IAssistScreenshotReceiver.Stub() {
+ @Override
+ public void send(Bitmap screenshot) throws RemoteException {
+ synchronized (mLock) {
+ if (mShown) {
+ mHaveScreenshot = true;
+ mScreenshot = screenshot;
+ deliverSessionDataLocked();
}
}
}
@@ -144,6 +161,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShown = true;
mShowArgs = args;
mShowFlags = flags;
+ mHaveAssistData = false;
if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) {
try {
mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
@@ -151,9 +169,17 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
} catch (RemoteException e) {
}
} else {
- mHaveAssistData = false;
mAssistData = null;
}
+ mHaveScreenshot = false;
+ if ((flags&VoiceInteractionService.START_WITH_SCREENSHOT) != 0) {
+ try {
+ mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
+ } catch (RemoteException e) {
+ }
+ } else {
+ mScreenshot = null;
+ }
if (mSession != null) {
try {
mSession.show(mShowArgs, mShowFlags);
@@ -161,7 +187,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShowFlags = 0;
} catch (RemoteException e) {
}
- deliverAssistData();
+ deliverSessionDataLocked();
}
return true;
}
@@ -210,39 +236,50 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
}
}
- void deliverAssistData() {
- if (mSession == null || !mHaveAssistData) {
+ void deliverSessionDataLocked() {
+ if (mSession == null) {
return;
}
- if (mAssistData != null) {
- int uid = mAssistData.getInt(Intent.EXTRA_ASSIST_UID, -1);
- if (uid >= 0) {
- Bundle assistContext = mAssistData.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
- if (assistContext != null) {
- AssistContent content = AssistContent.getAssistContent(assistContext);
- if (content != null) {
- Intent intent = content.getIntent();
- if (intent != null) {
- ClipData data = intent.getClipData();
- if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
- grantClipDataPermissions(data, intent.getFlags(), uid,
- mCallingUid, mSessionComponentName.getPackageName());
+ if (mHaveAssistData) {
+ if (mAssistData != null) {
+ int uid = mAssistData.getInt(Intent.EXTRA_ASSIST_UID, -1);
+ if (uid >= 0) {
+ Bundle assistContext = mAssistData.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
+ if (assistContext != null) {
+ AssistContent content = AssistContent.getAssistContent(assistContext);
+ if (content != null) {
+ Intent intent = content.getIntent();
+ if (intent != null) {
+ ClipData data = intent.getClipData();
+ if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
+ grantClipDataPermissions(data, intent.getFlags(), uid,
+ mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ ClipData data = content.getClipData();
+ if (data != null) {
+ grantClipDataPermissions(data,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ uid, mCallingUid, mSessionComponentName.getPackageName());
}
- }
- ClipData data = content.getClipData();
- if (data != null) {
- grantClipDataPermissions(data, Intent.FLAG_GRANT_READ_URI_PERMISSION,
- uid, mCallingUid, mSessionComponentName.getPackageName());
}
}
}
}
- }
- try {
- mSession.handleAssist(mAssistData);
+ try {
+ mSession.handleAssist(mAssistData);
+ } catch (RemoteException e) {
+ }
mAssistData = null;
mHaveAssistData = false;
- } catch (RemoteException e) {
+ }
+ if (mHaveScreenshot) {
+ try {
+ mSession.handleScreenshot(mScreenshot);
+ } catch (RemoteException e) {
+ }
+ mScreenshot = null;
+ mHaveScreenshot = false;
}
}
@@ -288,14 +325,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShowFlags = 0;
} catch (RemoteException e) {
}
- if (mHaveAssistData) {
- try {
- session.handleAssist(mAssistData);
- mAssistData = null;
- mHaveAssistData = false;
- } catch (RemoteException e) {
- }
- }
+ deliverSessionDataLocked();
}
return true;
}