summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java105
4 files changed, 111 insertions, 11 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index b610cf394a32..75e3bc1d3db3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -62,7 +62,9 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
if (arg instanceof Boolean) {
state.value = (Boolean) arg;
}
- state.visible = mFlashlightController.isAvailable();
+ // Always show the tile when the flashlight is on. This is needed because
+ // the camera is not available while it is being used for the flashlight.
+ state.visible = state.value || mFlashlightController.isAvailable();
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
state.iconId = state.value
? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
@@ -77,4 +79,9 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
public void onFlashlightError() {
refreshState(false);
}
+
+ @Override
+ public void onFlashlightAvailabilityChanged(boolean available) {
+ refreshState();
+ }
}
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 b5f38ae468ce..74bc6984d137 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -38,6 +38,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.FlashlightController;
/**
* Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
@@ -63,6 +64,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private ActivityStarter mActivityStarter;
private UnlockMethodCache mUnlockMethodCache;
private LockPatternUtils mLockPatternUtils;
+ private FlashlightController mFlashlightController;
public KeyguardBottomAreaView(Context context) {
super(context);
@@ -102,6 +104,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mActivityStarter = activityStarter;
}
+ public void setFlashlightController(FlashlightController flashlightController) {
+ mFlashlightController = flashlightController;
+ }
+
private Intent getCameraIntent() {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
@@ -189,6 +195,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
public void launchCamera() {
+ mFlashlightController.killFlashlight();
Intent intent = getCameraIntent();
if (intent == SECURE_CAMERA_INTENT) {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
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 a5dee6d6fe2f..59becd391d49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -752,6 +752,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
mFlashlightController = new FlashlightController(mContext);
+ mKeyguardBottomArea.setFlashlightController(mFlashlightController);
mUserSwitcherController = new UserSwitcherController(mContext);
mKeyguardMonitor = new KeyguardMonitor();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index b059043eb586..e05e34bcbe37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -28,6 +28,7 @@ import android.hardware.camera2.CaptureRequest;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -41,6 +42,14 @@ import java.util.ArrayList;
public class FlashlightController {
private static final String TAG = "FlashlightController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final boolean ENFORCE_AVAILABILITY_LISTENER =
+ SystemProperties.getBoolean("persist.sysui.flash.listener", false);
+
+ private static final int DISPATCH_ERROR = 0;
+ private static final int DISPATCH_OFF = 1;
+ private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
private final CameraManager mCameraManager;
/** Call {@link #ensureHandler()} before using */
@@ -52,6 +61,8 @@ public class FlashlightController {
/** Lock on {@code this} when accessing */
private boolean mFlashlightEnabled;
+ private String mCameraId;
+ private boolean mCameraAvailable;
private CameraDevice mCameraDevice;
private CaptureRequest mFlashlightRequest;
private CameraCaptureSession mSession;
@@ -60,6 +71,20 @@ public class FlashlightController {
public FlashlightController(Context mContext) {
mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+ initialize();
+ }
+
+ public void initialize() {
+ try {
+ mCameraId = getCameraId();
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "Couldn't initialize.", e);
+ return;
+ }
+
+ ensureHandler();
+ mCameraAvailable = true;
+ mCameraManager.addAvailabilityListener(mAvailabilityListener, mHandler);
}
public synchronized void setFlashlight(boolean enabled) {
@@ -69,14 +94,20 @@ public class FlashlightController {
}
}
- public boolean isAvailable() {
- try {
- return getCameraId() != null;
- } catch (CameraAccessException e) {
- return false;
+ public void killFlashlight() {
+ boolean enabled;
+ synchronized (this) {
+ enabled = mFlashlightEnabled;
+ }
+ if (enabled) {
+ mHandler.post(mKillFlashlightRunnable);
}
}
+ public synchronized boolean isAvailable() {
+ return ENFORCE_AVAILABILITY_LISTENER ? mCameraAvailable : (mCameraId != null);
+ }
+
public void addListener(FlashlightListener l) {
synchronized (mListeners) {
cleanUpListenersLocked(l);
@@ -207,24 +238,30 @@ public class FlashlightController {
}
private void dispatchOff() {
- dispatchListeners(false, true /* off */);
+ dispatchListeners(DISPATCH_OFF, false /* argument (ignored) */);
}
private void dispatchError() {
- dispatchListeners(true /* error */, false);
+ dispatchListeners(DISPATCH_ERROR, false /* argument (ignored) */);
}
- private void dispatchListeners(boolean error, boolean off) {
+ private void dispatchAvailabilityChanged(boolean available) {
+ dispatchListeners(DISPATCH_AVAILABILITY_CHANGED, available);
+ }
+
+ private void dispatchListeners(int message, boolean argument) {
synchronized (mListeners) {
final int N = mListeners.size();
boolean cleanup = false;
for (int i = 0; i < N; i++) {
FlashlightListener l = mListeners.get(i).get();
if (l != null) {
- if (error) {
+ if (message == DISPATCH_ERROR) {
l.onFlashlightError();
- } else if (off) {
+ } else if (message == DISPATCH_OFF) {
l.onFlashlightOff();
+ } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
+ l.onFlashlightAvailabilityChanged(argument);
}
} else {
cleanup = true;
@@ -293,6 +330,48 @@ public class FlashlightController {
}
};
+ private final Runnable mKillFlashlightRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (this) {
+ mFlashlightEnabled = false;
+ }
+ updateFlashlight(true /* forceDisable */);
+ dispatchOff();
+ }
+ };
+
+ private final CameraManager.AvailabilityListener mAvailabilityListener =
+ new CameraManager.AvailabilityListener() {
+ @Override
+ public void onCameraAvailable(String cameraId) {
+ if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
+ if (cameraId.equals(mCameraId)) {
+ setCameraAvailable(true);
+ }
+ }
+
+ @Override
+ public void onCameraUnavailable(String cameraId) {
+ if (DEBUG) Log.d(TAG, "onCameraUnavailable(" + cameraId + ")");
+ if (cameraId.equals(mCameraId)) {
+ setCameraAvailable(false);
+ }
+ }
+
+ private void setCameraAvailable(boolean available) {
+ boolean changed;
+ synchronized (FlashlightController.this) {
+ changed = mCameraAvailable != available;
+ mCameraAvailable = available;
+ }
+ if (changed) {
+ if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
+ dispatchAvailabilityChanged(available);
+ }
+ }
+ };
+
public interface FlashlightListener {
/**
@@ -304,5 +383,11 @@ public class FlashlightController {
* Called when there is an error that turns the flashlight off.
*/
void onFlashlightError();
+
+ /**
+ * Called when there is a change in availability of the flashlight functionality
+ * @param available true if the flashlight is currently available.
+ */
+ void onFlashlightAvailabilityChanged(boolean available);
}
}