mirror of
https://github.com/chararomandroid/android_device_samsung_a20
synced 2026-08-23 04:25:33 -04:00
universal7885: CameraLightSensor: Merge codes to 2 files and fix bugs
* Add proguard rules too * Auto-Brightness still working even if the settings is turned off
This commit is contained in:
parent
0546c8f6fe
commit
ae86b3fdcb
9 changed files with 357 additions and 390 deletions
|
|
@ -1,2 +0,0 @@
|
||||||
PRODUCT_MAKEFILES := \
|
|
||||||
$(LOCAL_DIR)/aosp_a20.mk
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
# Auto-Generated by device/samsung/a20/setup.sh
|
|
||||||
$(call inherit-product, device/samsung/a20/full_a20.mk)
|
|
||||||
$(call inherit-product, vendor/aosp/config/common_full_phone.mk)
|
|
||||||
PRODUCT_NAME := aosp_a20
|
|
||||||
|
|
||||||
# Additional Props
|
|
||||||
TARGET_FACE_UNLOCK_SUPPORTED := true
|
|
||||||
TARGET_BOOT_ANIMATION_RES := 720
|
|
||||||
|
|
@ -7,4 +7,7 @@ android_app {
|
||||||
privileged: true,
|
privileged: true,
|
||||||
certificate: "platform",
|
certificate: "platform",
|
||||||
static_libs: [ "androidx.core_core" ],
|
static_libs: [ "androidx.core_core" ],
|
||||||
|
optimize: {
|
||||||
|
proguard_flags_files: ["proguard.flags"],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,5 @@
|
||||||
<action android:name="android.intent.action.SCREEN_ON" />
|
<action android:name="android.intent.action.SCREEN_ON" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<service
|
|
||||||
android:name=".Camera2Service"
|
|
||||||
android:foregroundServiceType="camera">
|
|
||||||
</service>
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
7
universal7885-common/apps/CameraLightSensor/proguard.flags
Executable file
7
universal7885-common/apps/CameraLightSensor/proguard.flags
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
-renamesourcefileattribute SourceFile
|
||||||
|
|
@ -12,8 +12,7 @@ public class BootReceiver extends BroadcastReceiver {
|
||||||
final Intent i = new Intent();
|
final Intent i = new Intent();
|
||||||
i.setClassName("com.eurekateam.cameralightsensor",
|
i.setClassName("com.eurekateam.cameralightsensor",
|
||||||
"com.eurekateam.cameralightsensor.CameraLightSensorService");
|
"com.eurekateam.cameralightsensor.CameraLightSensorService");
|
||||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
context.startForegroundService(i);
|
||||||
context.startActivity(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,328 +0,0 @@
|
||||||
package com.eurekateam.cameralightsensor;
|
|
||||||
|
|
||||||
import static com.eurekateam.cameralightsensor.CameraLightSensorService.DEBUG;
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationChannel;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.ImageFormat;
|
|
||||||
import android.hardware.camera2.CameraAccessException;
|
|
||||||
import android.hardware.camera2.CameraCaptureSession;
|
|
||||||
import android.hardware.camera2.CameraCharacteristics;
|
|
||||||
import android.hardware.camera2.CameraDevice;
|
|
||||||
import android.hardware.camera2.CameraManager;
|
|
||||||
import android.hardware.camera2.CaptureRequest;
|
|
||||||
import android.media.Image;
|
|
||||||
import android.media.ImageReader;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
public class Camera2Service extends Service {
|
|
||||||
protected static final String TAG = Camera2Service.class.getSimpleName();
|
|
||||||
protected static final int CAMERACHOICE = CameraCharacteristics.LENS_FACING_FRONT;
|
|
||||||
boolean destroy;
|
|
||||||
protected CameraDevice cameraDevice;
|
|
||||||
protected CameraCaptureSession session;
|
|
||||||
boolean isavail = true;
|
|
||||||
protected ImageReader imageReader;
|
|
||||||
private Context mContext;
|
|
||||||
private CameraManager manager;
|
|
||||||
private long mCaptureTime;
|
|
||||||
private final int DELAY = 5000;
|
|
||||||
|
|
||||||
protected CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
|
|
||||||
@Override
|
|
||||||
public void onOpened(@NonNull CameraDevice camera) {
|
|
||||||
Log.d(TAG, "CameraDevice.StateCallback onOpened");
|
|
||||||
cameraDevice = camera;
|
|
||||||
actOnReadyCameraDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisconnected(@NonNull CameraDevice camera) {
|
|
||||||
Log.w(TAG, "CameraDevice.StateCallback onDisconnected");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(@NonNull CameraDevice camera, int error) {
|
|
||||||
Log.e(TAG, "CameraDevice.StateCallback onError " + error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected CameraCaptureSession.StateCallback sessionStateCallback = new CameraCaptureSession.StateCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReady(CameraCaptureSession session) {
|
|
||||||
if (!destroy) {
|
|
||||||
Camera2Service.this.session = session;
|
|
||||||
try {
|
|
||||||
if (createCaptureRequest() == null) return;
|
|
||||||
try {
|
|
||||||
session.capture(createCaptureRequest(), captureCallback, null);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Log.w(TAG, "onReady: Session is NULL");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Camera is in use");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigured(CameraCaptureSession session) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
protected ImageReader.OnImageAvailableListener onImageAvailableListener = reader -> {
|
|
||||||
if (DEBUG) Log.d(TAG, "onImageAvailable: Capturing");
|
|
||||||
Image img = reader.acquireLatestImage();
|
|
||||||
if (img != null) {
|
|
||||||
try {
|
|
||||||
processImage(img);
|
|
||||||
} catch (Settings.SettingNotFoundException | InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
img.close();
|
|
||||||
if (DEBUG)
|
|
||||||
Log.d(TAG, "ImageReader.OnImageAvailableListener: Closing Camera and Sessions..");
|
|
||||||
cameraDevice.close();
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
|
||||||
public void readyCamera() {
|
|
||||||
manager = (CameraManager) getSystemService(CAMERA_SERVICE);
|
|
||||||
mCaptureTime = System.currentTimeMillis();
|
|
||||||
try {
|
|
||||||
String pickedCamera = getCamera(manager);
|
|
||||||
manager.registerAvailabilityCallback(availabilityCallback, null);
|
|
||||||
manager.openCamera(pickedCamera, cameraStateCallback, null);
|
|
||||||
imageReader = ImageReader.newInstance(250, 250, ImageFormat.JPEG, 2 /* images buffered */);
|
|
||||||
imageReader.setOnImageAvailableListener(onImageAvailableListener, null);
|
|
||||||
if (DEBUG) Log.d(TAG, "imageReader created");
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, e.getMessage());
|
|
||||||
isavail = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCamera(CameraManager manager) {
|
|
||||||
try {
|
|
||||||
for (String cameraId : manager.getCameraIdList()) {
|
|
||||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
|
||||||
int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
|
|
||||||
if (cOrientation == CAMERACHOICE) {
|
|
||||||
return cameraId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
if(DEBUG) Log.d(TAG, "onStartCommand flags " + flags + " startId " + startId);
|
|
||||||
destroy = false;
|
|
||||||
isavail = true;
|
|
||||||
startForeground(50, PushNotification());
|
|
||||||
readyCamera();
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification PushNotification()
|
|
||||||
{
|
|
||||||
NotificationManager nm = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
|
|
||||||
NotificationChannel channel = new NotificationChannel(
|
|
||||||
mContext.getBasePackageName(), "CameraLightSensor",
|
|
||||||
NotificationManager.IMPORTANCE_LOW
|
|
||||||
);
|
|
||||||
nm.createNotificationChannel(channel);
|
|
||||||
NotificationCompat.Builder builder =
|
|
||||||
new NotificationCompat.Builder(mContext, mContext.getBasePackageName());
|
|
||||||
Intent notificationIntent = new Intent(mContext, Camera2Service.class);
|
|
||||||
PendingIntent contentIntent = PendingIntent.getActivity(mContext,50,
|
|
||||||
notificationIntent,PendingIntent.FLAG_IMMUTABLE);
|
|
||||||
|
|
||||||
//set
|
|
||||||
builder.setContentIntent(contentIntent);
|
|
||||||
builder.setSmallIcon(R.drawable.ic_brightness);
|
|
||||||
builder.setContentTitle("Camera Light Sensor Service");
|
|
||||||
builder.setChannelId(mContext.getBasePackageName());
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
if(DEBUG) Log.d(TAG, "onCreate service");
|
|
||||||
mContext = getApplicationContext();
|
|
||||||
startForeground(50, PushNotification());
|
|
||||||
readyCamera();
|
|
||||||
super.onCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void actOnReadyCameraDevice() {
|
|
||||||
try {
|
|
||||||
cameraDevice.createCaptureSession(Collections.singletonList(imageReader.getSurface()), sessionStateCallback, null);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
cameraDevice.close();
|
|
||||||
if (session != null && isavail) {
|
|
||||||
try {
|
|
||||||
session.abortCaptures();
|
|
||||||
session.close();
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, e.getMessage());
|
|
||||||
} catch (IllegalStateException e2){
|
|
||||||
Log.e(TAG, "Session Already Closed");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
manager.unregisterAvailabilityCallback(availabilityCallback);
|
|
||||||
isavail = false;
|
|
||||||
destroy = true;
|
|
||||||
stopForeground(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processImage(Image image) throws Settings.SettingNotFoundException, InterruptedException {
|
|
||||||
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
|
|
||||||
byte[] bytes = new byte[buffer.capacity()];
|
|
||||||
buffer.get(bytes);
|
|
||||||
Bitmap bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
|
|
||||||
int brightness = calculateBrightnessEstimate(bitmapImage,5);
|
|
||||||
AdjustBrightness(brightness);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CaptureRequest createCaptureRequest() {
|
|
||||||
try {
|
|
||||||
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
|
||||||
builder.addTarget(imageReader.getSurface());
|
|
||||||
return builder.build();
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
Log.e(TAG, e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraManager.AvailabilityCallback availabilityCallback = new CameraManager.AvailabilityCallback() {
|
|
||||||
@Override
|
|
||||||
public void onCameraOpened(String cameraId, String packageId) {
|
|
||||||
super.onCameraOpened(cameraId, packageId);
|
|
||||||
Log.i(TAG, "CameraManager.AvailabilityCallback: Camera " + cameraId
|
|
||||||
+ " Opened by Package " + packageId);
|
|
||||||
if (packageId.equals(mContext.getBasePackageName())) return;
|
|
||||||
isavail = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCameraUnavailable(String cameraId) {
|
|
||||||
if (DEBUG) Log.i(TAG, "CameraManager.AvailabilityCallback : Camera NOT Available. ");
|
|
||||||
isavail = false;
|
|
||||||
super.onCameraUnavailable(cameraId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCameraAvailable(String cameraId) {
|
|
||||||
if (DEBUG) Log.i(TAG, "CameraManager.AvailabilityCallback : Camera IS Available. ");
|
|
||||||
super.onCameraAvailable(cameraId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCameraClosed(String cameraId) {
|
|
||||||
super.onCameraClosed(cameraId);
|
|
||||||
while (mCaptureTime + DELAY >= System.currentTimeMillis() && isavail) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
if (DEBUG) Log.i(TAG, "CameraManager.AvailabilityCallback: " +
|
|
||||||
"Thread: Waiting...");
|
|
||||||
isavail = false;
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isavail = true;
|
|
||||||
Handler mHandler = new Handler(Looper.getMainLooper());
|
|
||||||
mHandler.postDelayed(() -> {
|
|
||||||
if(isavail) readyCamera();
|
|
||||||
},DELAY);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
|
|
||||||
@Override
|
|
||||||
public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {
|
|
||||||
if (DEBUG) Log.d(TAG, "captureCallback: Closing Session");
|
|
||||||
super.onCaptureSequenceCompleted(session, sequenceId, frameNumber);
|
|
||||||
cameraDevice.close();
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int calculateBrightnessEstimate(Bitmap bitmap, int pixelSpacing) {
|
|
||||||
int R = 0; int G = 0; int B = 0;
|
|
||||||
int height = bitmap.getHeight();
|
|
||||||
int width = bitmap.getWidth();
|
|
||||||
int n = 0;
|
|
||||||
int[] pixels = new int[width * height];
|
|
||||||
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
|
|
||||||
for (int i = 0; i < pixels.length; i += pixelSpacing) {
|
|
||||||
int color = pixels[i];
|
|
||||||
R += Color.red(color);
|
|
||||||
G += Color.green(color);
|
|
||||||
B += Color.blue(color);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
return (R + B + G) / (n * 3);
|
|
||||||
}
|
|
||||||
private void AdjustBrightness(int brightness) throws Settings.SettingNotFoundException {
|
|
||||||
if (DEBUG) Log.i(TAG, "AdjustBrightness: Received Brightness Value " + brightness);
|
|
||||||
int oldbrightness = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
|
|
||||||
if (DEBUG) Log.i(TAG, "AdjustBrightness: Oldval = " + oldbrightness + " Newval = " +
|
|
||||||
brightness + " Adjusting..");
|
|
||||||
int newbrightness = brightness;
|
|
||||||
if (newbrightness > 255){
|
|
||||||
newbrightness = 255;
|
|
||||||
}else if (newbrightness < 0){
|
|
||||||
newbrightness = 0;
|
|
||||||
}
|
|
||||||
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, newbrightness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +1,288 @@
|
||||||
package com.eurekateam.cameralightsensor;
|
package com.eurekateam.cameralightsensor;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.annotation.NonNull;
|
||||||
import android.app.Activity;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ImageFormat;
|
||||||
|
import android.hardware.camera2.CameraAccessException;
|
||||||
|
import android.hardware.camera2.CameraCaptureSession;
|
||||||
|
import android.hardware.camera2.CameraCharacteristics;
|
||||||
|
import android.hardware.camera2.CameraDevice;
|
||||||
|
import android.hardware.camera2.CameraManager;
|
||||||
|
import android.hardware.camera2.CaptureRequest;
|
||||||
|
import android.media.Image;
|
||||||
|
import android.media.ImageReader;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
public class CameraLightSensorService extends Activity {
|
import java.nio.ByteBuffer;
|
||||||
private static final String TAG = "CameraLightSensor";
|
import java.util.Collections;
|
||||||
static final boolean DEBUG = false;
|
|
||||||
Intent i;
|
public class CameraLightSensorService extends Service {
|
||||||
|
protected static final String TAG = CameraLightSensorService.class.getSimpleName();
|
||||||
|
static final boolean DEBUG = true;
|
||||||
IntentFilter screenStateFilter;
|
IntentFilter screenStateFilter;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
public ContentResolver contentResolver;
|
public ContentResolver contentResolver;
|
||||||
private boolean mRegistered;
|
private boolean mRegistered;
|
||||||
|
protected static final int CAMERA_CHOICE = CameraCharacteristics.LENS_FACING_FRONT;
|
||||||
|
boolean destroy;
|
||||||
|
protected CameraDevice cameraDevice;
|
||||||
|
protected CameraCaptureSession session;
|
||||||
|
volatile boolean avail = true;
|
||||||
|
protected ImageReader imageReader;
|
||||||
|
private CameraManager manager;
|
||||||
|
private final static int DELAY = 5 * 1000; // 5 Seconds
|
||||||
private boolean mServiceStarted;
|
private boolean mServiceStarted;
|
||||||
|
volatile private boolean mLock;
|
||||||
|
private boolean mThreadRunning;
|
||||||
|
|
||||||
|
public Notification PushNotification()
|
||||||
|
{
|
||||||
|
NotificationManager nm = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
NotificationChannel channel = new NotificationChannel(
|
||||||
|
mContext.getBasePackageName(), "CameraLightSensor",
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
);
|
||||||
|
nm.createNotificationChannel(channel);
|
||||||
|
NotificationCompat.Builder builder =
|
||||||
|
new NotificationCompat.Builder(mContext, mContext.getBasePackageName());
|
||||||
|
Intent notificationIntent = new Intent(mContext, CameraLightSensorService.class);
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(mContext,50,
|
||||||
|
notificationIntent,PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
|
||||||
|
//set
|
||||||
|
builder.setContentIntent(contentIntent);
|
||||||
|
builder.setSmallIcon(R.drawable.ic_brightness);
|
||||||
|
builder.setContentTitle("Camera Light Sensor Service");
|
||||||
|
builder.setChannelId(mContext.getBasePackageName());
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
public void onDestroy() {
|
||||||
super.onCreate(savedInstanceState);
|
if (DEBUG) Log.d(TAG, "Destroying service");
|
||||||
moveTaskToBack(true);
|
if(mRegistered) contentResolver.unregisterContentObserver(mSettingsObserver);
|
||||||
|
mRegistered = false;
|
||||||
|
cameraDevice.close();
|
||||||
|
if (session != null && avail) {
|
||||||
|
try {
|
||||||
|
session.abortCaptures();
|
||||||
|
session.close();
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
} catch (IllegalStateException e2){
|
||||||
|
Log.e(TAG, "Session Already Closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
manager.unregisterAvailabilityCallback(availabilityCallback);
|
||||||
|
avail = false;
|
||||||
|
destroy = true;
|
||||||
|
stopForeground(true);
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
|
||||||
|
onDisplayOn();
|
||||||
|
mServiceStarted = true;
|
||||||
|
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
||||||
|
if (mServiceStarted) onDisplayOff();
|
||||||
|
mServiceStarted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Make a listener for settings
|
||||||
|
ContentObserver mSettingsObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
super.onChange(selfChange);
|
||||||
|
Log.i(TAG, "observer: Brightness Settings Changed");
|
||||||
|
try {
|
||||||
|
if(Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE)
|
||||||
|
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC){
|
||||||
|
registerReceiver(mScreenStateReceiver, screenStateFilter);
|
||||||
|
mRegistered = true;
|
||||||
|
onDisplayOn();
|
||||||
|
}else{
|
||||||
|
if(mRegistered) unregisterReceiver(mScreenStateReceiver);
|
||||||
|
mRegistered = false;
|
||||||
|
onDisplayOff();
|
||||||
|
}
|
||||||
|
} catch (Settings.SettingNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean deliverSelfNotifications() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void onDisplayOn() {
|
||||||
|
if(DEBUG) Log.d(TAG, "Screen is on. Starting Service...");
|
||||||
|
avail = true;
|
||||||
|
readyCamera();
|
||||||
|
}
|
||||||
|
private void onDisplayOff(){
|
||||||
|
if(DEBUG) Log.d(TAG, "Screen is off. Stopping Service...");
|
||||||
|
thread.interrupt();
|
||||||
|
avail = false;
|
||||||
|
mThreadRunning = false;
|
||||||
|
}
|
||||||
|
public static void BatteryOptimization(Context context){
|
||||||
|
Intent intent = new Intent();
|
||||||
|
String packageName = context.getPackageName();
|
||||||
|
PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
|
||||||
|
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
|
||||||
|
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||||
|
intent.setData(Uri.parse("package:" + packageName));
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
|
||||||
|
@Override
|
||||||
|
public void onOpened(@NonNull CameraDevice camera) {
|
||||||
|
Log.d(TAG, "CameraDevice.StateCallback onOpened");
|
||||||
|
cameraDevice = camera;
|
||||||
|
actOnReadyCameraDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnected(@NonNull CameraDevice camera) {
|
||||||
|
Log.w(TAG, "CameraDevice.StateCallback onDisconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull CameraDevice camera, int error) {
|
||||||
|
Log.e(TAG, "CameraDevice.StateCallback onError " + error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected CameraCaptureSession.StateCallback sessionStateCallback = new CameraCaptureSession.StateCallback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReady(CameraCaptureSession session) {
|
||||||
|
if (!destroy) {
|
||||||
|
CameraLightSensorService.this.session = session;
|
||||||
|
try {
|
||||||
|
if (createCaptureRequest() == null) return;
|
||||||
|
try {
|
||||||
|
session.capture(createCaptureRequest(), captureCallback, null);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
Log.w(TAG, "onReady: Session is NULL");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Camera is in use");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigured(CameraCaptureSession session) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
protected ImageReader.OnImageAvailableListener onImageAvailableListener = reader -> {
|
||||||
|
if (DEBUG) Log.d(TAG, "onImageAvailable: Capturing");
|
||||||
|
Image img = reader.acquireLatestImage();
|
||||||
|
if (img != null) {
|
||||||
|
try {
|
||||||
|
processImage(img);
|
||||||
|
} catch (Settings.SettingNotFoundException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
img.close();
|
||||||
|
if (DEBUG)
|
||||||
|
Log.d(TAG, "ImageReader.OnImageAvailableListener: Closing Camera and Sessions..");
|
||||||
|
cameraDevice.close();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
public void readyCamera() {
|
||||||
|
manager = (CameraManager) getSystemService(CAMERA_SERVICE);
|
||||||
|
try {
|
||||||
|
String pickedCamera = getCamera(manager);
|
||||||
|
manager.registerAvailabilityCallback(availabilityCallback, null);
|
||||||
|
manager.openCamera(pickedCamera, cameraStateCallback, null);
|
||||||
|
imageReader = ImageReader.newInstance(250, 250, ImageFormat.JPEG, 2 /* images buffered */);
|
||||||
|
imageReader.setOnImageAvailableListener(onImageAvailableListener, null);
|
||||||
|
if(!mThreadRunning){
|
||||||
|
Thread mMyThread = new Thread(thread);
|
||||||
|
mMyThread.start();
|
||||||
|
mThreadRunning = true;
|
||||||
|
}
|
||||||
|
if (DEBUG) Log.d(TAG, "imageReader created");
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCamera(CameraManager manager) {
|
||||||
|
try {
|
||||||
|
for (String cameraId : manager.getCameraIdList()) {
|
||||||
|
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
||||||
|
int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||||
|
if (cOrientation == CAMERA_CHOICE) {
|
||||||
|
return cameraId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
mContext = getApplicationContext();
|
mContext = getApplicationContext();
|
||||||
contentResolver = getContentResolver();
|
contentResolver = getContentResolver();
|
||||||
|
startForeground(50, PushNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA);
|
||||||
BatteryOptimization(mContext);
|
BatteryOptimization(mContext);
|
||||||
i = new Intent(mContext, Camera2Service.class);
|
|
||||||
if (this.checkSelfPermission(Manifest.permission.CAMERA) ==
|
|
||||||
PackageManager.PERMISSION_GRANTED) {
|
|
||||||
Log.d(TAG, "Permission Granted");
|
|
||||||
} else {
|
|
||||||
// You can directly ask for the permission.
|
|
||||||
this.requestPermissions(new String[] { Manifest.permission.CAMERA },
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
mRegistered = false;
|
mRegistered = false;
|
||||||
screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
||||||
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||||
|
|
@ -57,71 +296,132 @@ public class CameraLightSensorService extends Activity {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
Uri setting = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
|
Uri setting = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
|
||||||
contentResolver.registerContentObserver(setting, false, observer);
|
contentResolver.registerContentObserver(setting, false, mSettingsObserver);
|
||||||
|
if(DEBUG) Log.d(TAG, "onStartCommand flags " + flags + " startId " + startId);
|
||||||
|
destroy = false;
|
||||||
|
avail = true;
|
||||||
|
startForeground(50, PushNotification());
|
||||||
|
return START_NOT_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onCreate() {
|
||||||
if (DEBUG) Log.d(TAG, "Destroying service");
|
if(DEBUG) Log.d(TAG, "onCreate service");
|
||||||
mRegistered = false;
|
mContext = getApplicationContext();
|
||||||
contentResolver.unregisterContentObserver(observer);
|
startForeground(50, PushNotification());
|
||||||
super.onDestroy();
|
super.onCreate();
|
||||||
}
|
}
|
||||||
private final BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
public void actOnReadyCameraDevice() {
|
||||||
public void onReceive(Context context, Intent intent) {
|
try {
|
||||||
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
|
cameraDevice.createCaptureSession(Collections.singletonList(imageReader.getSurface()), sessionStateCallback, null);
|
||||||
onDisplayOn();
|
} catch (CameraAccessException e) {
|
||||||
mServiceStarted = true;
|
Log.e(TAG, e.getMessage());
|
||||||
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
mLock = false;
|
||||||
if (mServiceStarted) onDisplayOff();
|
|
||||||
mServiceStarted = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
private void processImage(Image image) throws Settings.SettingNotFoundException, InterruptedException {
|
||||||
|
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
|
||||||
|
byte[] bytes = new byte[buffer.capacity()];
|
||||||
|
buffer.get(bytes);
|
||||||
|
Bitmap bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
|
||||||
|
int brightness = calculateBrightnessEstimate(bitmapImage,5);
|
||||||
|
AdjustBrightness(brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CaptureRequest createCaptureRequest() {
|
||||||
|
try {
|
||||||
|
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
||||||
|
builder.addTarget(imageReader.getSurface());
|
||||||
|
return builder.build();
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
mLock = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CameraManager.AvailabilityCallback availabilityCallback = new CameraManager.AvailabilityCallback() {
|
||||||
|
@Override
|
||||||
|
public void onCameraOpened(String cameraId, String packageId) {
|
||||||
|
super.onCameraOpened(cameraId, packageId);
|
||||||
|
Log.i(TAG, "CameraManager.AvailabilityCallback: Camera " + cameraId
|
||||||
|
+ " Opened by Package " + packageId);
|
||||||
|
mLock = true;
|
||||||
|
if (packageId.equals(mContext.getBasePackageName())) return;
|
||||||
|
avail = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraUnavailable(String cameraId) {
|
||||||
|
if (DEBUG) Log.i(TAG, "CameraManager.AvailabilityCallback : Camera NOT Available. ");
|
||||||
|
avail = false;
|
||||||
|
super.onCameraUnavailable(cameraId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraAvailable(String cameraId) {
|
||||||
|
if (DEBUG) Log.i(TAG, "CameraManager.AvailabilityCallback : Camera IS Available. ");
|
||||||
|
avail = true;
|
||||||
|
mLock = false;
|
||||||
|
super.onCameraAvailable(cameraId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraClosed(String cameraId) {
|
||||||
|
super.onCameraClosed(cameraId);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
// Make a listener
|
CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
|
||||||
ContentObserver observer = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {
|
||||||
super.onChange(selfChange);
|
if (DEBUG) Log.d(TAG, "captureCallback: Closing Session");
|
||||||
Log.i(TAG, "observer: Brightness Settings Changed");
|
super.onCaptureSequenceCompleted(session, sequenceId, frameNumber);
|
||||||
try {
|
cameraDevice.close();
|
||||||
if(Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE)
|
session.close();
|
||||||
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC){
|
|
||||||
registerReceiver(mScreenStateReceiver, screenStateFilter);
|
|
||||||
mRegistered = true;
|
|
||||||
mContext.startForegroundService(i);
|
|
||||||
}else{
|
|
||||||
if(mRegistered) unregisterReceiver(mScreenStateReceiver);
|
|
||||||
mRegistered = false;
|
|
||||||
mContext.stopService(i);
|
|
||||||
}
|
|
||||||
} catch (Settings.SettingNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean deliverSelfNotifications() {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
private void onDisplayOn() {
|
|
||||||
if(DEBUG) Log.d(TAG, "Screen is on. Starting Service...");
|
public int calculateBrightnessEstimate(Bitmap bitmap, int pixelSpacing) {
|
||||||
mContext.startForegroundService(i);
|
int R = 0; int G = 0; int B = 0;
|
||||||
|
int height = bitmap.getHeight();
|
||||||
|
int width = bitmap.getWidth();
|
||||||
|
int n = 0;
|
||||||
|
int[] pixels = new int[width * height];
|
||||||
|
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
for (int i = 0; i < pixels.length; i += pixelSpacing) {
|
||||||
|
int color = pixels[i];
|
||||||
|
R += Color.red(color);
|
||||||
|
G += Color.green(color);
|
||||||
|
B += Color.blue(color);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return (R + B + G) / (n * 3);
|
||||||
}
|
}
|
||||||
private void onDisplayOff(){
|
private void AdjustBrightness(int brightness) throws Settings.SettingNotFoundException {
|
||||||
if(DEBUG) Log.d(TAG, "Screen is off. Stopping Service...");
|
if (DEBUG) Log.i(TAG, "AdjustBrightness: Received Brightness Value " + brightness);
|
||||||
mContext.stopService(i);
|
int oldbrightness = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
|
||||||
|
if (DEBUG) Log.i(TAG, "AdjustBrightness: OldVal = " + oldbrightness + " NewVal = " +
|
||||||
|
brightness + " Adjusting..");
|
||||||
|
int newbrightness = brightness;
|
||||||
|
if (newbrightness > 255){
|
||||||
|
newbrightness = 255;
|
||||||
|
}else if (newbrightness < 0){
|
||||||
|
newbrightness = 0;
|
||||||
|
}
|
||||||
|
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, newbrightness);
|
||||||
}
|
}
|
||||||
public static void BatteryOptimization(Context context){
|
Thread thread = new Thread(() -> {
|
||||||
Intent intent = new Intent();
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
String packageName = context.getPackageName();
|
if (avail && !mLock) {
|
||||||
PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
|
SystemClock.sleep(DELAY);
|
||||||
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
|
ContextCompat.getMainExecutor(mContext).execute(() -> {
|
||||||
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
if (avail) readyCamera();
|
||||||
intent.setData(Uri.parse("package:" + packageName));
|
});
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in a new issue