Fix issue #5128639: SystemUI grows by 10MB after taking a screenshot

We now do the screenshot in a separate process.

Also change the recents panel to not use hardware acceleration
on lower-end devices.  And improve how it gets shown to not
load all data up-front which results in a long delay when you have
lots of recents.

Change-Id: Ia309a90f9939e5405758621b3f7114597bd0c02a
This commit is contained in:
Dianne Hackborn
2011-08-17 16:20:47 -07:00
parent 9a5505f025
commit fc8fa63861
13 changed files with 339 additions and 84 deletions

View File

@@ -155,6 +155,7 @@
<assign-permission name="android.permission.DEVICE_POWER" uid="shell" />
<assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />
<assign-permission name="android.permission.BACKUP" uid="shell" />
<assign-permission name="android.permission.FORCE_STOP_PACKAGES" uid="shell" />
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />

View File

@@ -277,10 +277,19 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
*/
public boolean setDrawableByLayerId(int id, Drawable drawable) {
final ChildDrawable[] layers = mLayerState.mChildren;
drawable.setCallback(this);
for (int i = mLayerState.mNum - 1; i >= 0; i--) {
if (layers[i].mId == id) {
if (layers[i].mDrawable != null) {
if (drawable != null) {
Rect bounds = layers[i].mDrawable.getBounds();
drawable.setBounds(bounds);
}
layers[i].mDrawable.setCallback(null);
}
if (drawable != null) {
drawable.setCallback(this);
}
layers[i].mDrawable = drawable;
return true;
}

View File

@@ -29,6 +29,7 @@
<!-- started from PhoneWindowManager
TODO: Should have an android:permission attribute -->
<service android:name=".screenshot.TakeScreenshotService"
android:process=":screenshot"
android:exported="false" />
<service android:name=".LoadAverageService"

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
<!-- Copyright (C) 2010 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.
@@ -13,7 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/recents_thumbnail_bg" android:id="@+id/base_layer"/>
<item android:drawable="@drawable/recents_thumbnail_overlay" android:id="@+id/overlay_layer"/>
</layer-list>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_shortAnimTime"
/>

View File

@@ -32,8 +32,14 @@
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:scaleType="center"
android:clickable="true"
android:background="@drawable/recents_thumbnail_layers"
/>
android:background="@drawable/recents_thumbnail_bg"
android:foreground="@drawable/recents_thumbnail_overlay">
<ImageView android:id="@+id/app_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
/>
</FrameLayout>
<ImageView android:id="@+id/app_icon"
android:layout_width="wrap_content"
@@ -45,6 +51,7 @@
android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width"
android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height"
android:adjustViewBounds="true"
android:visibility="invisible"
/>
<TextView android:id="@+id/app_label"
@@ -60,6 +67,7 @@
android:layout_marginLeft="@dimen/recents_thumbnail_bg_padding_left"
android:singleLine="true"
android:ellipsize="marquee"
android:visibility="invisible"
/>
<TextView android:id="@+id/app_description"

View File

@@ -32,8 +32,14 @@
android:clickable="true"
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:scaleType="center"
android:background="@drawable/recents_thumbnail_layers"
/>
android:background="@drawable/recents_thumbnail_bg"
android:foreground="@drawable/recents_thumbnail_overlay">
<ImageView android:id="@+id/app_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
/>
</FrameLayout>
<ImageView android:id="@+id/app_icon"
android:layout_width="wrap_content"

View File

@@ -32,8 +32,14 @@
android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
android:scaleType="center"
android:clickable="true"
android:background="@drawable/recents_thumbnail_layers"
/>
android:background="@drawable/recents_thumbnail_bg"
android:foreground="@drawable/recents_thumbnail_overlay">
<ImageView android:id="@+id/app_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
/>
</FrameLayout>
<ImageView android:id="@+id/app_icon"
android:layout_width="wrap_content"

View File

@@ -41,6 +41,10 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Process;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -51,12 +55,15 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.android.systemui.R;
@@ -68,11 +75,12 @@ import com.android.systemui.statusbar.tablet.TabletStatusBar;
public class RecentsPanelView extends RelativeLayout
implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener {
static final String TAG = "RecentsListView";
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG;
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
private static final int DISPLAY_TASKS = 20;
private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps
private StatusBar mBar;
private ArrayList<ActivityDescription> mActivityDescriptions;
private AsyncTask<Void, Integer, Void> mThumbnailLoader;
private int mIconDpi;
private View mRecentsScrim;
private View mRecentsGlowView;
@@ -87,31 +95,47 @@ public class RecentsPanelView extends RelativeLayout
private Choreographer mChoreo;
private View mRecentsDismissButton;
private ActivityDescriptionAdapter mListAdapter;
private final Handler mHandler = new Handler();
/* package */ final static class ActivityDescription {
/* package */ final class ActivityDescription {
final ActivityManager.RecentTaskInfo recentTaskInfo;
final ResolveInfo resolveInfo;
int taskId; // application task id for curating apps
Bitmap thumbnail; // generated by Activity.onCreateThumbnail()
Drawable icon; // application package icon
String label; // application package label
CharSequence description; // generated by Activity.onCreateDescription()
Intent intent; // launch intent for application
Matrix matrix; // arbitrary rotation matrix to correct orientation
String packageName; // used to override animations (see onClick())
int position; // position in list
public ActivityDescription(Bitmap _thumbnail,
Drawable _icon, String _label, CharSequence _desc, Intent _intent,
int _id, int _pos, String _packageName)
{
thumbnail = _thumbnail;
icon = _icon;
label = _label;
description = _desc;
private Bitmap mThumbnail; // generated by Activity.onCreateThumbnail()
private Drawable mIcon; // application package icon
private CharSequence mLabel; // application package label
public ActivityDescription(ActivityManager.RecentTaskInfo _recentInfo,
ResolveInfo _resolveInfo, Intent _intent,
int _id, int _pos, String _packageName) {
recentTaskInfo = _recentInfo;
resolveInfo = _resolveInfo;
intent = _intent;
taskId = _id;
position = _pos;
packageName = _packageName;
}
public CharSequence getLabel() {
return mLabel;
}
public Drawable getIcon() {
return mIcon;
}
public void setThumbnail(Bitmap thumbnail) {
mThumbnail = compositeBitmap(mGlowBitmap, thumbnail);
}
public Bitmap getThumbnail() {
return mThumbnail;
}
}
private final class OnLongClickDelegate implements View.OnLongClickListener {
@@ -126,6 +150,7 @@ public class RecentsPanelView extends RelativeLayout
/* package */ final static class ViewHolder {
View thumbnailView;
ImageView thumbnailViewImage;
ImageView iconView;
TextView labelView;
TextView descriptionView;
@@ -157,6 +182,8 @@ public class RecentsPanelView extends RelativeLayout
convertView = mInflater.inflate(R.layout.status_bar_recent_item, null);
holder = new ViewHolder();
holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
holder.thumbnailViewImage = (ImageView) convertView.findViewById(
R.id.app_thumbnail_image);
holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
@@ -169,11 +196,10 @@ public class RecentsPanelView extends RelativeLayout
final int activityId = mActivityDescriptions.size() - position - 1;
final ActivityDescription activityDescription = mActivityDescriptions.get(activityId);
final Bitmap thumb = activityDescription.thumbnail;
updateDrawable(holder.thumbnailView, compositeBitmap(mGlowBitmap, thumb));
holder.iconView.setImageDrawable(activityDescription.icon);
holder.labelView.setText(activityDescription.label);
holder.descriptionView.setText(activityDescription.description);
holder.thumbnailViewImage.setImageBitmap(activityDescription.getThumbnail());
holder.iconView.setImageDrawable(activityDescription.getIcon());
holder.labelView.setText(activityDescription.getLabel());
holder.descriptionView.setText(activityDescription.recentTaskInfo.description);
holder.thumbnailView.setTag(activityDescription);
holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
holder.activityDescription = activityDescription;
@@ -201,20 +227,6 @@ public class RecentsPanelView extends RelativeLayout
return x >= l && x < r && y >= t && y < b;
}
private void updateDrawable(View thumbnailView, Bitmap bitmap) {
Drawable d = thumbnailView.getBackground();
if (d instanceof LayerDrawable) {
LayerDrawable layerD = (LayerDrawable) d;
Drawable thumb = layerD.findDrawableByLayerId(R.id.base_layer);
if (thumb != null) {
layerD.setDrawableByLayerId(R.id.base_layer,
new BitmapDrawable(getResources(), bitmap));
return;
}
}
Log.w(TAG, "Failed to update drawable");
}
public void show(boolean show, boolean animate) {
if (animate) {
if (mShowing != show) {
@@ -373,12 +385,12 @@ public class RecentsPanelView extends RelativeLayout
}
}
private Drawable getFullResDefaultActivityIcon() {
Drawable getFullResDefaultActivityIcon() {
return getFullResIcon(Resources.getSystem(),
com.android.internal.R.mipmap.sym_def_app_icon);
}
private Drawable getFullResIcon(Resources resources, int iconId) {
Drawable getFullResIcon(Resources resources, int iconId) {
try {
return resources.getDrawableForDensity(iconId, mIconDpi);
} catch (Resources.NotFoundException e) {
@@ -442,15 +454,13 @@ public class RecentsPanelView extends RelativeLayout
final String title = info.loadLabel(pm).toString();
// Drawable icon = info.loadIcon(pm);
Drawable icon = getFullResIcon(resolveInfo, pm);
int id = recentTasks.get(i).id;
int id = recentInfo.id;
if (title != null && title.length() > 0 && icon != null) {
if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title);
ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(
recentInfo.persistentId);
ActivityDescription item = new ActivityDescription(
thumbs != null ? thumbs.mainThumbnail : null,
icon, title, recentInfo.description, intent, id,
index, info.packageName);
ActivityDescription item = new ActivityDescription(recentInfo,
resolveInfo, intent, id, index, info.packageName);
activityDescriptions.add(item);
++index;
} else {
@@ -474,12 +484,137 @@ public class RecentsPanelView extends RelativeLayout
return desc;
}
void loadActivityDescription(ActivityDescription ad, int index) {
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
final PackageManager pm = mContext.getPackageManager();
ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(
ad.recentTaskInfo.persistentId);
CharSequence label = ad.resolveInfo.activityInfo.loadLabel(pm);
Drawable icon = getFullResIcon(ad.resolveInfo, pm);
if (DEBUG) Log.v(TAG, "Loaded bitmap for #" + index + " in "
+ ad + ": " + thumbs.mainThumbnail);
synchronized (ad) {
ad.mLabel = label;
ad.mIcon = icon;
ad.setThumbnail(thumbs.mainThumbnail);
}
}
void applyActivityDescription(ActivityDescription ad, int index, boolean anim) {
synchronized (ad) {
if (mRecentsContainer != null) {
ViewGroup container = mRecentsContainer;
if (container instanceof HorizontalScrollView
|| container instanceof ScrollView) {
container = (ViewGroup)container.findViewById(
R.id.recents_linear_layout);
}
// Look for a view showing this thumbnail, to update.
for (int i=0; i<container.getChildCount(); i++) {
View v = container.getChildAt(i);
if (v.getTag() instanceof ViewHolder) {
ViewHolder h = (ViewHolder)v.getTag();
if (h.activityDescription == ad) {
if (DEBUG) Log.v(TAG, "Updatating thumbnail #" + index + " in "
+ h.activityDescription
+ ": " + ad.getThumbnail());
h.iconView.setImageDrawable(ad.getIcon());
if (anim) {
h.iconView.setAnimation(AnimationUtils.loadAnimation(
mContext, R.anim.recent_appear));
}
h.iconView.setVisibility(View.VISIBLE);
h.labelView.setText(ad.getLabel());
if (anim) {
h.labelView.setAnimation(AnimationUtils.loadAnimation(
mContext, R.anim.recent_appear));
}
h.labelView.setVisibility(View.VISIBLE);
Bitmap thumbnail = ad.getThumbnail();
if (thumbnail != null) {
// Should remove the default image in the frame
// that this now covers, to improve scrolling speed.
// That can't be done until the anim is complete though.
h.thumbnailViewImage.setImageBitmap(thumbnail);
if (anim) {
h.thumbnailViewImage.setAnimation(AnimationUtils.loadAnimation(
mContext, R.anim.recent_appear));
}
h.thumbnailViewImage.setVisibility(View.VISIBLE);
}
}
}
}
}
}
}
private void refreshApplicationList() {
if (mThumbnailLoader != null) {
mThumbnailLoader.cancel(false);
mThumbnailLoader = null;
}
mActivityDescriptions = getRecentTasks();
mListAdapter.notifyDataSetInvalidated();
if (mActivityDescriptions.size() > 0) {
if (DEBUG) Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
updateUiElements(getResources().getConfiguration());
final ArrayList<ActivityDescription> descriptions = mActivityDescriptions;
loadActivityDescription(descriptions.get(0), 0);
applyActivityDescription(descriptions.get(0), 0, false);
if (descriptions.size() > 1) {
mThumbnailLoader = new AsyncTask<Void, Integer, Void>() {
@Override
protected void onProgressUpdate(Integer... values) {
final ActivityDescription ad = descriptions.get(values[0]);
if (!isCancelled()) {
applyActivityDescription(ad, values[0], true);
}
// This is to prevent the loader thread from getting ahead
// of our UI updates.
mHandler.post(new Runnable() {
@Override public void run() {
synchronized (ad) {
ad.notifyAll();
}
}
});
}
@Override
protected Void doInBackground(Void... params) {
final int origPri = Process.getThreadPriority(Process.myTid());
Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE);
long nextTime = SystemClock.uptimeMillis();
for (int i=1; i<descriptions.size(); i++) {
ActivityDescription ad = descriptions.get(i);
loadActivityDescription(ad, i);
long now = SystemClock.uptimeMillis();
nextTime += 200;
if (nextTime > now) {
try {
Thread.sleep(nextTime-now);
} catch (InterruptedException e) {
}
}
if (isCancelled()) {
break;
}
synchronized (ad) {
publishProgress(i);
try {
ad.wait(500);
} catch (InterruptedException e) {
}
}
}
Process.setThreadPriority(origPri);
return null;
}
};
mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
} else {
// Immediately hide this panel
if (DEBUG) Log.v(TAG, "Nothing to show");
@@ -548,7 +683,7 @@ public class RecentsPanelView extends RelativeLayout
public void handleSwipe(View view) {
ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
if (DEBUG) Log.v(TAG, "Jettison " + ad.getLabel());
mActivityDescriptions.remove(ad);
// Handled by widget containers to enable LayoutTransitions properly

View File

@@ -66,20 +66,34 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper
private void update() {
mLinearLayout.removeAllViews();
// Once we can clear the data associated with individual item views,
// we can get rid of the removeAllViews() and the code below will
// recycle them.
for (int i = 0; i < mAdapter.getCount(); i++) {
final View view = mAdapter.getView(i, null, mLinearLayout);
view.setClickable(true);
view.setOnLongClickListener(mOnLongClick);
View old = null;
if (i < mLinearLayout.getChildCount()) {
old = mLinearLayout.getChildAt(i);
old.setVisibility(View.VISIBLE);
}
final View view = mAdapter.getView(i, old, mLinearLayout);
final View thumbnail = getChildContentView(view);
// thumbnail is set to clickable in the layout file
thumbnail.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mCallback.handleOnClick(view);
}
});
if (old == null) {
view.setClickable(true);
view.setOnLongClickListener(mOnLongClick);
mLinearLayout.addView(view);
final View thumbnail = getChildContentView(view);
// thumbnail is set to clickable in the layout file
thumbnail.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mCallback.handleOnClick(view);
}
});
mLinearLayout.addView(view);
}
}
for (int i = mAdapter.getCount(); i < mLinearLayout.getChildCount(); i++) {
mLinearLayout.getChildAt(i).setVisibility(View.GONE);
}
// Scroll to end after layout.
post(new Runnable() {
@@ -128,8 +142,9 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper
final float y = ev.getY() + getScrollY();
for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
View item = mLinearLayout.getChildAt(i);
if (x >= item.getLeft() && x < item.getRight()
&& y >= item.getTop() && y < item.getBottom()) {
if (item.getVisibility() == View.VISIBLE
&& x >= item.getLeft() && x < item.getRight()
&& y >= item.getTop() && y < item.getBottom()) {
return item;
}
}

View File

@@ -69,6 +69,7 @@ import java.util.Date;
class SaveImageInBackgroundData {
Context context;
Bitmap image;
Runnable finisher;
int result;
}
@@ -141,6 +142,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
Toast.makeText(params.context, R.string.screenshot_saving_toast,
Toast.LENGTH_SHORT).show();
}
params.finisher.run();
};
}
@@ -231,11 +233,9 @@ class GlobalScreenshot {
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();
@@ -244,10 +244,11 @@ class GlobalScreenshot {
/**
* Creates a new worker thread and saves the screenshot to the media store.
*/
private void saveScreenshotInWorkerThread() {
private void saveScreenshotInWorkerThread(Runnable finisher) {
SaveImageInBackgroundData data = new SaveImageInBackgroundData();
data.context = mContext;
data.image = mScreenBitmap;
data.finisher = finisher;
new SaveImageInBackgroundTask().execute(data);
}
@@ -269,7 +270,7 @@ class GlobalScreenshot {
/**
* Takes a screenshot of the current display and shows an animation.
*/
void takeScreenshot() {
void takeScreenshot(Runnable finisher) {
// 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);
@@ -302,18 +303,19 @@ class GlobalScreenshot {
if (mScreenBitmap == null) {
Toast.makeText(mContext, R.string.screenshot_failed_toast,
Toast.LENGTH_SHORT).show();
finisher.run();
return;
}
// Start the post-screenshot animation
startAnimation();
startAnimation(finisher);
}
/**
* Starts the animation after taking the screenshot
*/
private void startAnimation() {
private void startAnimation(final Runnable finisher) {
// Add the view for the animation
mScreenshotView.setImageBitmap(mScreenBitmap);
mScreenshotLayout.requestFocus();
@@ -332,8 +334,7 @@ class GlobalScreenshot {
@Override
public void onAnimationEnd(Animator animation) {
// Save the screenshot once we have a bit of time now
saveScreenshotInWorkerThread();
saveScreenshotInWorkerThread(finisher);
mWindowManager.removeView(mScreenshotLayout);
}
});

View File

@@ -26,7 +26,11 @@ import android.net.Uri;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.app.AlertActivity;
@@ -39,12 +43,30 @@ public class TakeScreenshotService extends Service {
private static GlobalScreenshot mScreenshot;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
final Messenger callback = msg.replyTo;
if (mScreenshot == null) {
mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
}
mScreenshot.takeScreenshot(new Runnable() {
@Override public void run() {
Message reply = Message.obtain(null, 1);
try {
callback.send(reply);
} catch (RemoteException e) {
}
}
});
}
}
};
@Override
public IBinder onBind(Intent intent) {
if (mScreenshot == null) {
mScreenshot = new GlobalScreenshot(this);
}
mScreenshot.takeScreenshot();
return null;
return new Messenger(mHandler).getBinder();
}
}

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.animation.ObjectAnimator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.Dialog;
import android.app.Notification;
@@ -371,9 +372,11 @@ public class PhoneStatusBar extends StatusBar {
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
(translucent ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
if (ActivityManager.isHighEndGfx(mDisplay)) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
lp.setTitle("RecentsPanel");
lp.windowAnimations = R.style.Animation_RecentPanel;

View File

@@ -41,6 +41,8 @@ import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.LocalPowerManager;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -2396,22 +2398,67 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
ServiceConnection mScreenshotConnection = null;
Runnable mScreenshotTimeout = null;
void finishScreenshot(ServiceConnection conn) {
if (mScreenshotConnection == conn) {
mContext.unbindService(conn);
mScreenshotConnection = null;
if (mScreenshotTimeout != null) {
mHandler.removeCallbacks(mScreenshotTimeout);
mScreenshotTimeout = null;
}
}
}
private void takeScreenshot() {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mScreenshotConnection != null) {
return;
}
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) {}
public void onServiceConnected(ComponentName name, IBinder service) {
if (mScreenshotConnection != this) {
return;
}
Messenger messenger = new Messenger(service);
Message msg = Message.obtain(null, 1);
final ServiceConnection myConn = this;
Handler h = new Handler(mHandler.getLooper()) {
@Override
public void handleMessage(Message msg) {
finishScreenshot(myConn);
}
};
msg.replyTo = new Messenger(h);
try {
messenger.send(msg);
} catch (RemoteException e) {
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
mContext.unbindService(conn);
if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
mScreenshotConnection = conn;
mScreenshotTimeout = new Runnable() {
@Override public void run() {
if (mScreenshotConnection != null) {
finishScreenshot(mScreenshotConnection);
}
}
};
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
}
});
}