Removed the secure camera launcher

With Android M, the system correctly handles camera arbitration
and therefore the secure camera launcher was only adding delay.

Bug: 23713450
Change-Id: Icd5e7883f3560bfd0c9b5f7bd93675847949469b
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 f4439bf..012dc9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -390,7 +390,8 @@
                 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
                 try {
                     if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
-                            Context.BIND_AUTO_CREATE, new UserHandle(UserHandle.USER_CURRENT))) {
+                            Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                            new UserHandle(UserHandle.USER_CURRENT))) {
                         mPrewarmBound = true;
                     }
                 } catch (SecurityException e) {
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 b93586e..9321938 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -111,12 +111,6 @@
     private boolean mQsTracking;
 
     /**
-     * Handles launching the secure camera properly even when other applications may be using the
-     * camera hardware.
-     */
-    private SecureCameraLaunchManager mSecureCameraLaunchManager;
-
-    /**
      * If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
      * the expansion for quick settings.
      */
@@ -262,8 +256,6 @@
         mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
         mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
         mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
-        mSecureCameraLaunchManager =
-                new SecureCameraLaunchManager(getContext(), mKeyguardBottomArea);
         mLastOrientation = getResources().getConfiguration().orientation;
 
         // recompute internal state when qspanel height changes
@@ -368,16 +360,6 @@
         updateMaxHeadsUpTranslation();
     }
 
-    @Override
-    public void onAttachedToWindow() {
-        mSecureCameraLaunchManager.create();
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        mSecureCameraLaunchManager.destroy();
-    }
-
     private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
         if (mQsSizeChangeAnimator != null) {
             oldHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
@@ -1963,7 +1945,7 @@
         } else {
             EventLogTags.writeSysuiLockscreenGesture(
                     EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
-            mSecureCameraLaunchManager.startSecureCameraLaunch();
+            mKeyguardBottomArea.launchCamera();
         }
         mStatusBar.startLaunchTransitionTimeout();
         mBlockTouches = true;
@@ -2010,7 +1992,6 @@
         boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
                 : rightIcon;
         if (camera) {
-            mSecureCameraLaunchManager.onSwipingStarted();
             mKeyguardBottomArea.bindCameraPrewarmService();
         }
         requestDisallowInterceptTouchEvent(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
deleted file mode 100644
index 45c8938..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.hardware.camera2.CameraManager;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.provider.MediaStore;
-import android.util.Log;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Handles launching the secure camera properly even when other applications may be using the camera
- * hardware.
- *
- * When other applications (e.g., Face Unlock) are using the camera, they must close the camera to
- * allow the secure camera to open it.  Since we want to minimize the delay when opening the secure
- * camera, other apps should close the camera at the first possible opportunity (i.e., as soon as
- * the user begins swiping to go to the secure camera).
- *
- * If the camera is unavailable when the user begins to swipe, the SecureCameraLaunchManager sends a
- * broadcast to tell other apps to close the camera.  When and if the user completes their swipe to
- * launch the secure camera, the SecureCameraLaunchManager delays launching the secure camera until
- * a callback indicates that the camera has become available.  If it doesn't receive that callback
- * within a specified timeout period, the secure camera is launched anyway.
- *
- * Ideally, the secure camera would handle waiting for the camera to become available.  This allows
- * some of the time necessary to close the camera to happen in parallel with starting the secure
- * camera app.  We can't rely on all third-party camera apps to handle this.  However, an app can
- * put com.android.systemui.statusbar.phone.will_wait_for_camera_available in its meta-data to
- * indicate that it will be responsible for waiting for the camera to become available.
- *
- * It is assumed that the functions in this class, including the constructor, will be called from
- * the UI thread.
- */
-public class SecureCameraLaunchManager {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "SecureCameraLaunchManager";
-
-    // Action sent as a broadcast to tell other apps to stop using the camera.  Other apps that use
-    // the camera from keyguard (e.g., Face Unlock) should listen for this broadcast and close the
-    // camera as soon as possible after receiving it.
-    private static final String CLOSE_CAMERA_ACTION_NAME =
-            "com.android.systemui.statusbar.phone.CLOSE_CAMERA";
-
-    // Apps should put this field in their meta-data to indicate that they will take on the
-    // responsibility of waiting for the camera to become available.  If this field is present, the
-    // SecureCameraLaunchManager launches the secure camera even if the camera hardware has not
-    // become available.  Having the secure camera app do the waiting is the optimal approach, but
-    // without this field, the SecureCameraLaunchManager doesn't launch the secure camera until the
-    // camera hardware is available.
-    private static final String META_DATA_WILL_WAIT_FOR_CAMERA_AVAILABLE =
-            "com.android.systemui.statusbar.phone.will_wait_for_camera_available";
-
-    // If the camera hardware hasn't become available after this period of time, the
-    // SecureCameraLaunchManager launches the secure camera anyway.
-    private static final int CAMERA_AVAILABILITY_TIMEOUT_MS = 1000;
-
-    private Context mContext;
-    private Handler mHandler;
-    private LockPatternUtils mLockPatternUtils;
-    private KeyguardBottomAreaView mKeyguardBottomArea;
-
-    private CameraManager mCameraManager;
-    private CameraAvailabilityCallback mCameraAvailabilityCallback;
-    private Map<String, Boolean> mCameraAvailabilityMap;
-    private boolean mWaitingToLaunchSecureCamera;
-    private Runnable mLaunchCameraRunnable;
-
-    private class CameraAvailabilityCallback extends CameraManager.AvailabilityCallback {
-        @Override
-        public void onCameraUnavailable(String cameraId) {
-            if (DEBUG) Log.d(TAG, "onCameraUnavailble(" + cameraId + ")");
-            mCameraAvailabilityMap.put(cameraId, false);
-        }
-
-        @Override
-        public void onCameraAvailable(String cameraId) {
-            if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
-            mCameraAvailabilityMap.put(cameraId, true);
-
-            // If we were waiting for the camera hardware to become available to launch the
-            // secure camera, we can launch it now if all cameras are available.  If one or more
-            // cameras are still not available, we will get this callback again for those
-            // cameras.
-            if (mWaitingToLaunchSecureCamera && areAllCamerasAvailable()) {
-                mKeyguardBottomArea.launchCamera();
-                mWaitingToLaunchSecureCamera = false;
-
-                // We no longer need to launch the camera after the timeout hits.
-                mHandler.removeCallbacks(mLaunchCameraRunnable);
-            }
-        }
-    }
-
-    public SecureCameraLaunchManager(Context context, KeyguardBottomAreaView keyguardBottomArea) {
-        mContext = context;
-        mHandler = new Handler();
-        mLockPatternUtils = new LockPatternUtils(context);
-        mKeyguardBottomArea = keyguardBottomArea;
-
-        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
-        mCameraAvailabilityCallback = new CameraAvailabilityCallback();
-
-        // An onCameraAvailable() or onCameraUnavailable() callback will be received for each camera
-        // when the availability callback is registered, thus initializing the map.
-        //
-        // Keeping track of the state of all cameras using the onCameraAvailable() and
-        // onCameraUnavailable() callbacks can get messy when dealing with hot-pluggable cameras.
-        // However, we have a timeout in place such that we will never hang waiting for cameras.
-        mCameraAvailabilityMap = new HashMap<String, Boolean>();
-
-        mWaitingToLaunchSecureCamera = false;
-        mLaunchCameraRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    if (mWaitingToLaunchSecureCamera) {
-                        Log.w(TAG, "Timeout waiting for camera availability");
-                        mKeyguardBottomArea.launchCamera();
-                        mWaitingToLaunchSecureCamera = false;
-                    }
-                }
-            };
-    }
-
-    /**
-     * Initializes the SecureCameraManager and starts listening for camera availability.
-     */
-    public void create() {
-        mCameraManager.registerAvailabilityCallback(mCameraAvailabilityCallback, mHandler);
-    }
-
-    /**
-     * Stops listening for camera availability and cleans up the SecureCameraManager.
-     */
-    public void destroy() {
-        mCameraManager.unregisterAvailabilityCallback(mCameraAvailabilityCallback);
-    }
-
-    /**
-     * Called when the user is starting to swipe horizontally, possibly to start the secure camera.
-     * Although this swipe ultimately may not result in the secure camera opening, we need to stop
-     * all other camera usage (e.g., Face Unlock) as soon as possible.  We send out a broadcast to
-     * notify other apps that they should close the camera immediately.  The broadcast is sent even
-     * if the camera appears to be available, because there could be an app that is about to open
-     * the camera.
-     */
-    public void onSwipingStarted() {
-        if (DEBUG) Log.d(TAG, "onSwipingStarted");
-        AsyncTask.execute(new Runnable() {
-                @Override
-                public void run() {
-                    Intent intent = new Intent();
-                    intent.setAction(CLOSE_CAMERA_ACTION_NAME);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                    mContext.sendBroadcast(intent);
-                }
-            });
-    }
-
-    /**
-     * Called when the secure camera should be started.  If the camera is available or the secure
-     * camera app has indicated that it will wait for camera availability, the secure camera app is
-     * launched immediately.  Otherwise, we wait for the camera to become available (or timeout)
-     * before launching the secure camera.
-     */
-    public void startSecureCameraLaunch() {
-        if (DEBUG) Log.d(TAG, "startSecureCameraLunch");
-        if (areAllCamerasAvailable() || targetWillWaitForCameraAvailable()) {
-            mKeyguardBottomArea.launchCamera();
-        } else {
-            mWaitingToLaunchSecureCamera = true;
-            mHandler.postDelayed(mLaunchCameraRunnable, CAMERA_AVAILABILITY_TIMEOUT_MS);
-        }
-    }
-
-    /**
-     * Returns true if all of the cameras we are tracking are currently available.
-     */
-    private boolean areAllCamerasAvailable() {
-        for (boolean cameraAvailable: mCameraAvailabilityMap.values()) {
-            if (!cameraAvailable) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Determines if the secure camera app will wait for the camera hardware to become available
-     * before trying to open the camera.  If so, we can fire off an intent to start the secure
-     * camera app before the camera is available.  Otherwise, it is our responsibility to wait for
-     * the camera hardware to become available before firing off the intent to start the secure
-     * camera.
-     *
-     * Ideally we are able to fire off the secure camera intent as early as possibly so that, if the
-     * camera is closing, it can continue to close while the secure camera app is opening.  This
-     * improves secure camera startup time.
-     */
-    private boolean targetWillWaitForCameraAvailable() {
-        // Create intent that would launch the secure camera.
-        Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
-                .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        PackageManager packageManager = mContext.getPackageManager();
-
-        // Get the list of applications that can handle the intent.
-        final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
-                intent, PackageManager.MATCH_DEFAULT_ONLY, KeyguardUpdateMonitor.getCurrentUser());
-        if (appList.size() == 0) {
-            if (DEBUG) Log.d(TAG, "No targets found for secure camera intent");
-            return false;
-        }
-
-        // Get the application that the intent resolves to.
-        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
-                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
-                KeyguardUpdateMonitor.getCurrentUser());
-
-        if (resolved == null || resolved.activityInfo == null) {
-            return false;
-        }
-
-        // If we would need to launch the resolver activity, then we can't assume that the target
-        // is one that would wait for the camera.
-        if (wouldLaunchResolverActivity(resolved, appList)) {
-            if (DEBUG) Log.d(TAG, "Secure camera intent would launch resolver");
-            return false;
-        }
-
-        // If the target doesn't have meta-data we must assume it won't wait for the camera.
-        if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
-            if (DEBUG) Log.d(TAG, "No meta-data found for secure camera application");
-            return false;
-        }
-
-        // Check the secure camera app meta-data to see if it indicates that it will wait for the
-        // camera to become available.
-        boolean willWaitForCameraAvailability =
-                resolved.activityInfo.metaData.getBoolean(META_DATA_WILL_WAIT_FOR_CAMERA_AVAILABLE);
-
-        if (DEBUG) Log.d(TAG, "Target will wait for camera: " + willWaitForCameraAvailability);
-
-        return willWaitForCameraAvailability;
-    }
-
-    /**
-     * Determines if the activity that would be launched by the intent is the ResolverActivity.
-     */
-    private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
-        // If the list contains the resolved activity, then it can't be the ResolverActivity itself.
-        for (int i = 0; i < appList.size(); i++) {
-            ResolveInfo tmp = appList.get(i);
-            if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
-                    && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
-                return false;
-            }
-        }
-        return true;
-    }
-}