diff options
Diffstat (limited to 'packages/SystemUI/src')
8 files changed, 287 insertions, 167 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 8d5c33f..bd1fcfc 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -230,7 +230,7 @@ public class RecentsPanelView extends RelativeLayout public void handleShowBackground(boolean show) { if (show) { - mRecentsScrim.setBackgroundResource(R.drawable.status_bar_recents_background); + mRecentsScrim.setBackgroundResource(R.drawable.status_bar_recents_background_solid); } else { mRecentsScrim.setBackgroundDrawable(null); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java index b7e656e..813099a 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java @@ -83,7 +83,7 @@ public class RecentsScrollViewPerformanceHelper { mLinearLayout = layout; mAttachedToWindow = true; mBackgroundDrawable = mContext.getResources() - .getDrawable(R.drawable.status_bar_recents_background).getConstantState(); + .getDrawable(R.drawable.status_bar_recents_background_solid).getConstantState(); updateShowBackground(); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 3fa3078..181cc98 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -19,27 +19,28 @@ 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.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PixelFormat; -import android.media.MediaScannerConnection; +import android.graphics.PointF; +import android.graphics.RectF; 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; @@ -48,18 +49,16 @@ import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; +import com.android.server.wm.WindowManagerService; 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; @@ -70,6 +69,7 @@ class SaveImageInBackgroundData { Context context; Bitmap image; Runnable finisher; + int iconSize; int result; } @@ -83,6 +83,71 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s"; + private int mNotificationId; + private NotificationManager mNotificationManager; + private Notification.Builder mNotificationBuilder; + private Intent mLaunchIntent; + private String mImageDir; + private String mImageFileName; + private String mImageFilePath; + private String mImageDate; + private long mImageTime; + + // WORKAROUND: We want the same notification across screenshots that we update so that we don't + // spam a user's notification drawer. However, we only show the ticker for the saving state + // and if the ticker text is the same as the previous notification, then it will not show. So + // for now, we just add and remove a space from the ticker text to trigger the animation when + // necessary. + private static boolean mTickerAddSpace; + + SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data, + NotificationManager nManager, int nId) { + Resources r = context.getResources(); + + // Prepare all the output metadata + mImageTime = System.currentTimeMillis(); + mImageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime)); + mImageDir = Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES).getAbsolutePath(); + mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, mImageDate); + mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, mImageDir, + SCREENSHOTS_DIR_NAME, mImageFileName); + + // Create the large notification icon + int imageWidth = data.image.getWidth(); + int imageHeight = data.image.getHeight(); + int iconWidth = data.iconSize; + int iconHeight = data.iconSize; + if (imageWidth > imageHeight) { + iconWidth = (int) (((float) iconHeight / imageHeight) * imageWidth); + } else { + iconHeight = (int) (((float) iconWidth / imageWidth) * imageHeight); + } + Bitmap rawIcon = Bitmap.createScaledBitmap(data.image, iconWidth, iconHeight, true); + Bitmap croppedIcon = Bitmap.createBitmap(rawIcon, (iconWidth - data.iconSize) / 2, + (iconHeight - data.iconSize) / 2, data.iconSize, data.iconSize); + + // Show the intermediate notification + mLaunchIntent = new Intent(Intent.ACTION_VIEW); + mLaunchIntent.setDataAndType(Uri.fromFile(new File(mImageFilePath)), "image/png"); + mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mTickerAddSpace = !mTickerAddSpace; + mNotificationId = nId; + mNotificationBuilder = new Notification.Builder(context) + .setLargeIcon(croppedIcon) + .setTicker(r.getString(R.string.screenshot_saving_ticker) + + (mTickerAddSpace ? " " : "")) + .setContentTitle(r.getString(R.string.screenshot_saving_title)) + .setContentText(r.getString(R.string.screenshot_saving_text)) + .setSmallIcon(android.R.drawable.ic_menu_gallery) + .setWhen(System.currentTimeMillis()); + Notification n = mNotificationBuilder.getNotification(); + n.flags |= Notification.FLAG_NO_CLEAR; + + mNotificationManager = nManager; + mNotificationManager.notify(nId, n); + } + @Override protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) { if (params.length != 1) return null; @@ -91,23 +156,15 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi Bitmap image = params[0].image; try { - long currentTime = System.currentTimeMillis(); - String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(currentTime)); - String imageDir = Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES).getAbsolutePath(); - String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date); - String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir, - SCREENSHOTS_DIR_NAME, imageFileName); - // Save the screenshot to the MediaStore ContentValues values = new ContentValues(); ContentResolver resolver = context.getContentResolver(); - values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath); - values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName); - values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName); - 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.DATA, mImageFilePath); + values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName); + values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName); + values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime); + values.put(MediaStore.Images.ImageColumns.DATE_ADDED, mImageTime); + values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, mImageTime); values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png"); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); @@ -118,7 +175,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi // update file size in the database values.clear(); - values.put(MediaStore.Images.ImageColumns.SIZE, new File(imageFilePath).length()); + values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length()); resolver.update(uri, values, null, null); params[0].result = 0; @@ -135,12 +192,21 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi 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(); + GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager); } 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(); + // Show the final notification to indicate screenshot saved + Resources r = params.context.getResources(); + + mNotificationBuilder + .setContentTitle(r.getString(R.string.screenshot_saved_title)) + .setContentText(r.getString(R.string.screenshot_saved_text)) + .setContentIntent(PendingIntent.getActivity(params.context, 0, mLaunchIntent, 0)) + .setWhen(System.currentTimeMillis()) + .setAutoCancel(true); + + Notification n = mNotificationBuilder.getNotification(); + n.flags &= ~Notification.FLAG_NO_CLEAR; + mNotificationManager.notify(mNotificationId, n); } params.finisher.run(); }; @@ -154,22 +220,23 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi */ 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 int SCREENSHOT_NOTIFICATION_ID = 789; + private static final int SCREENSHOT_FADE_IN_DURATION = 250; + private static final int SCREENSHOT_FADE_OUT_DELAY = 750; + private static final int SCREENSHOT_FADE_OUT_DURATION = 500; + private static final int SCREENSHOT_FAST_FADE_OUT_DURATION = 350; 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 static final float SCREENSHOT_SCALE_FUDGE = 0.075f; // To account for the border padding + private static final float SCREENSHOT_SCALE = 0.55f; + private static final float SCREENSHOT_FADE_IN_MIN_SCALE = SCREENSHOT_SCALE * 0.975f; + private static final float SCREENSHOT_FADE_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.925f; private Context mContext; private LayoutInflater mLayoutInflater; private IWindowManager mIWindowManager; private WindowManager mWindowManager; private WindowManager.LayoutParams mWindowLayoutParams; + private NotificationManager mNotificationManager; private Display mDisplay; private DisplayMetrics mDisplayMetrics; private Matrix mDisplayMatrix; @@ -182,34 +249,24 @@ class GlobalScreenshot { 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; - } - } - }; + private int mStatusBarIconSize; + private int mNotificationIconSize; + private float mDropOffsetX; + private float mDropOffsetY; + private float mBgPadding; + private float mBgPaddingScale; + /** * @param context everything needs a context :( */ public GlobalScreenshot(Context context) { + Resources r = context.getResources(); 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); @@ -237,7 +294,23 @@ class GlobalScreenshot { PixelFormat.TRANSLUCENT); mWindowLayoutParams.setTitle("ScreenshotAnimation"); mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + mNotificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); + mDisplayMetrics = new DisplayMetrics(); + mDisplay.getRealMetrics(mDisplayMetrics); + + // Get the various target sizes + mStatusBarIconSize = + r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size); + mNotificationIconSize = + r.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); + mDropOffsetX = r.getDimensionPixelSize(R.dimen.global_screenshot_drop_offset_x); + mDropOffsetY = r.getDimensionPixelSize(R.dimen.global_screenshot_drop_offset_y); + + // Scale has to account for both sides of the bg + mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding); + mBgPaddingScale = (2f * mBgPadding) / mDisplayMetrics.widthPixels; } /** @@ -247,8 +320,10 @@ class GlobalScreenshot { SaveImageInBackgroundData data = new SaveImageInBackgroundData(); data.context = mContext; data.image = mScreenBitmap; + data.iconSize = mNotificationIconSize; data.finisher = finisher; - new SaveImageInBackgroundTask().execute(data); + new SaveImageInBackgroundTask(mContext, data, mNotificationManager, + SCREENSHOT_NOTIFICATION_ID).execute(data); } /** @@ -257,11 +332,11 @@ class GlobalScreenshot { private float getDegreesForRotation(int value) { switch (value) { case Surface.ROTATION_90: - return 90f; + return 360f - 90f; case Surface.ROTATION_180: - return 180f; + return 360f - 180f; case Surface.ROTATION_270: - return 270f; + return 360f - 270f; } return 0f; } @@ -269,7 +344,7 @@ class GlobalScreenshot { /** * Takes a screenshot of the current display and shows an animation. */ - void takeScreenshot(Runnable finisher) { + void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) { // 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); @@ -291,7 +366,7 @@ class GlobalScreenshot { mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(ss); c.translate(ss.getWidth() / 2, ss.getHeight() / 2); - c.rotate(360f - degrees); + c.rotate(degrees); c.translate(-dims[0] / 2, -dims[1] / 2); c.drawBitmap(mScreenBitmap, 0, 0, null); c.setBitmap(null); @@ -300,21 +375,26 @@ class GlobalScreenshot { // 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(); + notifyScreenshotError(mContext, mNotificationManager); finisher.run(); return; } + // Optimizations + mScreenBitmap.setHasAlpha(false); + mScreenBitmap.prepareToDraw(); + // Start the post-screenshot animation - startAnimation(finisher); + startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, + statusBarVisible, navBarVisible); } /** * Starts the animation after taking the screenshot */ - private void startAnimation(final Runnable finisher) { + private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible, + boolean navBarVisible) { // Add the view for the animation mScreenshotView.setImageBitmap(mScreenBitmap); mScreenshotLayout.requestFocus(); @@ -326,7 +406,8 @@ class GlobalScreenshot { mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams); ValueAnimator screenshotFadeInAnim = createScreenshotFadeInAnimation(); - ValueAnimator screenshotFadeOutAnim = createScreenshotFadeOutAnimation(); + ValueAnimator screenshotFadeOutAnim = createScreenshotFadeOutAnimation(w, h, + statusBarVisible, navBarVisible); mScreenshotAnimation = new AnimatorSet(); mScreenshotAnimation.play(screenshotFadeInAnim).before(screenshotFadeOutAnim); mScreenshotAnimation.addListener(new AnimatorListenerAdapter() { @@ -337,16 +418,29 @@ class GlobalScreenshot { mWindowManager.removeView(mScreenshotLayout); } }); - mScreenshotAnimation.start(); + mScreenshotLayout.post(new Runnable() { + @Override + public void run() { + mScreenshotContainerView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + mScreenshotContainerView.buildLayer(); + mScreenshotAnimation.start(); + } + }); } private ValueAnimator createScreenshotFadeInAnimation() { ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); - anim.setInterpolator(mCubicInterpolator); + anim.setInterpolator(new AccelerateInterpolator(1.5f)); anim.setDuration(SCREENSHOT_FADE_IN_DURATION); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { + mBackgroundView.setAlpha(0f); mBackgroundView.setVisibility(View.VISIBLE); + mScreenshotContainerView.setTranslationX(0f); + mScreenshotContainerView.setTranslationY(0f); + mScreenshotContainerView.setScaleX(SCREENSHOT_FADE_IN_MIN_SCALE); + mScreenshotContainerView.setScaleY(SCREENSHOT_FADE_IN_MIN_SCALE); + mScreenshotContainerView.setAlpha(0f); mScreenshotContainerView.setVisibility(View.VISIBLE); } }); @@ -354,41 +448,98 @@ class GlobalScreenshot { @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); + float scaleT = (SCREENSHOT_FADE_IN_MIN_SCALE) + + (float) t * (SCREENSHOT_SCALE - SCREENSHOT_FADE_IN_MIN_SCALE); + mBackgroundView.setAlpha(t * BACKGROUND_ALPHA); mScreenshotContainerView.setScaleX(scaleT); mScreenshotContainerView.setScaleY(scaleT); - mScreenshotContainerView.setRotation(t * SCREENSHOT_ROTATION); + mScreenshotContainerView.setAlpha(t); } }); return anim; } - private ValueAnimator createScreenshotFadeOutAnimation() { - ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f); - anim.setInterpolator(mCubicInterpolator); + private ValueAnimator createScreenshotFadeOutAnimation(int w, int h, boolean statusBarVisible, + boolean navBarVisible) { + ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); + anim.setInterpolator(new DecelerateInterpolator(0.5f)); 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); + mScreenshotContainerView.setLayerType(View.LAYER_TYPE_NONE, null); } }); - 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); + + if (!statusBarVisible || !navBarVisible) { + // There is no status bar/nav bar, so just fade the screenshot away in place + anim.setDuration(SCREENSHOT_FAST_FADE_OUT_DURATION); + anim.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float t = ((Float) animation.getAnimatedValue()).floatValue(); + float scaleT = (SCREENSHOT_FADE_OUT_MIN_SCALE) + + (float) (1f - t) * (SCREENSHOT_SCALE - SCREENSHOT_FADE_OUT_MIN_SCALE); + mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA); + mScreenshotContainerView.setAlpha((1f - t) * BACKGROUND_ALPHA); + mScreenshotContainerView.setScaleX(scaleT); + mScreenshotContainerView.setScaleY(scaleT); + } + }); + } else { + // Determine the bounds of how to scale + float halfScreenWidth = (w - 2f * mBgPadding) / 2f; + float halfScreenHeight = (h - 2f * mBgPadding) / 2f; + final RectF finalBounds = new RectF(mDropOffsetX, mDropOffsetY, + mDropOffsetX + mStatusBarIconSize, + mDropOffsetY + mStatusBarIconSize); + final PointF currentPos = new PointF(0f, 0f); + final PointF finalPos = new PointF(-halfScreenWidth + finalBounds.centerX(), + -halfScreenHeight + finalBounds.centerY()); + final DecelerateInterpolator d = new DecelerateInterpolator(2f); + // Note: since the scale origin is in the center of the view, divide difference by 2 + float tmpMinScale = 0f; + if (w > h) { + tmpMinScale = finalBounds.width() / (2f * w); + } else { + tmpMinScale = finalBounds.height() / (2f * h); } - }); + final float minScale = tmpMinScale; + + // Animate the screenshot to the status bar + anim.setDuration(SCREENSHOT_FADE_OUT_DURATION); + anim.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float t = ((Float) animation.getAnimatedValue()).floatValue(); + float scaleT = minScale + + (float) (1f - t) * (SCREENSHOT_SCALE - minScale - mBgPaddingScale) + + mBgPaddingScale; + mScreenshotContainerView.setAlpha(d.getInterpolation(1f - t)); + mScreenshotContainerView.setTranslationX(d.getInterpolation(t) * finalPos.x); + mScreenshotContainerView.setTranslationY(d.getInterpolation(t) * finalPos.y); + mScreenshotContainerView.setScaleX(scaleT); + mScreenshotContainerView.setScaleY(scaleT); + mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA); + } + }); + } return anim; } + + static void notifyScreenshotError(Context context, NotificationManager nManager) { + Resources r = context.getResources(); + + // Clear all existing notification, compose the new notification and show it + Notification n = new Notification.Builder(context) + .setTicker(r.getString(R.string.screenshot_failed_title)) + .setContentTitle(r.getString(R.string.screenshot_failed_title)) + .setContentText(r.getString(R.string.screenshot_failed_text)) + .setSmallIcon(android.R.drawable.ic_menu_report_image) + .setWhen(System.currentTimeMillis()) + .setAutoCancel(true) + .getNotification(); + nManager.notify(SCREENSHOT_NOTIFICATION_ID, n); + } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java index 05ff8be..456b5fa 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java @@ -17,26 +17,12 @@ 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.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; -import com.android.internal.app.AlertController; - -import com.android.systemui.R; public class TakeScreenshotService extends Service { private static final String TAG = "TakeScreenshotService"; @@ -60,7 +46,7 @@ public class TakeScreenshotService extends Service { } catch (RemoteException e) { } } - }); + }, msg.arg1 > 0, msg.arg2 > 0); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java index 5959537..2e1803e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java @@ -146,4 +146,26 @@ public abstract class StatusBar extends SystemUI implements CommandQueue.Callbac mDoNotDisturb = new DoNotDisturb(mContext); } + + protected View updateNotificationVetoButton(View row, StatusBarNotification n) { + View vetoButton = row.findViewById(R.id.veto); + if (n.isClearable()) { + final String _pkg = n.pkg; + final String _tag = n.tag; + final int _id = n.id; + vetoButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + try { + mBarService.onNotificationClear(_pkg, _tag, _id); + } catch (RemoteException ex) { + // system process is dead if we're here. + } + } + }); + vetoButton.setVisibility(View.VISIBLE); + } else { + vetoButton.setVisibility(View.GONE); + } + return vetoButton; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 9c8c229..4e9b411 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -94,7 +94,7 @@ public class PhoneStatusBar extends StatusBar { public static final boolean DUMPTRUCK = true; // extra dumpsys info // additional instrumentation for testing purposes; intended to be left on during development - public static final boolean CHATTY = DEBUG || true; + public static final boolean CHATTY = DEBUG; public static final String ACTION_STATUSBAR_START = "com.android.internal.policy.statusbar.START"; @@ -618,6 +618,10 @@ public class PhoneStatusBar extends StatusBar { boolean orderUnchanged = notification.notification.when==oldNotification.notification.when && notification.priority == oldNotification.priority; // priority now encompasses isOngoing() + + boolean updateTicker = notification.notification.tickerText != null + && !TextUtils.equals(notification.notification.tickerText, + oldEntry.notification.notification.tickerText); boolean isFirstAnyway = rowParent.indexOfChild(oldEntry.row) == 0; if (contentsUnchanged && (orderUnchanged || isFirstAnyway)) { if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key); @@ -665,10 +669,13 @@ public class PhoneStatusBar extends StatusBar { addNotificationViews(key, notification); } + // Update the veto button accordingly (and as a result, whether this row is + // swipe-dismissable) + updateNotificationVetoButton(oldEntry.row, notification); + // Restart the ticker if it's still running - if (notification.notification.tickerText != null - && !TextUtils.equals(notification.notification.tickerText, - oldEntry.notification.notification.tickerText)) { + if (updateTicker) { + mTicker.halt(); tick(notification); } @@ -711,23 +718,7 @@ public class PhoneStatusBar extends StatusBar { View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false); // wire up the veto button - View vetoButton = row.findViewById(R.id.veto); - if (notification.isClearable()) { - final String _pkg = notification.pkg; - final String _tag = notification.tag; - final int _id = notification.id; - vetoButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - try { - mBarService.onNotificationClear(_pkg, _tag, _id); - } catch (RemoteException ex) { - // system process is dead if we're here. - } - } - }); - } else { - vetoButton.setVisibility(View.GONE); - } + View vetoButton = updateNotificationVetoButton(row, notification); vetoButton.setContentDescription(mContext.getString( R.string.accessibility_remove_notification)); @@ -897,23 +888,7 @@ public class PhoneStatusBar extends StatusBar { LayoutInflater inflater = (LayoutInflater)mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false); - View vetoButton = row.findViewById(R.id.veto); - if (entry.notification.isClearable()) { - final String _pkg = sbn.pkg; - final String _tag = sbn.tag; - final int _id = sbn.id; - vetoButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - try { - mBarService.onNotificationClear(_pkg, _tag, _id); - } catch (RemoteException ex) { - // system process is dead if we're here. - } - } - }); - } else { - vetoButton.setVisibility(View.GONE); - } + View vetoButton = updateNotificationVetoButton(row, sbn); vetoButton.setContentDescription(mContext.getString( R.string.accessibility_remove_notification)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 8d964e3..4f9eb38 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -61,7 +61,7 @@ public class NetworkController extends BroadcastReceiver { // debug static final String TAG = "StatusBar.NetworkController"; static final boolean DEBUG = false; - static final boolean CHATTY = true; // additional diagnostics, but not logspew + static final boolean CHATTY = false; // additional diagnostics, but not logspew // telephony boolean mHspaDataDistinguishable; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 415a9a4..f0a10f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -840,6 +840,9 @@ public class TabletStatusBar extends StatusBar implements boolean orderUnchanged = notification.notification.when==oldNotification.notification.when && notification.priority == oldNotification.priority; // priority now encompasses isOngoing() + boolean updateTicker = notification.notification.tickerText != null + && !TextUtils.equals(notification.notification.tickerText, + oldEntry.notification.notification.tickerText); boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1; if (contentsUnchanged && (orderUnchanged || isLastAnyway)) { if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key); @@ -896,9 +899,8 @@ public class TabletStatusBar extends StatusBar implements } // Restart the ticker if it's still running - if (notification.notification.tickerText != null - && !TextUtils.equals(notification.notification.tickerText, - oldEntry.notification.notification.tickerText)) { + if (updateTicker) { + mTicker.halt(); tick(key, notification, false); } @@ -1736,23 +1738,7 @@ public class TabletStatusBar extends StatusBar implements Context.LAYOUT_INFLATER_SERVICE); View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false); workAroundBadLayerDrawableOpacity(row); - View vetoButton = row.findViewById(R.id.veto); - if (entry.notification.isClearable()) { - final String _pkg = sbn.pkg; - final String _tag = sbn.tag; - final int _id = sbn.id; - vetoButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - try { - mBarService.onNotificationClear(_pkg, _tag, _id); - } catch (RemoteException ex) { - // system process is dead if we're here. - } - } - }); - } else { - vetoButton.setVisibility(View.GONE); - } + View vetoButton = updateNotificationVetoButton(row, entry.notification); vetoButton.setContentDescription(mContext.getString( R.string.accessibility_remove_notification)); |
