diff options
17 files changed, 316 insertions, 108 deletions
diff --git a/api/current.txt b/api/current.txt index be6e873..54647ad 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26126,8 +26126,6 @@ package android.provider { method public static java.lang.String getVersion(android.content.Context); field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE"; field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE"; - field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN"; - field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM"; field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE"; field public static final java.lang.String AUTHORITY = "media"; field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit"; @@ -26155,6 +26153,7 @@ package android.provider { field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH"; field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia"; field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume"; + field public static final java.lang.String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service"; field public static final java.lang.String UNKNOWN_STRING = "<unknown>"; } @@ -28713,6 +28712,13 @@ package android.service.dreams { package android.service.media { + public abstract class CameraPrewarmService extends android.app.Service { + ctor public CameraPrewarmService(); + method public android.os.IBinder onBind(android.content.Intent); + method public abstract void onCooldown(boolean); + method public abstract void onPrewarm(); + } + public abstract class MediaBrowserService extends android.app.Service { ctor public MediaBrowserService(); method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); diff --git a/api/system-current.txt b/api/system-current.txt index a072bd7..87bdff5 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -28049,8 +28049,6 @@ package android.provider { method public static java.lang.String getVersion(android.content.Context); field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE"; field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE"; - field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN"; - field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM"; field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE"; field public static final java.lang.String AUTHORITY = "media"; field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit"; @@ -28078,6 +28076,7 @@ package android.provider { field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH"; field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia"; field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume"; + field public static final java.lang.String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service"; field public static final java.lang.String UNKNOWN_STRING = "<unknown>"; } @@ -30739,6 +30738,13 @@ package android.service.dreams { package android.service.media { + public abstract class CameraPrewarmService extends android.app.Service { + ctor public CameraPrewarmService(); + method public android.os.IBinder onBind(android.content.Intent); + method public abstract void onCooldown(boolean); + method public abstract void onPrewarm(); + } + public abstract class MediaBrowserService extends android.app.Service { ctor public MediaBrowserService(); method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 7565654b..51dbdee 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -22,6 +22,7 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; +import android.content.Intent; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteException; @@ -33,6 +34,7 @@ import android.media.ThumbnailUtils; import android.net.Uri; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.service.media.CameraPrewarmService; import android.util.Log; import java.io.FileInputStream; @@ -226,33 +228,24 @@ public final class MediaStore { public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA"; /** - * The name of the Intent action used to indicate that a camera launch might be imminent. This - * broadcast should be targeted to the package that is receiving - * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or - * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE}, depending on the context. If such - * intent would launch the resolver activity, this broadcast should not be sent at all. + * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or + * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm + * service. * <p> - * A receiver of this broadcast should do the absolute minimum amount of work to initialize the - * camera in order to reduce startup time in likely case that shortly after an actual camera - * launch intent would be sent. + * This meta-data should reference the fully qualified class name of the prewarm service + * extending {@link CameraPrewarmService}. * <p> - * In case the actual intent will not be fired, the target package will receive - * {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN}. However, it is recommended that the receiver - * also implements a timeout to close the camera after receiving this intent, as there is no - * guarantee that {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN} will be delivered. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM"; - - /** - * The name of the Intent action used to indicate that an imminent camera launch has been - * cancelled by the user. This broadcast should be targeted to the package that has received - * {@link #ACTION_STILL_IMAGE_CAMERA_PREWARM}. + * The prewarm service will get bound and receive a prewarm signal + * {@link CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent. + * An application implementing a prewarm service should do the absolute minimum amount of work + * to initialize the camera in order to reduce startup time in likely case that shortly after a + * camera launch intent would be sent. * <p> - * A receiver of this broadcast should close the camera immediately. + * If the camera launch intent gets fired shortly after, the service will be unbound + * asynchronously, without receiving */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN"; + public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = + "android.media.still_image_camera_preview_service"; /** * The name of the Intent action used to launch a camera in still image mode @@ -2268,5 +2261,4 @@ public final class MediaStore { } return null; } - } diff --git a/core/java/android/service/media/CameraPrewarmService.java b/core/java/android/service/media/CameraPrewarmService.java new file mode 100644 index 0000000..335b00a --- /dev/null +++ b/core/java/android/service/media/CameraPrewarmService.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.service.media; + +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; + +/** + * Extend this class to implement a camera prewarm service. See + * {@link android.provider.MediaStore#META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE}. + */ +public abstract class CameraPrewarmService extends Service { + + /** + * Intent action to bind the service as a prewarm service. + * @hide + */ + public static final String ACTION_PREWARM = + "android.service.media.CameraPrewarmService.ACTION_PREWARM"; + + /** + * Message sent by the client indicating that the camera intent has been fired. + * @hide + */ + public static final int MSG_CAMERA_FIRED = 1; + + private final Handler mHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_CAMERA_FIRED: + mCameraIntentFired = true; + break; + default: + super.handleMessage(msg); + } + } + }; + private boolean mCameraIntentFired; + + @Override + public IBinder onBind(Intent intent) { + if (ACTION_PREWARM.equals(intent.getAction())) { + onPrewarm(); + return new Messenger(mHandler).getBinder(); + } else { + return null; + } + } + + @Override + public boolean onUnbind(Intent intent) { + if (ACTION_PREWARM.equals(intent.getAction())) { + onCooldown(mCameraIntentFired); + } + return false; + } + + /** + * Called when the camera should be prewarmed. + */ + public abstract void onPrewarm(); + + /** + * Called when prewarm phase is done, either because the camera launch intent has been fired + * at this point or prewarm is no longer needed. A client should close the camera + * immediately in the latter case. + * <p> + * In case the camera launch intent has been fired, there is no guarantee about the ordering + * of these two events. Cooldown might happen either before or after the activity has been + * created that handles the camera intent. + * + * @param cameraIntentFired Indicates whether the intent to launch the camera has been + * fired. + */ + public abstract void onCooldown(boolean cameraIntentFired); +} diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index 2cf30ba..cd4b24a 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -60,6 +60,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { protected ViewMediatorCallback mViewMediatorCallback; protected LockPatternUtils mLockPatternUtils; private OnDismissAction mDismissAction; + private Runnable mCancelAction; private final KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @@ -126,8 +127,17 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { * * @param action */ - public void setOnDismissAction(OnDismissAction action) { + public void setOnDismissAction(OnDismissAction action, Runnable cancelAction) { + if (mCancelAction != null) { + mCancelAction.run(); + mCancelAction = null; + } mDismissAction = action; + mCancelAction = cancelAction; + } + + public void cancelDismissAction() { + setOnDismissAction(null, null); } @Override @@ -197,6 +207,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { if (mDismissAction != null) { deferKeyguardDone = mDismissAction.onDismiss(); mDismissAction = null; + mCancelAction = null; } if (mViewMediatorCallback != null) { if (deferKeyguardDone) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java index ee5eb38..9ef320b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java @@ -24,6 +24,11 @@ import android.content.Intent; * Keyguard. */ public interface ActivityStarter { - public void startActivity(Intent intent, boolean dismissShade); + void startActivity(Intent intent, boolean dismissShade); + void startActivity(Intent intent, boolean dismissShade, Callback callback); void preventNextAnimation(); + + interface Callback { + void onActivityStarted(int resultCode); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java index 8bffdc9..64735ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -160,7 +160,7 @@ public class KeyguardAffordanceHelper { } else { mTouchSlopExeeded = false; } - mCallback.onSwipingStarted(targetView == mLeftIcon); + mCallback.onSwipingStarted(targetView == mRightIcon); mSwipingInProgress = true; mTargetedView = targetView; mInitialTouchX = x; @@ -550,7 +550,7 @@ public class KeyguardAffordanceHelper { float getMaxTranslationDistance(); - void onSwipingStarted(boolean isRightwardMotion); + void onSwipingStarted(boolean rightIcon); void onSwipingAborted(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index adee5a8..3258a9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -16,12 +16,17 @@ package com.android.systemui.statusbar.phone; +import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.Application; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; @@ -29,9 +34,13 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; import android.os.AsyncTask; import android.os.Bundle; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; import android.os.RemoteException; import android.os.UserHandle; import android.provider.MediaStore; +import android.service.media.CameraPrewarmService; import android.telecom.TelecomManager; import android.util.AttributeSet; import android.util.Log; @@ -100,7 +109,23 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private PhoneStatusBar mPhoneStatusBar; private final Interpolator mLinearOutSlowInInterpolator; - private boolean mPrewarmSent; + private boolean mPrewarmBound; + private Messenger mPrewarmMessenger; + private final ServiceConnection mPrewarmConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + mPrewarmMessenger = new Messenger(service); + mPrewarmBound = true; + } + + @Override + public void onServiceDisconnected(ComponentName name) { + mPrewarmBound = false; + mPrewarmMessenger = null; + } + }; + private boolean mLeftIsVoiceAssist; private AssistManager mAssistManager; @@ -343,37 +368,44 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser()); } - public void prewarmCamera() { + public void bindCameraPrewarmService() { Intent intent = getCameraIntent(); - String targetPackage = PreviewInflater.getTargetPackage(mContext, intent, + ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent, KeyguardUpdateMonitor.getCurrentUser()); - if (targetPackage != null) { - Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM); - prewarm.setPackage(targetPackage); - mPrewarmSent = true; - mContext.sendBroadcast(prewarm); + if (targetInfo != null) { + String clazz = targetInfo.metaData.getString( + MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE); + if (clazz != null) { + Intent serviceIntent = new Intent(); + serviceIntent.setClassName(targetInfo.packageName, clazz); + serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM); + try { + getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection, + Context.BIND_AUTO_CREATE, new UserHandle(UserHandle.USER_CURRENT)); + } catch (SecurityException e) { + Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName + + " class=" + clazz, e); + } + } } } - public void maybeCooldownCamera() { - if (!mPrewarmSent) { - return; - } - mPrewarmSent = false; - Intent intent = getCameraIntent(); - String targetPackage = PreviewInflater.getTargetPackage(mContext, intent, - KeyguardUpdateMonitor.getCurrentUser()); - if (targetPackage != null) { - Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN); - prewarm.setPackage(targetPackage); - mContext.sendBroadcast(prewarm); + public void unbindCameraPrewarmService(boolean launched) { + if (mPrewarmBound) { + if (launched) { + try { + mPrewarmMessenger.send(Message.obtain(null /* handler */, + CameraPrewarmService.MSG_CAMERA_FIRED)); + } catch (RemoteException e) { + Log.w(TAG, "Error sending camera fired message", e); + } + } + mContext.unbindService(mPrewarmConnection); + mPrewarmBound = false; } } public void launchCamera() { - - // Reset prewarm state. - mPrewarmSent = false; final Intent intent = getCameraIntent(); boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity( mContext, intent, KeyguardUpdateMonitor.getCurrentUser()); @@ -381,18 +413,47 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL AsyncTask.execute(new Runnable() { @Override public void run() { - mContext.startActivityAsUser(intent, UserHandle.CURRENT); + int result = ActivityManager.START_CANCELED; + try { + result = ActivityManagerNative.getDefault().startActivityAsUser( + null, getContext().getBasePackageName(), + intent, + intent.resolveTypeIfNeeded(getContext().getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, + UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start camera activity", e); + } mActivityStarter.preventNextAnimation(); + final boolean launched = isSuccessfulLaunch(result); + post(new Runnable() { + @Override + public void run() { + unbindCameraPrewarmService(launched); + } + }); } }); } else { // We need to delay starting the activity because ResolverActivity finishes itself if // launched behind lockscreen. - mActivityStarter.startActivity(intent, false /* dismissShade */); + mActivityStarter.startActivity(intent, false /* dismissShade */, + new ActivityStarter.Callback() { + @Override + public void onActivityStarted(int resultCode) { + unbindCameraPrewarmService(isSuccessfulLaunch(resultCode)); + } + }); } } + private static boolean isSuccessfulLaunch(int result) { + return result == ActivityManager.START_SUCCESS + || result == ActivityManager.START_DELIVERED_TO_TOP + || result == ActivityManager.START_TASK_TO_FRONT; + } + public void launchLeftAffordance() { if (mLeftIsVoiceAssist) { launchVoiceAssist(); @@ -412,8 +473,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (mPhoneStatusBar.isKeyguardCurrentlySecure()) { AsyncTask.execute(runnable); } else { - mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, false /* dismissShade */, - false /* afterKeyguardGone */); + mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */, + false /* dismissShade */, false /* afterKeyguardGone */); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 262d955..3d57d54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -95,16 +95,16 @@ public class KeyguardBouncer { mShowingSoon = false; } - public void showWithDismissAction(OnDismissAction r) { + public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) { ensureView(); - mKeyguardView.setOnDismissAction(r); + mKeyguardView.setOnDismissAction(r, cancelAction); show(false /* resetSecuritySelection */); } public void hide(boolean destroyView) { cancelShowRunnable(); if (mKeyguardView != null) { - mKeyguardView.setOnDismissAction(null); + mKeyguardView.cancelDismissAction(); mKeyguardView.cleanUp(); } if (destroyView) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 5d48190..2fe98bb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1934,12 +1934,12 @@ public class NotificationPanelView extends PanelView implements } @Override - public void onSwipingStarted(boolean isRightwardMotion) { - boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? isRightwardMotion - : !isRightwardMotion; - if (!start) { + public void onSwipingStarted(boolean rightIcon) { + boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon + : rightIcon; + if (camera) { mSecureCameraLaunchManager.onSwipingStarted(); - mKeyguardBottomArea.prewarmCamera(); + mKeyguardBottomArea.bindCameraPrewarmService(); } requestDisallowInterceptTouchEvent(true); mOnlyAffordanceInThisMotion = true; @@ -1948,7 +1948,7 @@ public class NotificationPanelView extends PanelView implements @Override public void onSwipingAborted() { - mKeyguardBottomArea.maybeCooldownCamera(); + mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */); } @Override 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 1e4aa61..e6089ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1826,6 +1826,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override + public void startActivity(Intent intent, boolean dismissShade, Callback callback) { + startActivityDismissingKeyguard(intent, false, dismissShade, callback); + } + + @Override public void preventNextAnimation() { overrideActivityPendingAppTransition(true /* keyguardShowing */); } @@ -2707,7 +2712,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, - final boolean dismissShade) { + boolean dismissShade) { + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */); + } + + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + final boolean dismissShade, final Callback callback) { if (onlyProvisioned && !isDeviceProvisioned()) return; final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( @@ -2717,16 +2727,35 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void run() { intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mContext.startActivityAsUser( - intent, new UserHandle(UserHandle.USER_CURRENT)); + int result = ActivityManager.START_CANCELED; + try { + result = ActivityManagerNative.getDefault().startActivityAsUser( + null, mContext.getBasePackageName(), + intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, + UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start activity", e); + } overrideActivityPendingAppTransition( keyguardShowing && !afterKeyguardGone); + if (callback != null) { + callback.onActivityStarted(result); + } } }; - executeRunnableDismissingKeyguard(runnable, dismissShade, afterKeyguardGone); + Runnable cancelRunnable = new Runnable() { + @Override + public void run() { + callback.onActivityStarted(ActivityManager.START_CANCELED); + } + }; + executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone); } public void executeRunnableDismissingKeyguard(final Runnable runnable, + final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone) { final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); @@ -2753,7 +2782,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } return true; } - }, afterKeyguardGone); + }, cancelAction, afterKeyguardGone); } private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @@ -2813,10 +2842,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - protected void dismissKeyguardThenExecute(final OnDismissAction action, + protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { + dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); + } + + private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone) { if (mStatusBarKeyguardViewManager.isShowing()) { - mStatusBarKeyguardViewManager.dismissWithAction(action, afterKeyguardGone); + mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, + afterKeyguardGone); } else { action.onDismiss(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 0caf51a..6cb890a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -126,10 +126,11 @@ public class StatusBarKeyguardViewManager { updateStates(); } - public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) { + public void dismissWithAction(OnDismissAction r, Runnable cancelAction, + boolean afterKeyguardGone) { if (mShowing) { if (!afterKeyguardGone) { - mBouncer.showWithDismissAction(r); + mBouncer.showWithDismissAction(r, cancelAction); } else { mBouncer.show(false /* resetSecuritySelection */); mAfterKeyguardGoneAction = r; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java index 4269c19..93d0ec3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.policy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; @@ -138,14 +139,14 @@ public class PreviewInflater { public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent, int currentUserId) { - return getTargetPackage(ctx, intent, currentUserId) == null; + return getTargetActivityInfo(ctx, intent, currentUserId) == null; } /** - * @return the target package of the intent it resolves to a specific package or {@code null} if - * it resolved to the resolver activity + * @return the target activity info of the intent it resolves to a specific package or + * {@code null} if it resolved to the resolver activity */ - public static String getTargetPackage(Context ctx, Intent intent, + public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent, int currentUserId) { PackageManager packageManager = ctx.getPackageManager(); final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( @@ -158,7 +159,7 @@ public class PreviewInflater { if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { return null; } else { - return resolved.activityInfo.packageName; + return resolved.activityInfo; } } diff --git a/tests/CameraPrewarmTest/AndroidManifest.xml b/tests/CameraPrewarmTest/AndroidManifest.xml index eb40200..11b2686 100644 --- a/tests/CameraPrewarmTest/AndroidManifest.xml +++ b/tests/CameraPrewarmTest/AndroidManifest.xml @@ -22,13 +22,13 @@ <activity android:name=".CameraActivity" android:theme="@android:style/Theme.NoTitleBar"> <intent-filter> - <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <intent-filter> <action android:name="android.media.action.STILL_IMAGE_CAMERA" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> + <meta-data + android:name="android.media.still_image_camera_preview_service" + android:value="com.google.android.test.cameraprewarm.PrewarmService"> + </meta-data> </activity> <activity android:name=".SecureCameraActivity" @@ -37,16 +37,15 @@ <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> + <meta-data + android:name="android.media.still_image_camera_preview_service" + android:value="com.google.android.test.cameraprewarm.PrewarmService"> + </meta-data> </activity> - <receiver android:name=".PrewarmReceiver" > - <intent-filter> - <action android:name="android.media.action.STILL_IMAGE_CAMERA_PREWARM" /> - </intent-filter> - <intent-filter> - <action android:name="android.media.action.STILL_IMAGE_CAMERA_COOLDOWN" /> - </intent-filter> - </receiver> + <service android:name=".PrewarmService" + android:exported="true"> + </service> </application> </manifest> diff --git a/tests/CameraPrewarmTest/res/values/strings.xml b/tests/CameraPrewarmTest/res/values/strings.xml index 11f7ac7..fe39ac1 100644 --- a/tests/CameraPrewarmTest/res/values/strings.xml +++ b/tests/CameraPrewarmTest/res/values/strings.xml @@ -16,6 +16,6 @@ --> <resources> - <string name="activity_title">Assistant</string> + <string name="activity_title">Camera Prewarm test</string> <string name="search_label">Orilla Search Engine</string> </resources> diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java index 4d22234..0b43666 100644 --- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java +++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java @@ -19,7 +19,6 @@ package com.google.android.test.cameraprewarm; import android.app.Activity; import android.os.Bundle; import android.util.Log; -import android.view.WindowManager; import com.google.android.test.cameraprewarm.R; @@ -31,7 +30,6 @@ public class CameraActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camera_activity); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); Log.i(TAG, "Activity created"); } } diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java index d49f96d..d080b1a 100644 --- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java +++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java @@ -16,20 +16,18 @@ package com.google.android.test.cameraprewarm; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.provider.MediaStore; +import android.service.media.CameraPrewarmService; import android.util.Log; -public class PrewarmReceiver extends BroadcastReceiver { +public class PrewarmService extends CameraPrewarmService { @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM)) { - Log.i(CameraActivity.TAG, "Prewarm received"); - } else if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN)){ - Log.i(CameraActivity.TAG, "Cooldown received"); - } + public void onPrewarm() { + Log.i("PrewarmService", "Warming up"); + } + + @Override + public void onCooldown(boolean cameraIntentFired) { + Log.i("PrewarmService", "Cooling down fired=" + cameraIntentFired); } } |