package com.xypower.mpapp; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.UriMatcher; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.text.TextUtils; import android.util.Base64; import android.util.Log; import com.xypower.common.FilesUtils; import com.xypower.common.JSONUtils; import com.xypower.common.MicroPhotoContext; import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.ArrayList; import java.util.List; public class BridgeProvider extends ContentProvider { private final static String TAG = "MPLOG"; private final static String AUTHORITY = "com.xypower.mpapp.provider"; private final static String PATH_QUERY_SEC_VERSION = "/querySecVersion"; private final static String PATH_QUERY_BATTERY_VOLTAGE = "/queryBatVol"; private final static String PATH_IMP_PRI_KEY = "/importPriKey"; private final static String PATH_IMP_PUB_KEY = "/importPubKey"; private final static String PATH_GEN_KEYS = "/genKeys"; private final static String PATH_GEN_CERT_REQ = "/genCertReq"; private final static String PATH_TAKE_PHOTO = "/takePhoto"; private final static String PATH_TAKE_VIDEO = "/takeVideo"; private final static String PATH_HDRPLUS = "/hdrplus"; private final static String PATH_RECOG_PIC = "/recogPic"; private final static String PATH_REQUEST_PWR_CTRL = "/requestPwrCtrl"; private final static String PATH_RELEASE_PWR_CTRL = "/releasePwrCtrl"; public BridgeProvider() { Log.i(TAG, "BridgeProvider"); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Implement this to handle requests to delete one or more rows. throw new UnsupportedOperationException("Not yet implemented"); } @Override public String getType(Uri uri) { // TODO: Implement this to handle requests for the MIME type of the data // at the given URI. throw new UnsupportedOperationException("Not yet implemented"); } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public boolean onCreate() { // TODO: Implement this to initialize your content provider on startup. return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); Log.i(TAG, uri.toString()); matcher.addURI(AUTHORITY, PATH_QUERY_SEC_VERSION, 1); matcher.addURI(AUTHORITY, PATH_QUERY_BATTERY_VOLTAGE, 2); matcher.addURI(AUTHORITY, PATH_RECOG_PIC, 3); matcher.addURI(AUTHORITY, PATH_REQUEST_PWR_CTRL, 4); matcher.addURI(AUTHORITY, PATH_RELEASE_PWR_CTRL, 5); Cursor cursor = null; int matched = matcher.match(uri); switch (matched) { case 1: cursor = querySecVersion(); break; case 2: cursor = queryBattaryVoltage(); break; case 3: cursor = recoganizePicture(uri, selection, selectionArgs); break; case 4: cursor = requestPowerControl(uri, selection, selectionArgs); break; case 5: cursor = recoganizePicture(uri, selection, selectionArgs); break; default: break; } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); matcher.addURI(AUTHORITY, PATH_IMP_PRI_KEY, 1); matcher.addURI(AUTHORITY, PATH_IMP_PUB_KEY, 2); matcher.addURI(AUTHORITY, PATH_GEN_KEYS, 3); matcher.addURI(AUTHORITY, PATH_GEN_CERT_REQ, 4); matcher.addURI(AUTHORITY, PATH_TAKE_PHOTO, 5); matcher.addURI(AUTHORITY, PATH_TAKE_VIDEO, 6); matcher.addURI(AUTHORITY, PATH_HDRPLUS, 7); int res = 0; int matched = matcher.match(uri); switch (matched) { case 1: res = importPrivateKey(uri, values); break; case 2: res = importPublicKey(uri, values); break; case 3: res = genKeys(uri, values); break; case 4: res = genCertReq(uri, values); break; case 5: res = takePhoto(uri, values); break; case 6: res = takeVideo(uri, values); break; case 7: res = hdrPlus(uri, values); break; default: break; } return res; } private Cursor querySecVersion() { String version = MicroPhotoService.querySecVersion(); String[] columns = { "version" }; MatrixCursor matrixCursor = new MatrixCursor(columns, 1); matrixCursor.addRow(new Object[] { version }); return matrixCursor; } private Cursor queryBattaryVoltage() { // #define CMD_GET_CHARGING_BUS_VOLTAGE_STATE 112 // #define CMD_GET_BAT_VOL_STATE 115 // #define CMD_GET_BAT_BUS_VOLTAGE_STATE 117 int bv = MicroPhotoService.getGpioInt(117); int bcv = MicroPhotoService.getGpioInt(112); String[] columns = { "bv", "bcv" }; MatrixCursor matrixCursor = new MatrixCursor(columns, 1); matrixCursor.addRow(new Object[] { Integer.valueOf(bv), Integer.valueOf(bcv) }); return matrixCursor; } private Cursor requestPowerControl(Uri uri, String selection, String[] selectionArgs) { String decodedSelection = stringFromBase64(selection); int type = 0; if (!TextUtils.isEmpty(decodedSelection)) { Uri u = Uri.parse("http://a.com/?" + decodedSelection); String val = u.getQueryParameter("type"); try { type = Integer.parseInt(val); } catch (Exception ex) { ex.printStackTrace(); } } long nativeHandle = MicroPhotoService.requestPowerControl(type); String[] columns = { "pwrCtrl" }; MatrixCursor matrixCursor = new MatrixCursor(columns, 1); matrixCursor.addRow(new Object[] { Long.valueOf(nativeHandle) }); return matrixCursor; } private Cursor releasePowerControl(Uri uri, String selection, String[] selectionArgs) { String decodedSelection = stringFromBase64(selection); long nativeHandle = 0; if (!TextUtils.isEmpty(decodedSelection)) { Uri u = Uri.parse("http://a.com/?" + decodedSelection); String val = u.getQueryParameter("handle"); try { nativeHandle = Long.parseLong(val); } catch (Exception ex) { ex.printStackTrace(); } } boolean res = MicroPhotoService.releasePowerControl(nativeHandle); String[] columns = { "result" }; MatrixCursor matrixCursor = new MatrixCursor(columns, 1); matrixCursor.addRow(new Object[] { Integer.valueOf(res ? 1 : 0) }); return matrixCursor; } private Cursor recoganizePicture(Uri uri, String selection, String[] selectionArgs) { String decodedSelection = stringFromBase64(selection); String paramPath = null; String binPath = null; String blobName8 = null; String blobName16 = null; String blobName32 = null; String path = null; if (!TextUtils.isEmpty(decodedSelection)) { Uri u = Uri.parse("http://a.com/?" + decodedSelection); paramPath = u.getQueryParameter("param"); binPath = u.getQueryParameter("bin"); blobName8 = u.getQueryParameter("b8"); blobName16 = u.getQueryParameter("b16"); blobName32 = u.getQueryParameter("b32"); path = u.getQueryParameter("path"); } if (TextUtils.isEmpty(paramPath) || TextUtils.isEmpty(binPath) || TextUtils.isEmpty(blobName8) || TextUtils.isEmpty(blobName16) || TextUtils.isEmpty(blobName32) || TextUtils.isEmpty(path)) { return null; } int[] data = MicroPhotoService.recoganizePicture(paramPath, binPath, blobName8, blobName16, blobName32, path); if (data == null || data.length == 0) { return null; } int rows = data.length / 6; if (rows == 0) { return null; } String[] columns = { "x", "y", "w", "h", "label", "prob" }; MatrixCursor matrixCursor = new MatrixCursor(columns, rows); int idx = 0; for (int row = 0; row < rows; row++) { matrixCursor.addRow(new Object[] { Integer.valueOf(data[idx]), Integer.valueOf(data[idx + 1]), Integer.valueOf(data[idx + 2]), Integer.valueOf(data[idx + 3]), Integer.valueOf(data[idx + 4]), Integer.valueOf(data[idx + 5])}); idx += 6; } return matrixCursor; } private int importPrivateKey(Uri uri, ContentValues values) { String cert = values.containsKey("cert") ? values.getAsString("cert") : null; String path = values.containsKey("path") ? values.getAsString("path") : null; String resultFile = values.containsKey("resultFile") ? values.getAsString("resultFile") : null; int index = values.containsKey("index") ? values.getAsInteger("index").intValue() : 0; Log.i(TAG, "Start import private key"); boolean res = false; if (!TextUtils.isEmpty(cert)) { // Import byte[] content = Base64.decode(cert, Base64.DEFAULT); if (content != null) { res = MicroPhotoService.importPrivateKey(index, content); } } else if (TextUtils.isEmpty(path)) { String md5 = values.containsKey("md5") ? values.getAsString("md5") : null; File file = new File(path); if (file.exists() && file.isFile()) { res = MicroPhotoService.importPrivateKeyFile(index, path, md5); } } Log.i(TAG, "Finish import private key"); if (!TextUtils.isEmpty(resultFile)) { FilesUtils.ensureParentDirectoryExisted(resultFile); FilesUtils.writeTextFile(resultFile, res ? "1" : "0"); } return res ? 1 : 0; } private int importPublicKey(Uri uri, ContentValues values) { String cert = values.containsKey("cert") ? values.getAsString("cert") : null; String path = values.containsKey("path") ? values.getAsString("path") : null; String resultFile = values.containsKey("resultFile") ? values.getAsString("resultFile") : null; int index = values.containsKey("index") ? values.getAsInteger("index").intValue() : 0; boolean res = false; if (!TextUtils.isEmpty(cert)) { // Import byte[] content = Base64.decode(cert, Base64.DEFAULT); if (content != null) { res = MicroPhotoService.importPublicKey(index, content); } } else if (TextUtils.isEmpty(path)) { String md5 = values.containsKey("md5") ? values.getAsString("md5") : null; File file = new File(path); if (file.exists() && file.isFile()) { res = MicroPhotoService.importPublicKeyFile(index, path, md5); } } if (!TextUtils.isEmpty(resultFile)) { FilesUtils.ensureParentDirectoryExisted(resultFile); FilesUtils.writeTextFile(resultFile, res ? "1" : "0"); } return res ? 1 : 0; } private int genKeys(Uri uri, ContentValues values) { int index = values.containsKey("index") ? values.getAsInteger("index").intValue() : 0; String resultFile = values.containsKey("resultFile") ? values.getAsString("resultFile") : null; boolean res = MicroPhotoService.genKeys(index); if (!TextUtils.isEmpty(resultFile)) { FilesUtils.ensureParentDirectoryExisted(resultFile); FilesUtils.writeTextFile(resultFile, res ? "1" : "0"); } return res ? 1 : 0; } private int genCertReq(Uri uri, ContentValues values) { int index = values.containsKey("index") ? values.getAsInteger("index").intValue() : 0; int type = values.containsKey("type") ? values.getAsInteger("type").intValue() : 0; String subject = values.containsKey("subject") ? values.getAsString("subject") : null; String path = values.containsKey("path") ? values.getAsString("path") : null; if (TextUtils.isEmpty(subject) || TextUtils.isEmpty(path)) { return 0; } boolean res = MicroPhotoService.genCertRequest(index, type, subject, path); return res ? 1 : 0; } private String stringFromBase64(String decoded) { if (TextUtils.isEmpty(decoded)) { return null; } byte[] bytes = Base64.decode(decoded, Base64.DEFAULT); String str = null; try { str = new String(bytes, "UTF-8"); } catch (Exception ex) { ex.printStackTrace(); } return str; } private int takePhoto(Uri uri, ContentValues values) { String path = values.containsKey("path") ? values.getAsString("path") : null; int channel = values.containsKey("channel") ? values.getAsInteger("channel").intValue() : 1; int preset = values.containsKey("preset") ? values.getAsInteger("preset").intValue() : 0xFF; int width = values.containsKey("width") ? values.getAsInteger("width").intValue() : 0; int height = values.containsKey("height") ? values.getAsInteger("height").intValue() : 0; String leftTopOsd = stringFromBase64(values.containsKey("leftTopOsd") ? values.getAsString("leftTopOsd") : null); String rightTopOsd = stringFromBase64(values.containsKey("rightTopOsd") ? values.getAsString("rightTopOsd") : null); String rightBottomOsd = stringFromBase64(values.containsKey("rightBottomOsd") ? values.getAsString("rightBottomOsd") : null); String leftBottomOsd = stringFromBase64(values.containsKey("leftBottomOsd") ? values.getAsString("leftBottomOsd") : null); String appPath = MicroPhotoContext.buildMpAppDir(getContext()); File configFile = new File(appPath); configFile = new File(configFile, "data/channels/" + Integer.toString(channel) + ".json"); File tmpConfigFile = new File(appPath); tmpConfigFile = new File(tmpConfigFile, "tmp/" + Integer.toString(channel) + "-" + Long.toString(System.currentTimeMillis()) + ".json"); if (configFile.exists()) { try { FilesUtils.copyFile(configFile, tmpConfigFile); } catch (Exception ex) { ex.printStackTrace(); } } JSONObject configJson = JSONUtils.loadJson(tmpConfigFile.getAbsolutePath()); try { if (configJson == null) { configJson = new JSONObject(); } if (width > 0) { configJson.put("resolutionCX", width); } if (height > 0) { configJson.put("resolutionCY", height); } JSONObject osdJson = configJson.getJSONObject("osd"); if (osdJson == null) { osdJson = configJson.put("osd", new JSONObject()); } osdJson.put("leftTop", TextUtils.isEmpty(leftTopOsd) ? "" : leftTopOsd); osdJson.put("rightTop", TextUtils.isEmpty(rightTopOsd) ? "" : rightTopOsd); osdJson.put("rightBottom", TextUtils.isEmpty(rightBottomOsd) ? "" : rightBottomOsd); osdJson.put("leftBottom", TextUtils.isEmpty(leftBottomOsd) ? "" : leftBottomOsd); JSONUtils.saveJson(tmpConfigFile.getAbsolutePath(), configJson); } catch (Exception ex) { ex.printStackTrace(); } File file = new File(path); if (file.exists()) { file.delete(); } else { FilesUtils.ensureParentDirectoryExisted(path); } MicroPhotoService.takePhoto(channel, preset, true, tmpConfigFile.getAbsolutePath(), path); if (tmpConfigFile.exists()) { tmpConfigFile.delete(); } return 1; } private int takeVideo(Uri uri, ContentValues values) { String path = values.containsKey("path") ? values.getAsString("path") : null; int channel = values.containsKey("channel") ? values.getAsInteger("channel").intValue() : 1; int preset = values.containsKey("preset") ? values.getAsInteger("preset").intValue() : 0xFF; int width = values.containsKey("width") ? values.getAsInteger("width").intValue() : 0; int height = values.containsKey("height") ? values.getAsInteger("height").intValue() : 0; int quality = values.containsKey("quality") ? values.getAsInteger("quality").intValue() : 0; int cameraId = values.containsKey("cameraId") ? values.getAsInteger("cameraId").intValue() : -1; int duration = values.containsKey("duration") ? values.getAsInteger("duration").intValue() : 15; int orientation = values.containsKey("orientation") ? values.getAsInteger("orientation").intValue() : 0; long videoId = System.currentTimeMillis() / 1000; String leftTopOsd = stringFromBase64(values.containsKey("leftTopOsd") ? values.getAsString("leftTopOsd") : null); String rightTopOsd = stringFromBase64(values.containsKey("rightTopOsd") ? values.getAsString("rightTopOsd") : null); String rightBottomOsd = stringFromBase64(values.containsKey("rightBottomOsd") ? values.getAsString("rightBottomOsd") : null); String leftBottomOsd = stringFromBase64(values.containsKey("leftBottomOsd") ? values.getAsString("leftBottomOsd") : null); if (cameraId == -1) { cameraId = channel - 1; } Context context = getContext(); Intent recordingIntent = MicroPhotoService.makeRecordingIntent(context, false, cameraId, videoId, duration, width, height, quality, orientation, leftTopOsd, rightTopOsd, rightBottomOsd, leftBottomOsd, path); recordingIntent.putExtra("resultType", 0); recordingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(recordingIntent); return 1; } private int hdrPlus(Uri uri, ContentValues values) { int rotation = values.containsKey("rotation") ? values.getAsInteger("rotation").intValue() : -1; int frontCamera = values.containsKey("front") ? values.getAsInteger("front").intValue() : 0; String outputPath = values.containsKey("output") ? values.getAsString("output") : null; int numberOfCaptures = values.containsKey("captures") ? values.getAsInteger("captures").intValue() : 0; List paths = new ArrayList<>(); for (int idx = 0; idx < numberOfCaptures; idx++) { String key = "path" + Integer.toString(idx + 1); String path = values.containsKey(key) ? values.getAsString(key) : null; if (!TextUtils.isEmpty(path)) { paths.add(path); } } ApplicationInfo applicationInfo = null; Context context = getContext(); try { applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_SHARED_LIBRARY_FILES); } catch (Exception ex) { } Log.d(TAG, "nativeLibraryDir= " + applicationInfo.nativeLibraryDir); String exeFilePath = applicationInfo.nativeLibraryDir + '/' + "libhdrp.so"; File hdrpFile = new File(exeFilePath); if (!hdrpFile.exists()) { return 0; } String cmd = exeFilePath + " " + Integer.toString(rotation) + " "; cmd += Integer.toString(frontCamera) + " "; cmd += outputPath + " " + TextUtils.join(" ", paths); String[] params = new String[]{""}; File workDir = context.getFilesDir(); int exitCode = 0; try { Process process = Runtime.getRuntime().exec(cmd, params, workDir.getAbsoluteFile()); // Intrinsics.checkNotNullExpressionValue(process, "process"); InputStream inputStream = process.getInputStream(); BufferedReader reader = new BufferedReader((Reader)(new InputStreamReader(inputStream))); // StringBuilder stringBuilder = new StringBuilder(); while(true) { String line = reader.readLine(); if (line == null) { exitCode = process.exitValue(); reader.close(); process.destroy(); break; } if (line != null) { // this.outputCallback.invoke(var5); Log.d("HDRPlus", line); // stringBuilder.append(line); // stringBuilder.append("\r\n"); } } } catch (Exception ex) { ex.printStackTrace(); } return 1; } }