diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-03-16 17:15:53 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2015-03-17 16:45:51 -0700 |
commit | 27eac1d58fe0b7ca3a2e27f5ed64eff232745f45 (patch) | |
tree | c1f0dc2a368ab1c7db1be81dc02b020eea0d1628 /services | |
parent | 7438f814f16ff1ced53d93a2fe9e3973490f3843 (diff) | |
download | frameworks_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')
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; } |