summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt10
-rw-r--r--api/system-current.txt10
-rw-r--r--core/java/android/provider/MediaStore.java40
-rw-r--r--core/java/android/service/media/CameraPrewarmService.java96
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java11
-rw-r--r--tests/CameraPrewarmTest/AndroidManifest.xml23
-rw-r--r--tests/CameraPrewarmTest/res/values/strings.xml2
-rw-r--r--tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java2
-rw-r--r--tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java (renamed from tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java)20
17 files changed, 316 insertions, 108 deletions
diff --git a/api/current.txt b/api/current.txt
index f110d0b..8541495 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26143,8 +26143,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";
@@ -26172,6 +26170,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>";
}
@@ -28730,6 +28729,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 84c0f83..fb7376c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -28072,8 +28072,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";
@@ -28101,6 +28099,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>";
}
@@ -30762,6 +30761,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 5ff4ddb..bc95743 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1830,6 +1830,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 */);
}
@@ -2711,7 +2716,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(
@@ -2721,16 +2731,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();
@@ -2757,7 +2786,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
return true;
}
- }, afterKeyguardGone);
+ }, cancelAction, afterKeyguardGone);
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -2817,10 +2846,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);
}
}