CameraWidgetFrame.java revision 47cde77bc7ac5c3a1e486691596a7534ad855ff2
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.policy.impl.keyguard; 18 19import android.content.Context; 20import android.content.pm.PackageManager.NameNotFoundException; 21import android.graphics.Bitmap; 22import android.graphics.Canvas; 23import android.graphics.Color; 24import android.os.Handler; 25import android.os.SystemClock; 26import android.util.Log; 27import android.view.LayoutInflater; 28import android.view.View; 29import android.widget.FrameLayout; 30import android.widget.ImageView; 31import android.widget.ImageView.ScaleType; 32 33import com.android.internal.policy.impl.keyguard.KeyguardActivityLauncher.CameraWidgetInfo; 34 35public class CameraWidgetFrame extends KeyguardWidgetFrame { 36 private static final String TAG = CameraWidgetFrame.class.getSimpleName(); 37 private static final boolean DEBUG = KeyguardHostView.DEBUG; 38 private static final int WIDGET_ANIMATION_DURATION = 250; 39 40 interface Callbacks { 41 void onLaunchingCamera(); 42 void onCameraLaunched(); 43 } 44 45 private final Handler mHandler = new Handler(); 46 private final KeyguardActivityLauncher mActivityLauncher; 47 private final Callbacks mCallbacks; 48 49 private View mWidgetView; 50 private long mLaunchCameraStart; 51 private boolean mRendered; 52 53 private final Runnable mLaunchCameraRunnable = new Runnable() { 54 @Override 55 public void run() { 56 mLaunchCameraStart = SystemClock.uptimeMillis(); 57 mActivityLauncher.launchCamera(); 58 }}; 59 60 private final Runnable mRenderRunnable = new Runnable() { 61 @Override 62 public void run() { 63 render(); 64 }}; 65 66 private CameraWidgetFrame(Context context, Callbacks callbacks, 67 KeyguardActivityLauncher activityLauncher) { 68 super(context); 69 70 mCallbacks = callbacks; 71 mActivityLauncher = activityLauncher; 72 } 73 74 public static CameraWidgetFrame create(Context context, Callbacks callbacks, 75 KeyguardActivityLauncher launcher) { 76 if (context == null || callbacks == null || launcher == null) 77 return null; 78 79 CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo(); 80 if (widgetInfo == null) 81 return null; 82 View widgetView = widgetInfo.layoutId > 0 ? 83 inflateWidgetView(context, widgetInfo) : 84 inflateGenericWidgetView(context); 85 if (widgetView == null) 86 return null; 87 88 ImageView preview = new ImageView(context); 89 preview.setLayoutParams(new FrameLayout.LayoutParams( 90 FrameLayout.LayoutParams.MATCH_PARENT, 91 FrameLayout.LayoutParams.MATCH_PARENT)); 92 preview.setScaleType(ScaleType.FIT_CENTER); 93 CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher); 94 cameraWidgetFrame.addView(preview); 95 cameraWidgetFrame.mWidgetView = widgetView; 96 return cameraWidgetFrame; 97 } 98 99 private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) { 100 View widgetView = null; 101 Exception exception = null; 102 try { 103 Context cameraContext = context.createPackageContext( 104 widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED); 105 LayoutInflater cameraInflater = (LayoutInflater) 106 cameraContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 107 cameraInflater = cameraInflater.cloneInContext(cameraContext); 108 widgetView = cameraInflater.inflate(widgetInfo.layoutId, null, false); 109 } catch (NameNotFoundException e) { 110 exception = e; 111 } catch (RuntimeException e) { 112 exception = e; 113 } 114 if (exception != null) { 115 Log.w(TAG, "Error creating camera widget view", exception); 116 } 117 return widgetView; 118 } 119 120 private static View inflateGenericWidgetView(Context context) { 121 ImageView iv = new ImageView(context); 122 iv.setImageResource(com.android.internal.R.drawable.ic_lockscreen_camera); 123 iv.setScaleType(ScaleType.CENTER); 124 iv.setBackgroundColor(Color.argb(127, 0, 0, 0)); 125 return iv; 126 } 127 128 public void render() { 129 if (mRendered) return; 130 131 try { 132 int width = getRootView().getWidth(); 133 int height = getRootView().getHeight(); 134 if (DEBUG) Log.d(TAG, String.format("render [%sx%s] %s", 135 width, height, Integer.toHexString(hashCode()))); 136 if (width == 0 || height == 0) { 137 return; 138 } 139 Bitmap offscreen = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 140 Canvas c = new Canvas(offscreen); 141 mWidgetView.measure( 142 MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 143 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 144 mWidgetView.layout(0, 0, width, height); 145 mWidgetView.draw(c); 146 ((ImageView)getChildAt(0)).setImageBitmap(offscreen); 147 mRendered = true; 148 } catch (Throwable t) { 149 Log.w(TAG, "Error rendering camera widget", t); 150 removeAllViews(); 151 View genericView = inflateGenericWidgetView(mContext); 152 addView(genericView); 153 } 154 } 155 156 private void transitionToCamera() { 157 int startWidth = getChildAt(0).getWidth(); 158 int startHeight = getChildAt(0).getHeight(); 159 160 int finishWidth = getRootView().getWidth(); 161 int finishHeight = getRootView().getHeight(); 162 163 float scaleX = (float) finishWidth / startWidth; 164 float scaleY = (float) finishHeight / startHeight; 165 166 float scale = Math.max(scaleX, scaleY); 167 animate() 168 .scaleX(scale) 169 .scaleY(scale) 170 .setDuration(WIDGET_ANIMATION_DURATION) 171 .withEndAction(mLaunchCameraRunnable) 172 .start(); 173 mCallbacks.onLaunchingCamera(); 174 } 175 176 @Override 177 public void onWindowFocusChanged(boolean hasWindowFocus) { 178 super.onWindowFocusChanged(hasWindowFocus); 179 180 if (!hasWindowFocus) { 181 if (mLaunchCameraStart > 0) { 182 long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart; 183 if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime)); 184 mLaunchCameraStart = 0; 185 onCameraLaunched(); 186 } 187 } 188 } 189 190 @Override 191 public void onActive(boolean isActive) { 192 if (isActive) { 193 mHandler.post(new Runnable(){ 194 @Override 195 public void run() { 196 transitionToCamera(); 197 }}); 198 } else { 199 reset(); 200 } 201 } 202 203 private void onCameraLaunched() { 204 reset(); 205 mCallbacks.onCameraLaunched(); 206 } 207 208 private void reset() { 209 animate().cancel(); 210 setScaleX(1); 211 setScaleY(1); 212 } 213 214 @Override 215 protected void onAttachedToWindow() { 216 super.onAttachedToWindow(); 217 mHandler.post(mRenderRunnable); 218 } 219} 220