diff --git a/parts/AndroidManifest.xml b/parts/AndroidManifest.xml
index 33f323d..ad5474d 100644
--- a/parts/AndroidManifest.xml
+++ b/parts/AndroidManifest.xml
@@ -1,7 +1,7 @@
+ Warning
+ Couldn\'t close front camera. Try calibrating the motor.
+ Couldn\'t open front camera. Try calibrating the motor.
+ Front camera cannot be used during calibration.
+ Calibrate
+ Couldn\'t calibrate
+ Calibrated successfully. You can open the front camera now.
diff --git a/parts/res/values/styles.xml b/parts/res/values/styles.xml
index e98b9f6..73b3ea7 100644
--- a/parts/res/values/styles.xml
+++ b/parts/res/values/styles.xml
@@ -70,4 +70,7 @@
- 0.072727273
+
+
diff --git a/parts/src/org/lineageos/settings/popupcamera/Constants.java b/parts/src/org/lineageos/settings/popupcamera/Constants.java
index 339cd07..9554e8e 100644
--- a/parts/src/org/lineageos/settings/popupcamera/Constants.java
+++ b/parts/src/org/lineageos/settings/popupcamera/Constants.java
@@ -23,10 +23,14 @@ public class Constants {
public static final int MSG_CAMERA_CLOSED = 1001;
public static final int MSG_CAMERA_OPEN = 1002;
- public static final int MOTOR_STATUS_POPUP = 11;
- public static final int MOTOR_STATUS_POPUP_JAM = 12;
- public static final int MOTOR_STATUS_TAKEBACK = 13;
- public static final int MOTOR_STATUS_TAKEBACK_JAM = 14;
+ public static final int MOTOR_STATUS_POPUP_OK = 11;
+ public static final int MOTOR_STATUS_POPUP_JAMMED = 12;
+ public static final int MOTOR_STATUS_TAKEBACK_OK = 13;
+ public static final int MOTOR_STATUS_TAKEBACK_JAMMED = 14;
+ public static final int MOTOR_STATUS_PRESSED = 15;
+ public static final int MOTOR_STATUS_CALIB_OK = 17;
+ public static final int MOTOR_STATUS_CALIB_ERROR = 18;
+ public static final int MOTOR_STATUS_REQUEST_CALIB = 19;
public static final String CLOSE_CAMERA_STATE = "0";
public static final String OPEN_CAMERA_STATE = "1";
diff --git a/parts/src/org/lineageos/settings/popupcamera/PopupCameraService.java b/parts/src/org/lineageos/settings/popupcamera/PopupCameraService.java
index 40a9228..4e69c7d 100644
--- a/parts/src/org/lineageos/settings/popupcamera/PopupCameraService.java
+++ b/parts/src/org/lineageos/settings/popupcamera/PopupCameraService.java
@@ -17,8 +17,11 @@
package org.lineageos.settings.popupcamera;
import android.annotation.NonNull;
+import android.app.AlertDialog;
import android.app.Service;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -33,11 +36,14 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
+import android.view.WindowManager;
import org.lineageos.settings.R;
import org.lineageos.settings.utils.FileUtils;
import vendor.xiaomi.hardware.motor.V1_0.IMotor;
+import vendor.xiaomi.hardware.motor.V1_0.IMotorCallback;
+import vendor.xiaomi.hardware.motor.V1_0.MotorEvent;
public class PopupCameraService extends Service implements Handler.Callback {
private static final String TAG = "PopupCameraService";
@@ -50,6 +56,10 @@ public class PopupCameraService extends Service implements Handler.Callback {
private Handler mHandler = new Handler(this);
private IMotor mMotor = null;
+ private IMotorCallback mMotorStatusCallback;
+ private boolean mMotorCalibrating = false;
+ private boolean mErrorDialogShowing;
+ private final Object mLock = new Object();
private PopupCameraPreferences mPopupCameraPreferences;
private SensorManager mSensorManager;
private Sensor mFreeFallSensor;
@@ -127,15 +137,55 @@ public class PopupCameraService extends Service implements Handler.Callback {
try {
mMotor = IMotor.getService();
int status = mMotor.getMotorStatus();
- if (status == Constants.MOTOR_STATUS_POPUP || status == Constants.MOTOR_STATUS_POPUP_JAM
- || status == Constants.MOTOR_STATUS_TAKEBACK_JAM) {
+ if (status == Constants.MOTOR_STATUS_POPUP_OK
+ || status == Constants.MOTOR_STATUS_TAKEBACK_JAMMED) {
mMotor.takebackMotor(1);
}
+ mMotorStatusCallback = new MotorStatusCallback();
+ mMotor.setMotorCallback(mMotorStatusCallback);
} catch (RemoteException e) {
// Do nothing
}
}
+ private final class MotorStatusCallback extends IMotorCallback.Stub {
+ public MotorStatusCallback() {}
+
+ @Override
+ public void onNotify(MotorEvent event) {
+ int status = event.vaalue;
+ int cookie = event.cookie;
+ if (DEBUG)
+ Log.d(TAG, "onNotify: cookie=" + cookie + ", status=" + status);
+ synchronized (mLock) {
+ if (status == Constants.MOTOR_STATUS_CALIB_OK
+ || status == Constants.MOTOR_STATUS_CALIB_ERROR) {
+ mMotorCalibrating = false;
+ showCalibrationResult(status);
+ } else if (status == Constants.MOTOR_STATUS_PRESSED) {
+ updateMotor(Constants.CLOSE_CAMERA_STATE);
+ goBackHome();
+ } else if (status == Constants.MOTOR_STATUS_POPUP_JAMMED
+ || status == Constants.MOTOR_STATUS_TAKEBACK_JAMMED) {
+ showErrorDialog();
+ }
+ }
+ }
+ }
+
+ private void calibrateMotor() {
+ synchronized (mLock) {
+ if (mMotorCalibrating || mMotor == null)
+ return;
+ try {
+ mMotorCalibrating = true;
+ mMotor.calibration();
+ } catch (RemoteException e) {
+ // Do nothing
+ }
+ }
+ }
+
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (DEBUG)
@@ -161,25 +211,38 @@ public class PopupCameraService extends Service implements Handler.Callback {
}
final Runnable r = () -> {
mMotorBusy = true;
- mHandler.postDelayed(() -> mMotorBusy = false, 1200);
try {
+ int status = mMotor.getMotorStatus();
+ if (DEBUG)
+ Log.d(TAG, "updateMotor: status=" + status + ", cameraState=" + cameraState);
if (cameraState.equals(Constants.OPEN_CAMERA_STATE)
- && mMotor.getMotorStatus() == Constants.MOTOR_STATUS_TAKEBACK) {
+ && (status == Constants.MOTOR_STATUS_TAKEBACK_OK
+ || status == Constants.MOTOR_STATUS_CALIB_OK)) {
lightUp();
playSoundEffect(Constants.OPEN_CAMERA_STATE);
mMotor.popupMotor(1);
mSensorManager.registerListener(
mFreeFallListener, mFreeFallSensor, SensorManager.SENSOR_DELAY_NORMAL);
} else if (cameraState.equals(Constants.CLOSE_CAMERA_STATE)
- && mMotor.getMotorStatus() == Constants.MOTOR_STATUS_POPUP) {
+ && status == Constants.MOTOR_STATUS_POPUP_OK) {
lightUp();
playSoundEffect(Constants.CLOSE_CAMERA_STATE);
mMotor.takebackMotor(1);
mSensorManager.unregisterListener(mFreeFallListener, mFreeFallSensor);
+ } else {
+ mMotorBusy = false;
+ if (status == Constants.MOTOR_STATUS_POPUP_JAMMED
+ || status == Constants.MOTOR_STATUS_TAKEBACK_JAMMED
+ || status == Constants.MOTOR_STATUS_CALIB_ERROR
+ || status == Constants.MOTOR_STATUS_REQUEST_CALIB) {
+ showErrorDialog();
+ }
+ return;
}
} catch (RemoteException e) {
// Do nothing
}
+ mHandler.postDelayed(() -> mMotorBusy = false, 1200);
};
if (mMotorBusy) {
@@ -210,6 +273,68 @@ public class PopupCameraService extends Service implements Handler.Callback {
}
}
+ private void showCalibrationResult(int status) {
+ if (mErrorDialogShowing) {
+ return;
+ }
+ mErrorDialogShowing = true;
+ mHandler.post(() -> {
+ Resources res = getResources();
+ int dialogMessageResId = mMotorCalibrating
+ ? R.string.popup_camera_calibrate_running
+ : (status == Constants.MOTOR_STATUS_CALIB_OK
+ ? R.string.popup_camera_calibrate_success
+ : R.string.popup_camera_calibrate_failed);
+ AlertDialog.Builder alertDialogBuilder =
+ new AlertDialog.Builder(this, R.style.SystemAlertDialogTheme);
+ alertDialogBuilder.setMessage(res.getString(dialogMessageResId));
+ alertDialogBuilder.setPositiveButton(android.R.string.ok, null);
+ AlertDialog alertDialog = alertDialogBuilder.create();
+ alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ alertDialog.setCancelable(false);
+ alertDialog.setCanceledOnTouchOutside(false);
+ alertDialog.show();
+ alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ mErrorDialogShowing = false;
+ }
+ });
+ });
+ }
+
+ private void showErrorDialog() {
+ if (mErrorDialogShowing) {
+ return;
+ }
+ mErrorDialogShowing = true;
+ goBackHome();
+ mHandler.post(() -> {
+ Resources res = getResources();
+ String cameraState = "-1";
+ int dialogMessageResId = cameraState.equals(Constants.CLOSE_CAMERA_STATE)
+ ? R.string.popup_camera_takeback_failed_calibrate
+ : R.string.popup_camera_popup_failed_calibrate;
+ AlertDialog alertDialog =
+ new AlertDialog.Builder(this, R.style.SystemAlertDialogTheme)
+ .setTitle(res.getString(R.string.popup_camera_tip))
+ .setMessage(res.getString(dialogMessageResId))
+ .setPositiveButton(res.getString(R.string.popup_camera_calibrate_now),
+ (dialog, which) -> calibrateMotor())
+ .setNegativeButton(res.getString(android.R.string.cancel), null)
+ .create();
+ alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ alertDialog.setCanceledOnTouchOutside(false);
+ alertDialog.show();
+ alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ mErrorDialogShowing = false;
+ }
+ });
+ });
+ }
+
private void playSoundEffect(String state) {
int soundEffect = Integer.parseInt(mPopupCameraPreferences.getSoundEffect());
if (soundEffect != -1) {
diff --git a/proprietary-files.txt b/proprietary-files.txt
index 8ccd288..6ef9245 100644
--- a/proprietary-files.txt
+++ b/proprietary-files.txt
@@ -131,8 +131,6 @@ vendor/lib64/libmialgo_sd.so
vendor/lib64/libmialgo_utils.so
vendor/lib64/libmialgoengine.so
vendor/lib64/libmibokeh_712.so
-vendor/lib64/libmivendor_module_hall.so
-vendor/lib64/libmivendor_module_motor.so
vendor/lib64/libmmcamera_faceproc2.so
vendor/lib64/libmmcamera_faceproc.so
vendor/lib64/libmpbase.so
@@ -272,7 +270,11 @@ vendor/firmware/CAMERA_ICP.elf
# Camera motor
vendor/bin/hw/vendor.xiaomi.hardware.motor@1.0-service
+vendor/etc/step_motor/mi_camera_config.xml
vendor/lib64/hw/vendor.xiaomi.hardware.motor@1.0-impl.so
+vendor/lib64/libmivendor_module_calibration.so
+vendor/lib64/libmivendor_module_hall.so
+vendor/lib64/libmivendor_module_motor.so
vendor/lib64/mi.motor.daemon.so
# Camera (popup sound effects)
diff --git a/sepolicy/vendor/hal_motor_default.te b/sepolicy/vendor/hal_motor_default.te
index 7595068..dffd6aa 100644
--- a/sepolicy/vendor/hal_motor_default.te
+++ b/sepolicy/vendor/hal_motor_default.te
@@ -7,6 +7,8 @@ hal_server_domain(hal_motor_default, hal_motor)
binder_call(hal_motor_client, hal_motor_server)
+binder_call(hal_motor_default, system_app)
+
type hal_motor_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_motor_default)
@@ -16,8 +18,8 @@ allow hal_motor_client hal_motor_hwservice_xiaomi:hwservice_manager find;
allow hal_motor_default hall_device:chr_file rw_file_perms;
allow hal_motor_default motor_device:chr_file rw_file_perms;
-allow hal_motor_default persist_sensors_file:dir search;
-allow hal_motor_default persist_sensors_file:file r_file_perms;
+allow hal_motor_default persist_sensors_file:dir rw_dir_perms;
+allow hal_motor_default persist_sensors_file:file rw_file_perms;
allow hal_motor_default mnt_vendor_file:dir { search };