Merge branch 'master' into release_robosweeper-d_100-sweeper_220830_1.0.0.1_merge
# Conflicts: # app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java # core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/MoGoAutopilotProvider.kt # core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.kt # core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasMsgConnectStatusListenerImpl.kt # core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/widget/TrafficDataView.java # core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/map/MapPointCloudSubscriber.kt # core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotProvider.kt # gradle.properties # libraries/mogo-adas-data/src/main/proto/message_pad.proto # libraries/mogo-adas-data/src/main/proto/special_vehicle_task_cmd.proto # libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/AdasChannel.java # libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/AdasManager.java # libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/IAdasNetCommApi.java # libraries/mogo-adas/src/main/java/com/zhidao/support/adas/high/common/MessageType.java
This commit is contained in:
@@ -82,7 +82,6 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
implementation rootProject.ext.dependencies.flexbox
|
||||
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.mogo.eagle.core.data.deva.scene.SceneTAG
|
||||
import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider
|
||||
import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager
|
||||
import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchManager
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.MonitorManager
|
||||
import com.zhjt.mogo_core_function_devatools.scene.SceneManager.Companion.sceneManager
|
||||
import com.zhjt.mogo_core_function_devatools.status.*
|
||||
import com.zhjt.mogo_core_function_devatools.trace.TraceManager.Companion.traceManager
|
||||
@@ -110,4 +111,12 @@ class DevaToolsProvider : IDevaToolsProvider {
|
||||
override fun hideStatusBar() {
|
||||
StatusManager.hide()
|
||||
}
|
||||
|
||||
override fun startMonitor() {
|
||||
mContext?.let { MonitorManager.getInstance(it)?.startMonitor() }
|
||||
}
|
||||
|
||||
override fun stopMonitor() {
|
||||
mContext?.let { MonitorManager.getInstance(it)?.stopMonitor() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Process
|
||||
import android.util.Log
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.db.CpuInfo
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.db.MonitorDb
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.utils.CpuUtils
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
class CpuMonitor private constructor(var context: Context) {
|
||||
|
||||
var isRunning = false
|
||||
|
||||
private val pid by lazy {
|
||||
Process.myPid()
|
||||
}
|
||||
|
||||
private val cpuInfoList by lazy {
|
||||
ArrayList<CpuInfo>()
|
||||
}
|
||||
|
||||
private val dateFormat by lazy {
|
||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CpuMonitor"
|
||||
const val INTERVAL_PERF = 1000L
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@Volatile
|
||||
private var sInstance: CpuMonitor? = null
|
||||
fun getInstance(context: Context): CpuMonitor? {
|
||||
if (sInstance == null) {
|
||||
synchronized(CpuMonitor::class.java) {
|
||||
if (sInstance == null) {
|
||||
sInstance = CpuMonitor(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请先运行Shizuku的服务
|
||||
*/
|
||||
@Synchronized
|
||||
fun startRun() {
|
||||
if (!isRunning) {
|
||||
Thread(CpuRunnable()).start()
|
||||
isRunning = true
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun isStarted() = isRunning
|
||||
|
||||
@Synchronized
|
||||
fun stop() {
|
||||
isRunning = false
|
||||
}
|
||||
|
||||
fun saveCpuInfos() {
|
||||
synchronized(this) {
|
||||
MonitorDb.getDb(context).monitorDao().saveAllCpuInfos(*cpuInfoList.toTypedArray())
|
||||
cpuInfoList.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCpuValue(): Double {
|
||||
var value = 0.0
|
||||
try {
|
||||
// 应用获取当前进程CPU使用时间,Binder服务端获取系统CPU时间,中间用耗时,不如使用top命令
|
||||
// value = UserServiceManager.getCpuUsage(Process.myPid())
|
||||
value = CpuUtils.getCpuUsageForO()
|
||||
return value
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.message ?: "未知异常!")
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
inner class CpuRunnable : Runnable {
|
||||
override fun run() {
|
||||
while (isRunning) {
|
||||
val cpu = getCpuValue()
|
||||
if (cpu > 0) {
|
||||
synchronized(this@CpuMonitor) {
|
||||
cpuInfoList.add(
|
||||
CpuInfo(
|
||||
saveTime = dateFormat.format(System.currentTimeMillis()),
|
||||
cpuPercent = cpu
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(INTERVAL_PERF)
|
||||
} catch (e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Process.myPid
|
||||
import android.util.Log
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.db.MemInfo
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.db.MonitorDb
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.utils.HookUtils
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.utils.MemUtils
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
class MemMonitor private constructor(var context: Context) {
|
||||
|
||||
var isRunning = false
|
||||
|
||||
private val memInfoList by lazy {
|
||||
ArrayList<MemInfo>()
|
||||
}
|
||||
|
||||
private val dateFormat by lazy {
|
||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MemMonitor"
|
||||
const val INTERVAL_PERF = 1000L
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@Volatile
|
||||
private var sInstance: MemMonitor? = null
|
||||
fun getInstance(context: Context): MemMonitor? {
|
||||
if (sInstance == null) {
|
||||
synchronized(MemMonitor::class.java) {
|
||||
if (sInstance == null) {
|
||||
sInstance = MemMonitor(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun startRun() {
|
||||
if (!isRunning) {
|
||||
Thread(MemoryRunnable()).start()
|
||||
isRunning = true
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun isStarted() = isRunning
|
||||
|
||||
@Synchronized
|
||||
fun stop() {
|
||||
isRunning = false
|
||||
}
|
||||
|
||||
fun saveMemInfos() {
|
||||
synchronized(this) {
|
||||
MonitorDb.getDb(context).monitorDao().saveAllMemInfos(*memInfoList.toTypedArray())
|
||||
memInfoList.clear()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单位MB
|
||||
*/
|
||||
private fun getMemoryValue(): Double {
|
||||
var value = 0.0
|
||||
try {
|
||||
value = MemUtils.getPssMemValue(context, intArrayOf(myPid()))
|
||||
return value
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.message ?: "未知异常!")
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* 单位MB
|
||||
*/
|
||||
private fun getMemoryArray(): DoubleArray {
|
||||
var value = doubleArrayOf()
|
||||
try {
|
||||
value = MemUtils.getPssArray(context, intArrayOf(myPid()))
|
||||
return value
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.message ?: "未知异常!")
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
inner class MemoryRunnable : Runnable {
|
||||
override fun run() {
|
||||
while (isRunning) {
|
||||
// 0: 总PSS,1: dalvik总Pss, 2: native总Pss, 3: other总Pss
|
||||
val pssArray = getMemoryArray()
|
||||
if (pssArray[0] > 0) {
|
||||
synchronized(this@MemMonitor) {
|
||||
memInfoList.add(
|
||||
MemInfo(
|
||||
saveTime = dateFormat.format(System.currentTimeMillis()),
|
||||
totalPss = pssArray[0],
|
||||
dalvikPss = pssArray[1],
|
||||
nativePss = pssArray[2],
|
||||
otherPss = pssArray[3]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(INTERVAL_PERF)
|
||||
} catch (e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Looper
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import java.util.*
|
||||
|
||||
class MonitorManager private constructor(var context: Context) {
|
||||
|
||||
private var timer: Timer? = null
|
||||
|
||||
private var isStarted = false
|
||||
|
||||
companion object {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@Volatile
|
||||
private var sInstance: MonitorManager? = null
|
||||
fun getInstance(context: Context): MonitorManager? {
|
||||
if (sInstance == null) {
|
||||
synchronized(MonitorManager::class.java) {
|
||||
if (sInstance == null) {
|
||||
sInstance = MonitorManager(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主线程中执行
|
||||
*/
|
||||
fun startMonitor() {
|
||||
if (Thread.currentThread() == Looper.getMainLooper().thread) {
|
||||
if (!isStarted) {
|
||||
CpuMonitor.getInstance(context)?.startRun()
|
||||
MemMonitor.getInstance(context)?.startRun()
|
||||
if (timer == null) {
|
||||
timer = Timer()
|
||||
}
|
||||
timer!!.schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
CpuMonitor.getInstance(context)?.saveCpuInfos()
|
||||
MemMonitor.getInstance(context)?.saveMemInfos()
|
||||
}
|
||||
}, 1000, 60000)
|
||||
isStarted = true
|
||||
ToastUtils.showShort("性能监控启动成功!")
|
||||
} else {
|
||||
ToastUtils.showShort("性能监控已启动,请勿重复启动!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stopMonitor() {
|
||||
CpuMonitor.getInstance(context)?.stop()
|
||||
MemMonitor.getInstance(context)?.stop()
|
||||
timer?.cancel()
|
||||
timer = null
|
||||
isStarted = false
|
||||
ToastUtils.showShort("性能监控停止成功!")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.db
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "t_cpu")
|
||||
data class CpuInfo(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = "id")
|
||||
val uuid: Long = 0,
|
||||
|
||||
@ColumnInfo(name = "save_time")
|
||||
val saveTime: String?,
|
||||
|
||||
@ColumnInfo(name = "cpu_percent")
|
||||
val cpuPercent: Double
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.db
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "t_memory")
|
||||
data class MemInfo(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = "id")
|
||||
val uuid: Long = 0,
|
||||
|
||||
@ColumnInfo(name = "save_time")
|
||||
val saveTime: String,
|
||||
|
||||
@ColumnInfo(name = "total_pss")
|
||||
val totalPss: Double,
|
||||
|
||||
@ColumnInfo(name = "dalvik_pss")
|
||||
val dalvikPss: Double,
|
||||
|
||||
@ColumnInfo(name = "native_pss")
|
||||
val nativePss: Double,
|
||||
|
||||
@ColumnInfo(name = "other_pss")
|
||||
val otherPss: Double
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.db
|
||||
|
||||
import androidx.room.*
|
||||
|
||||
@Dao
|
||||
interface MonitorDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun saveCpu(info: CpuInfo)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun saveAllCpuInfos(vararg cpuInfo: CpuInfo)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun saveMemory(info: MemInfo)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun saveAllMemInfos(vararg memInfo: MemInfo)
|
||||
|
||||
@Query("SELECT * FROM t_cpu WHERE id =:id")
|
||||
fun getAllCPUById(id: Long): List<CpuInfo>
|
||||
|
||||
@Query("SELECT * FROM t_memory WHERE id =:id")
|
||||
fun getAllMemById(id: Long): List<MemInfo>
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(entities = [CpuInfo::class, MemInfo::class], version = 1, exportSchema = false)
|
||||
abstract class MonitorDb: RoomDatabase() {
|
||||
abstract fun monitorDao(): MonitorDao
|
||||
|
||||
companion object {
|
||||
const val INTERNAL_DB_NAME = "mogo_monitor.db"
|
||||
|
||||
private var db: MonitorDb? = null
|
||||
|
||||
@JvmStatic
|
||||
fun getDb(context: Context): MonitorDb {
|
||||
if (db == null) {
|
||||
db = Room.databaseBuilder(context.applicationContext, MonitorDb::class.java, INTERNAL_DB_NAME)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
return db!!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.remote;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.RemoteException;
|
||||
|
||||
public interface IUserInterface extends IInterface {
|
||||
|
||||
String DESCRIPTOR = "rikka.shizuku.demo.IUserInterface";
|
||||
|
||||
int TRANSACTION_exec = IBinder.FIRST_CALL_TRANSACTION;
|
||||
int TRANSACTION_getCpuUsage = IBinder.FIRST_CALL_TRANSACTION + 1;
|
||||
|
||||
String exec(String cmd) throws RemoteException;
|
||||
|
||||
double getCpuUsage(int pid) throws RemoteException;
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.remote;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.zhjt.mogo_core_function_devatools.monitor.utils.CpuUtils;
|
||||
|
||||
/**
|
||||
* Server端Binder类
|
||||
*/
|
||||
public class RemoteUserServiceImp extends Binder implements IUserInterface {
|
||||
|
||||
public RemoteUserServiceImp() {
|
||||
attachInterface(this, DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static IUserInterface asInterface(IBinder obj) {
|
||||
if ((obj == null)) {
|
||||
return null;
|
||||
}
|
||||
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
|
||||
if (iin instanceof IUserInterface) {
|
||||
return ((IUserInterface) iin);
|
||||
}
|
||||
return new Proxy(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String exec(String cmd) throws RemoteException {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCpuUsage(int pid) throws RemoteException {
|
||||
return CpuUtils.getCpuUsagePercentWithPid(pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Client端请求
|
||||
*
|
||||
* @param code
|
||||
* @param data
|
||||
* @param reply
|
||||
* @param flags
|
||||
* @return
|
||||
* @throws RemoteException
|
||||
*/
|
||||
@Override
|
||||
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
|
||||
final String descriptor = DESCRIPTOR;
|
||||
switch (code) {
|
||||
case TRANSACTION_exec:
|
||||
data.enforceInterface(descriptor);
|
||||
String _arg0;
|
||||
_arg0 = data.readString();
|
||||
String _result = this.exec(_arg0);
|
||||
reply.writeNoException();
|
||||
reply.writeString(_result);
|
||||
return true;
|
||||
default:
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getInterfaceDescriptor() {
|
||||
return super.getInterfaceDescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回给Client端并被封装成BinderProxy
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Proxy implements IUserInterface {
|
||||
private IBinder mRemote;
|
||||
|
||||
public Proxy(IBinder remote) {
|
||||
mRemote = remote;
|
||||
}
|
||||
|
||||
public String getInterfaceDescriptor() {
|
||||
return DESCRIPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
// 返回Server端Binder对象
|
||||
return mRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String exec(String cmd) throws RemoteException {
|
||||
// 参数传递给Server端并挂起当前线程,等待Server端执行完返回结果
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
String _result;
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeString(cmd);
|
||||
mRemote.transact(TRANSACTION_exec, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = _reply.readString();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCpuUsage(int pid) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
double _result;
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeInt(pid);
|
||||
mRemote.transact(TRANSACTION_getCpuUsage, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = _reply.readDouble();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.remote
|
||||
|
||||
//import rikka.shizuku.Shizuku
|
||||
//import android.content.ServiceConnection
|
||||
//import android.content.ComponentName
|
||||
//import android.os.IBinder
|
||||
//import rikka.shizuku.Shizuku.UserServiceArgs
|
||||
//import android.content.pm.PackageManager
|
||||
//import android.util.Log
|
||||
//import com.mogo.eagle.core.utilcode.util.AppUtils
|
||||
//import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
//import rikka.shizuku.Shizuku.OnBinderReceivedListener
|
||||
//import rikka.shizuku.Shizuku.OnBinderDeadListener
|
||||
//import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
|
||||
//import java.lang.StringBuilder
|
||||
|
||||
object UserServiceManager {
|
||||
|
||||
// private const val TAG = "UserServiceManager"
|
||||
// private const val REQUEST_CODE_BIND = 1
|
||||
// private const val REQUEST_CODE_UNBIND = 2
|
||||
//
|
||||
// private var userServiceProxy: IUserInterface? = null
|
||||
// private var isFirst = true
|
||||
//
|
||||
// fun init() {
|
||||
// if (isFirst) {
|
||||
// addListener()
|
||||
// isFirst = false
|
||||
// }
|
||||
// bindUserService()
|
||||
// }
|
||||
//
|
||||
// fun stopService() {
|
||||
// removeListener()
|
||||
// unbindUserService()
|
||||
// }
|
||||
//
|
||||
// fun isServiceActive(): Boolean {
|
||||
// var isActive = false
|
||||
// val service = userServiceProxy
|
||||
// if (service != null && service is IBinder && service.isBinderAlive) {
|
||||
// isActive = true
|
||||
// }
|
||||
// return isActive
|
||||
// }
|
||||
//
|
||||
// private fun addListener() {
|
||||
// Shizuku.addBinderReceivedListenerSticky(BINDER_RECEIVED_LISTENER)
|
||||
// Shizuku.addBinderDeadListener(BINDER_DEAD_LISTENER)
|
||||
// Shizuku.addRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER)
|
||||
// }
|
||||
//
|
||||
// private fun removeListener() {
|
||||
// Shizuku.removeBinderReceivedListener(BINDER_RECEIVED_LISTENER)
|
||||
// Shizuku.removeBinderDeadListener(BINDER_DEAD_LISTENER)
|
||||
// Shizuku.removeRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER)
|
||||
// }
|
||||
//
|
||||
// private fun bindUserService() {
|
||||
// if (checkPermission(REQUEST_CODE_BIND)) {
|
||||
// val res = StringBuilder()
|
||||
// try {
|
||||
// if (Shizuku.getVersion() < 10) {
|
||||
// res.append("requires Shizuku API 10")
|
||||
// } else {
|
||||
// Shizuku.bindUserService(userServiceArgs, userServiceConnection)
|
||||
// }
|
||||
// } catch (tr: Throwable) {
|
||||
// tr.printStackTrace()
|
||||
// res.append(tr.toString())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun unbindUserService() {
|
||||
// if (checkPermission(REQUEST_CODE_UNBIND)) {
|
||||
// val res = StringBuilder()
|
||||
// try {
|
||||
// if (Shizuku.getVersion() < 10) {
|
||||
// res.append("requires Shizuku API 10")
|
||||
// } else {
|
||||
// Shizuku.unbindUserService(userServiceArgs, userServiceConnection, true)
|
||||
// }
|
||||
// } catch (tr: Throwable) {
|
||||
// tr.printStackTrace()
|
||||
// res.append(tr.toString())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun exec(cmd: String): String {
|
||||
// return userServiceProxy?.exec(cmd) ?: ""
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 单位:%,保留1位小数
|
||||
// */
|
||||
// fun getCpuUsage(pid: Int): Double {
|
||||
// return userServiceProxy?.getCpuUsage(pid) ?: -1.0
|
||||
// }
|
||||
//
|
||||
// private val userServiceConnection: ServiceConnection = object : ServiceConnection {
|
||||
// override fun onServiceConnected(componentName: ComponentName, binder: IBinder?) {
|
||||
// if (binder != null && binder.pingBinder()) {
|
||||
// val service = RemoteUserServiceImp.asInterface(binder)
|
||||
// userServiceProxy = service
|
||||
// ToastUtils.showShort("监控权限获取成功!")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onServiceDisconnected(componentName: ComponentName) {}
|
||||
// }
|
||||
//
|
||||
// private val userServiceArgs by lazy {
|
||||
// val appInfo = AppUtils.getAppInfo()
|
||||
// UserServiceArgs(
|
||||
// ComponentName(
|
||||
// appInfo?.packageName ?: "com.mogo.launcher.f",
|
||||
// RemoteUserServiceImp::class.java.name
|
||||
// )
|
||||
// )
|
||||
// .daemon(false)
|
||||
// .processNameSuffix("service")
|
||||
// .debuggable(true)
|
||||
// .version(appInfo?.versionCode ?: 1)
|
||||
// }
|
||||
//
|
||||
// private fun checkPermission(code: Int): Boolean {
|
||||
// if (Shizuku.isPreV11()) {
|
||||
// Log.w(TAG, "Version is preV11!")
|
||||
// return false
|
||||
// }
|
||||
// try {
|
||||
// return if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
|
||||
// true
|
||||
// } else if (Shizuku.shouldShowRequestPermissionRationale()) {
|
||||
// Log.e(TAG, "User denied permission (shouldShowRequestPermissionRationale=true)")
|
||||
// false
|
||||
// } else {
|
||||
// Shizuku.requestPermission(code)
|
||||
// false
|
||||
// }
|
||||
// } catch (e: Throwable) {
|
||||
// Log.e(TAG, Log.getStackTraceString(e))
|
||||
// ToastUtils.showLong("请先打开Shizuku并启动它!")
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// private fun onRequestPermissionsResult(requestCode: Int, grantResult: Int) {
|
||||
// if (grantResult == PackageManager.PERMISSION_GRANTED) {
|
||||
// when (requestCode) {
|
||||
// REQUEST_CODE_BIND -> {
|
||||
// bindUserService()
|
||||
// }
|
||||
// REQUEST_CODE_UNBIND -> {
|
||||
// unbindUserService()
|
||||
// }
|
||||
// else -> {}
|
||||
// }
|
||||
// } else {
|
||||
// Log.e(TAG, "User denied permission")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private val BINDER_RECEIVED_LISTENER = OnBinderReceivedListener {
|
||||
// if (Shizuku.isPreV11()) {
|
||||
// Log.w(TAG, "Shizuku pre-v11 is not supported")
|
||||
// } else {
|
||||
// Log.d(TAG, "Binder received")
|
||||
// }
|
||||
// }
|
||||
// private val BINDER_DEAD_LISTENER = OnBinderDeadListener { Log.w(TAG, "Binder dead") }
|
||||
// private val REQUEST_PERMISSION_RESULT_LISTENER =
|
||||
// OnRequestPermissionResultListener { requestCode: Int, grantResult: Int ->
|
||||
// onRequestPermissionsResult(
|
||||
// requestCode,
|
||||
// grantResult
|
||||
// )
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.utils;
|
||||
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* CPU相关工具类。
|
||||
*/
|
||||
public class CpuUtils {
|
||||
private static boolean initCpu = true;
|
||||
private static double oCpu = 0.0;
|
||||
private static double oIdle = 0.0;
|
||||
|
||||
private static double pJif = 0.0;
|
||||
private static double pCpu = 0.0;
|
||||
private static double aCpu = 0.0;
|
||||
private static double opCpu = 0.0;
|
||||
private static double oaCpu = 0.0;
|
||||
|
||||
/**
|
||||
* 8.0以上获取cpu的方式
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static double getCpuUsageForO() {
|
||||
java.lang.Process process = null;
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("top -n 1");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
int cpuIndex = -1;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
if (TextUtils.isEmpty(line)) {
|
||||
continue;
|
||||
}
|
||||
int tempIndex = getCPUIndex(line);
|
||||
if (tempIndex != -1) {
|
||||
cpuIndex = tempIndex;
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(String.valueOf(Process.myPid()))) {
|
||||
if (cpuIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
String[] param = line.split("\\s+");
|
||||
if (param.length <= cpuIndex) {
|
||||
continue;
|
||||
}
|
||||
String cpu = param[cpuIndex];
|
||||
if (cpu.endsWith("%")) {
|
||||
cpu = cpu.substring(0, cpu.lastIndexOf("%"));
|
||||
}
|
||||
return Double.parseDouble(cpu) / Runtime.getRuntime().availableProcessors();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (process != null) {
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int getCPUIndex(String line) {
|
||||
if (line.contains("CPU")) {
|
||||
String[] titles = line.split("\\s+");
|
||||
for (int i = 0; i < titles.length; i++) {
|
||||
if (titles[i].contains("CPU")) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用的CPU占用率,单位:%,保留1位小数
|
||||
* @param pid
|
||||
* @return
|
||||
*/
|
||||
public static double getCpuUsagePercentWithPid(int pid) {
|
||||
double usage = 0.0;
|
||||
String[] result1;
|
||||
String[] result2;
|
||||
if (pid >= 0) {
|
||||
result1 = getCpuWithPid(pid);
|
||||
if (null != result1) {
|
||||
pCpu = Double.parseDouble(result1[1])
|
||||
+ Double.parseDouble(result1[2]);
|
||||
}
|
||||
result2 = getSystemCpu();
|
||||
if (null != result2) {
|
||||
aCpu = 0.0;
|
||||
for (int i = 2; i < result2.length; i++) {
|
||||
if (result2[i] != null) {
|
||||
aCpu += Double.parseDouble(result2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((aCpu - oaCpu) != 0) {
|
||||
usage = DoubleUtils.div(((pCpu - opCpu) * 100.00),
|
||||
(aCpu - oaCpu), 1);
|
||||
if (usage < 0) {
|
||||
usage = 0;
|
||||
}
|
||||
else if (usage > 100)
|
||||
{
|
||||
usage = 100;
|
||||
}
|
||||
|
||||
}
|
||||
opCpu = pCpu;
|
||||
oaCpu = aCpu;
|
||||
}
|
||||
pJif = pCpu;
|
||||
return usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CPU使用率
|
||||
*
|
||||
* @return CPU使用率,单位:%
|
||||
*/
|
||||
public static double getSysCpuUsagePercent() {
|
||||
double usage = 0.0;
|
||||
if (initCpu) {
|
||||
initCpu = false;
|
||||
RandomAccessFile reader = null;
|
||||
try {
|
||||
reader = new RandomAccessFile("/proc/stat",
|
||||
"r");
|
||||
String load;
|
||||
load = reader.readLine();
|
||||
String[] toks = load.split(" ");
|
||||
oIdle = Double.parseDouble(toks[5]);
|
||||
oCpu = Double.parseDouble(toks[2])
|
||||
+ Double.parseDouble(toks[3])
|
||||
+ Double.parseDouble(toks[4])
|
||||
+ Double.parseDouble(toks[6])
|
||||
+ Double.parseDouble(toks[8])
|
||||
+ Double.parseDouble(toks[7]);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileUtil.closeRandomAccessFile(reader);
|
||||
}
|
||||
} else {
|
||||
RandomAccessFile reader = null;
|
||||
try {
|
||||
reader = new RandomAccessFile("/proc/stat", "r");
|
||||
String load;
|
||||
load = reader.readLine();
|
||||
String[] toks = load.split(" ");
|
||||
double cIdle = Double.parseDouble(toks[5]);
|
||||
double cCpu = Double.parseDouble(toks[2])
|
||||
+ Double.parseDouble(toks[3])
|
||||
+ Double.parseDouble(toks[4])
|
||||
+ Double.parseDouble(toks[6])
|
||||
+ Double.parseDouble(toks[8])
|
||||
+ Double.parseDouble(toks[7]);
|
||||
if (0 != ((cCpu + cIdle) - (oCpu + oIdle))) {
|
||||
usage = DoubleUtils.div((100.00 * ((cCpu - oCpu))),
|
||||
((cCpu + cIdle) - (oCpu + oIdle)), 1);
|
||||
if (usage < 0) {
|
||||
usage = 0;
|
||||
}
|
||||
else if (usage > 100)
|
||||
{
|
||||
usage = 100;
|
||||
}
|
||||
}
|
||||
oCpu = cCpu;
|
||||
oIdle = cIdle;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
FileUtil.closeRandomAccessFile(reader);
|
||||
}
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
private static String[] getCpuWithPid(int pid) {
|
||||
String cpuPath = "/proc/" + pid + "/stat";
|
||||
String cpu = "";
|
||||
String[] result = new String[3];
|
||||
|
||||
File f = new File(cpuPath);
|
||||
// 部分进程信息无法读取
|
||||
if (!f.exists() || !f.canRead())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
FileReader fr = null;
|
||||
BufferedReader localBufferedReader = null;
|
||||
|
||||
try {
|
||||
fr = new FileReader(f);
|
||||
localBufferedReader = new BufferedReader(fr, 8192);
|
||||
cpu = localBufferedReader.readLine();
|
||||
if (null != cpu) {
|
||||
String[] cpuSplit = cpu.split(" ");
|
||||
result[0] = cpuSplit[1];
|
||||
result[1] = cpuSplit[13];
|
||||
result[2] = cpuSplit[14];
|
||||
}
|
||||
}catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FileUtil.closeReader(localBufferedReader);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String[] getSystemCpu() {
|
||||
String cpuPath = "/proc/stat";
|
||||
String cpu = "";
|
||||
String[] result = new String[7];
|
||||
|
||||
File f = new File(cpuPath);
|
||||
if (!f.exists() || !f.canRead())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
FileReader fr = null;
|
||||
BufferedReader localBufferedReader = null;
|
||||
|
||||
try {
|
||||
fr = new FileReader(f);
|
||||
localBufferedReader = new BufferedReader(fr, 8192);
|
||||
cpu = localBufferedReader.readLine();
|
||||
if (null != cpu) {
|
||||
result = cpu.split(" ");
|
||||
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FileUtil.closeReader(localBufferedReader);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getCpuUsageByCmd() {
|
||||
java.lang.Process process;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
String cmd = "dumpsys cpuinfo";
|
||||
try {
|
||||
process = Runtime.getRuntime().exec(
|
||||
new String[] { "sh", "-c", cmd });
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||
process.getInputStream()));
|
||||
while (((line = br.readLine()) != null)) {
|
||||
// 去掉空白行数据
|
||||
line = line.trim();
|
||||
if (line.equals("")) {
|
||||
continue;
|
||||
}
|
||||
sb.append(line);
|
||||
sb.append("\r\n");
|
||||
}
|
||||
try {
|
||||
process.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进程的CPU使用时间片
|
||||
*
|
||||
* @return 进程的CPU使用时间片
|
||||
*/
|
||||
public long getJif() {
|
||||
return (long)pJif;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.utils
|
||||
|
||||
import java.lang.Exception
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
||||
object DoubleUtils {
|
||||
|
||||
fun mul(d1: Double, d2: Double): Double {
|
||||
val bd1 = BigDecimal(d1.toString())
|
||||
val bd2 = BigDecimal(d2.toString())
|
||||
return try {
|
||||
bd1.multiply(bd2).toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun div(d1: Double, d2: Double, scale: Int): Double {
|
||||
val bd1 = BigDecimal(d1.toString())
|
||||
val bd2 = BigDecimal(d2.toString())
|
||||
return try {
|
||||
// 直接向下取整
|
||||
bd1.divide(bd2, scale, BigDecimal.ROUND_DOWN).toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 四舍五入
|
||||
* scale:保留多少个小数位
|
||||
*/
|
||||
@JvmStatic
|
||||
fun keepDecimal(v: Double, scale: Int = 1): Double {
|
||||
if (scale < 0) {
|
||||
throw IllegalArgumentException("The scale must be a positive integer or zero")
|
||||
}
|
||||
return BigDecimal(v).setScale(scale, BigDecimal.ROUND_HALF_UP).toDouble()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.utils
|
||||
|
||||
import android.net.LocalSocket
|
||||
import android.util.Log
|
||||
import java.io.*
|
||||
import java.lang.Exception
|
||||
import java.net.Socket
|
||||
import java.nio.channels.FileChannel
|
||||
|
||||
object FileUtil {
|
||||
private const val TAG = "FileUtil"
|
||||
const val separator = "/"
|
||||
fun isPathStringValid(path: String?): Boolean {
|
||||
if (null == path || path.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (path.contains(":") || path.contains("*") || path.contains("?")
|
||||
|| path.contains("\"") || path.contains("<")
|
||||
|| path.contains(">") || path.contains("|")
|
||||
) {
|
||||
Log.w(TAG, "filename can not contains:*:?\"<>|")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun isPath(path: String): Boolean {
|
||||
return path.contains(separator) || path.contains("\\")
|
||||
}
|
||||
|
||||
fun getPath(path: String): String {
|
||||
val la = path.lastIndexOf(separator)
|
||||
return path.substring(0, la)
|
||||
}
|
||||
|
||||
fun convertValidFilePath(path: String, defPosfix: String): String {
|
||||
var filePath = path
|
||||
if (path.contains(separator) || path.contains("\\")) {
|
||||
val la = filePath.lastIndexOf(".")
|
||||
if (la < 0) {
|
||||
filePath = path + defPosfix
|
||||
} else {
|
||||
val temp = filePath.substring(la)
|
||||
if (temp.contains(separator) || temp.contains("\\")) {
|
||||
// "."是目录名的一部分而不是后缀名的情况
|
||||
filePath = path + defPosfix
|
||||
}
|
||||
// else fileName = fileName
|
||||
}
|
||||
} else {
|
||||
if (!path.contains(".")) // 没有有后缀
|
||||
{
|
||||
filePath = filePath + defPosfix
|
||||
}
|
||||
}
|
||||
return filePath
|
||||
}
|
||||
|
||||
fun isFileExists(file: String?): Boolean {
|
||||
try {
|
||||
val f = File(file)
|
||||
if (!f.exists()) {
|
||||
return false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun isFileValid(f: File): Boolean {
|
||||
if (!f.exists()) {
|
||||
try {
|
||||
f.createNewFile()
|
||||
} catch (e: IOException) {
|
||||
return false
|
||||
}
|
||||
f.delete()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun isFileValid(parent: File?, name: String?): Boolean {
|
||||
val f = File(parent, name)
|
||||
return isFileValid(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除存在的文件
|
||||
*
|
||||
* @param filePath
|
||||
*/
|
||||
fun delExistFile(filePath: String?) {
|
||||
val f = File(filePath)
|
||||
if (f.exists()) f.delete()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭bufferReader
|
||||
*
|
||||
* @param br
|
||||
*/
|
||||
@JvmStatic
|
||||
fun closeReader(br: Reader?) {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭Writer
|
||||
*
|
||||
* @param wr
|
||||
*/
|
||||
fun closeWriter(wr: Writer?) {
|
||||
if (wr != null) {
|
||||
try {
|
||||
wr.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* flush Writer
|
||||
*
|
||||
* @param wr
|
||||
*/
|
||||
fun flushWriter(wr: Writer?) {
|
||||
if (wr != null) {
|
||||
try {
|
||||
wr.flush()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入流的关闭
|
||||
*
|
||||
* @param in
|
||||
*/
|
||||
fun closeInputStream(`in`: InputStream?) {
|
||||
if (`in` != null) {
|
||||
try {
|
||||
`in`.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出流的关闭
|
||||
*
|
||||
* @param out
|
||||
*/
|
||||
fun closeOutputStream(out: OutputStream?) {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件管道的关闭
|
||||
*
|
||||
* @param chl
|
||||
*/
|
||||
fun closeFileChannel(chl: FileChannel?) {
|
||||
if (chl != null) {
|
||||
try {
|
||||
chl.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RandomAccessFile的关闭
|
||||
*
|
||||
* @param f RandomAccessFile对象
|
||||
*/
|
||||
@JvmStatic
|
||||
fun closeRandomAccessFile(f: RandomAccessFile?) {
|
||||
if (f != null) {
|
||||
try {
|
||||
f.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket的关闭
|
||||
*
|
||||
* @param s Socket对象
|
||||
*/
|
||||
fun colseSocket(s: Socket?) {
|
||||
if (s != null) {
|
||||
try {
|
||||
s.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalSocket的关闭
|
||||
*
|
||||
* @param s Socket对象
|
||||
*/
|
||||
fun colseLocalSocket(s: LocalSocket?) {
|
||||
if (s != null) {
|
||||
try {
|
||||
s.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteFile(file: File) {
|
||||
if (file.exists()) { // 判断文件是否存在
|
||||
if (file.isFile) { // 判断是否是文件
|
||||
file.delete() // delete()方法 你应该知道 是删除的意思;
|
||||
} else if (file.isDirectory) { // 否则如果它是一个目录
|
||||
val files = file.listFiles() // 声明目录下所有的文件 files[];
|
||||
for (i in files.indices) { // 遍历目录下所有的文件
|
||||
deleteFile(files[i]) // 把每个文件 用这个方法进行迭代
|
||||
}
|
||||
}
|
||||
file.delete()
|
||||
} else {
|
||||
Log.e(TAG, "文件不存在!" + "n")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝文件
|
||||
*
|
||||
* @param s 源文件
|
||||
* @param t 目标文件
|
||||
*/
|
||||
fun copyFile(s: File?, t: File) {
|
||||
var fi: FileInputStream? = null
|
||||
var fo: FileOutputStream? = null
|
||||
var `in`: FileChannel? = null
|
||||
var out: FileChannel? = null
|
||||
try {
|
||||
if (!t.exists()) {
|
||||
t.createNewFile()
|
||||
}
|
||||
fi = FileInputStream(s)
|
||||
fo = FileOutputStream(t)
|
||||
`in` = fi.channel
|
||||
out = fo.channel
|
||||
// 连接两个通道,并且从in通道读取,然后写入out通道
|
||||
`in`.transferTo(0, `in`.size(), out)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
closeOutputStream(fo)
|
||||
closeInputStream(fi)
|
||||
closeFileChannel(`in`)
|
||||
closeFileChannel(out)
|
||||
}
|
||||
}
|
||||
|
||||
fun copyInputToFile(`in`: InputStream?, path: String?) {
|
||||
var bis: BufferedInputStream? = null
|
||||
var fos: FileOutputStream? = null
|
||||
try {
|
||||
val buffer = ByteArray(10 * 1024)
|
||||
bis = BufferedInputStream(`in`)
|
||||
fos = FileOutputStream(path)
|
||||
var a = bis.read(buffer, 0, buffer.size)
|
||||
while (a != -1) {
|
||||
fos.write(buffer, 0, a)
|
||||
fos.flush()
|
||||
a = bis.read(buffer, 0, buffer.size)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
closeOutputStream(fos)
|
||||
closeInputStream(bis)
|
||||
closeInputStream(`in`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.utils;
|
||||
|
||||
import android.os.Debug;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class HookUtils {
|
||||
private static final String TAG = "HookUtils";
|
||||
|
||||
/**
|
||||
* 单位为MB
|
||||
* 0: 总PSS,1: dalvik总Pss, 2: native总Pss, 3: other总Pss
|
||||
* @param memoryInfo
|
||||
* @return
|
||||
*/
|
||||
public static double[] getPssArray(Debug.MemoryInfo memoryInfo) {
|
||||
double[] pssArray = new double[4];
|
||||
if (memoryInfo != null) {
|
||||
double totalPss = DoubleUtils.keepDecimal(memoryInfo.getTotalPss() / 1024.0, 3);
|
||||
// Log.d(TAG, "===========Hook PSS 开始:===========\n");
|
||||
// Log.d(TAG, "总PSS内存为:" + totalPss);
|
||||
pssArray[0] = totalPss;
|
||||
try {
|
||||
Field dalvikField = memoryInfo.getClass().getField("dalvikSwappedOutPss");
|
||||
double dalvikPss = DoubleUtils.keepDecimal(memoryInfo.dalvikPss / 1024.0, 3);
|
||||
double dalvikSwappedOutPss = DoubleUtils.keepDecimal((int) dalvikField.get(memoryInfo) / 1024.0, 3);
|
||||
pssArray[1] = dalvikPss + dalvikSwappedOutPss;
|
||||
// Log.d(TAG, "dalvikPss is:" + dalvikSwappedOutPss);
|
||||
// Log.d(TAG, "dalvikSwappedOutPss is:" + dalvikPss + "\n\n");
|
||||
|
||||
Field nativeField = memoryInfo.getClass().getField("nativeSwappedOutPss");
|
||||
double nativePss = DoubleUtils.keepDecimal(memoryInfo.nativePss / 1024.0, 3);
|
||||
double nativeSwappedOutPss = DoubleUtils.keepDecimal((int) nativeField.get(memoryInfo) / 1024.0, 3);
|
||||
pssArray[2] = nativePss + nativeSwappedOutPss;
|
||||
// Log.d(TAG, "nativePss is:" + nativePss);
|
||||
// Log.d(TAG, "nativeSwappedOutPss is:" + nativeSwappedOutPss + "\n\n");
|
||||
|
||||
Field otherField = memoryInfo.getClass().getField("otherSwappedOutPss");
|
||||
double otherPss = DoubleUtils.keepDecimal(memoryInfo.otherPss / 1024.0, 3);
|
||||
double otherSwappedOutPss = DoubleUtils.keepDecimal((int) otherField.get(memoryInfo) / 1024.0, 3);
|
||||
pssArray[3] = otherPss + otherSwappedOutPss;
|
||||
// Log.d(TAG, "otherPss is:" + otherPss);
|
||||
// Log.d(TAG, "otherSwappedOutPss is:" + otherSwappedOutPss + "\n\n");
|
||||
//
|
||||
// Log.d(TAG, "===========Hook PSS 结束!===========\n");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
return pssArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package com.zhjt.mogo_core_function_devatools.monitor.utils;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.Debug;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 内存信息工具类。
|
||||
*/
|
||||
public class MemUtils {
|
||||
|
||||
public static double[] getPssArray(Context context, int[] pids) {
|
||||
Debug.MemoryInfo[] memoryArray = getMemoryInfo(context, pids);
|
||||
if (memoryArray.length > 0) {
|
||||
return HookUtils.getPssArray(memoryArray[0]);
|
||||
} else {
|
||||
return new double[4];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单位MB
|
||||
*/
|
||||
public static double getPssMemValue(Context context, int[] pids) {
|
||||
double value = 0.0;
|
||||
Debug.MemoryInfo[] memoryArray = getMemoryInfo(context, pids);
|
||||
if (memoryArray.length > 0) {
|
||||
value = DoubleUtils.keepDecimal(memoryArray[0].getTotalPss() / 1024.0, 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能获取本应用的PSS内存占系统百分比:单位%,保留1位小数
|
||||
* @return
|
||||
*/
|
||||
public static double getPidMemPercent() {
|
||||
double percent = 0.0;
|
||||
Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
|
||||
Debug.getMemoryInfo(memInfo);
|
||||
int pidTotalPss = memInfo.getTotalPss();
|
||||
long systemTotalMem = getTotalMem();
|
||||
percent = DoubleUtils.keepDecimal(pidTotalPss * 100.0 / systemTotalMem, 1);
|
||||
return percent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本应用进程总pss内存,单位MB
|
||||
*/
|
||||
public static double getPssMem() {
|
||||
Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
|
||||
Debug.getMemoryInfo(memInfo);
|
||||
return DoubleUtils.keepDecimal(memInfo.getTotalPss() / 1024.0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统空闲内存占用百分比: 单位%
|
||||
* @return
|
||||
*/
|
||||
public static double getSystemMemPercent() {
|
||||
double percent = 0.0;
|
||||
long[] memInfo = getMemInfo();
|
||||
long free = memInfo[1] + memInfo[2] + memInfo[3];
|
||||
long total = memInfo[0];
|
||||
percent = DoubleUtils.keepDecimal(free * 100.0 / total, 1);
|
||||
return percent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取空闲内存
|
||||
*
|
||||
* @return 空闲内存,单位KB
|
||||
*/
|
||||
public static long getFreeMem() {
|
||||
long[] memInfo = getMemInfo();
|
||||
return memInfo[1] + memInfo[2] + memInfo[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总内存
|
||||
*
|
||||
* @return 总内存,单位KB
|
||||
*/
|
||||
public static long getTotalMem() {
|
||||
long[] memInfo = getMemInfo();
|
||||
return memInfo[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内存信息:total、free、buffers、cached,单位KB
|
||||
*
|
||||
* @return 内存信息
|
||||
*/
|
||||
public static long[] getMemInfo() {
|
||||
long memInfo[] = new long[4];
|
||||
try {
|
||||
Class<?> procClazz = Class.forName("android.os.Process");
|
||||
Class<?> paramTypes[] = new Class[] { String.class, String[].class,
|
||||
long[].class };
|
||||
Method readProclines = procClazz.getMethod("readProcLines",
|
||||
paramTypes);
|
||||
Object args[] = new Object[3];
|
||||
final String[] memInfoFields = new String[] { "MemTotal:",
|
||||
"MemFree:", "Buffers:", "Cached:" };
|
||||
long[] memInfoSizes = new long[memInfoFields.length];
|
||||
memInfoSizes[0] = 30;
|
||||
memInfoSizes[1] = -30;
|
||||
args[0] = "/proc/meminfo";
|
||||
args[1] = memInfoFields;
|
||||
args[2] = memInfoSizes;
|
||||
if (null != readProclines) {
|
||||
readProclines.invoke(null, args);
|
||||
for (int i = 0; i < memInfoSizes.length; i++) {
|
||||
memInfo[i] = memInfoSizes[i];
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return memInfo;
|
||||
}
|
||||
|
||||
public static long[] getHeapNative() {
|
||||
int Native_HeapSize = 0;
|
||||
int Native_HeapAlloc = 1;
|
||||
long[] value = new long[2];
|
||||
value[Native_HeapSize] = Debug.getNativeHeapSize() >> 10;
|
||||
value[Native_HeapAlloc] = Debug.getNativeHeapAllocatedSize() >> 10;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static long[] getHeapDalvik() {
|
||||
int Total_HeapSize = 0;
|
||||
int Total_HeapAlloc = 1;
|
||||
|
||||
long[] value_total = new long[2];
|
||||
value_total[Total_HeapSize] = Runtime.getRuntime().totalMemory() >> 10;
|
||||
value_total[Total_HeapAlloc] = (Runtime.getRuntime().totalMemory() - Runtime
|
||||
.getRuntime().freeMemory()) >> 10;
|
||||
|
||||
long[] value_native = getHeapNative();
|
||||
|
||||
int Dalvik_HeapSize = 0;
|
||||
int Dalvik_HeapAlloc = 1;
|
||||
long[] value_dalvik = new long[2];
|
||||
value_dalvik[Dalvik_HeapSize] = value_total[Total_HeapSize]
|
||||
- value_native[0];
|
||||
value_dalvik[Dalvik_HeapAlloc] = value_total[Total_HeapAlloc]
|
||||
- value_native[1];
|
||||
|
||||
return value_dalvik;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取堆内存数据,精确到KB Get VM Heap Size by calling:
|
||||
* Runtime.getRuntime().totalMemory(); Get Allocated VM Memory by calling:
|
||||
* Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||
* Get VM Heap Size Limit by calling: Runtime.getRuntime().maxMemory() Get
|
||||
* Native Allocated Memory by calling: Debug.getNativeHeapAllocatedSize();
|
||||
*/
|
||||
public static long[] getVM() {
|
||||
long[] value = new long[5];
|
||||
value[0] = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime()
|
||||
.freeMemory()) >> 10;
|
||||
value[1] = Runtime.getRuntime().totalMemory() >> 10;
|
||||
|
||||
value[2] = Debug.getNativeHeapAllocatedSize() >> 10;
|
||||
value[3] = Debug.getNativeHeapSize() >> 10;
|
||||
value[4] = Debug.getGlobalAllocSize() >> 10;
|
||||
return value;
|
||||
}
|
||||
|
||||
private static Debug.MemoryInfo[] getMemoryInfo(Context context, int[] pids) {
|
||||
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
return am.getProcessMemoryInfo(pids);
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,25 @@ class CanStatus(var enabled: Boolean = false): Status() {
|
||||
*/
|
||||
class TracingStatus(var state: Tracing = UNKNOWN): Status() {
|
||||
|
||||
enum class Tracing(val code: String? = "") {
|
||||
enum class Tracing(val code: String? = "", var extra: Map<String, String>? = null) {
|
||||
|
||||
/**
|
||||
* 类型切换
|
||||
*/
|
||||
MAP_TRA_TYPE("IMAP_TRA_TYPE"),
|
||||
|
||||
|
||||
/**
|
||||
* 地图数据存在
|
||||
*/
|
||||
MAP_DATA_EXIST("IMAP_DATA_EXIST"),
|
||||
|
||||
|
||||
/**
|
||||
* 地图数据不存在
|
||||
*/
|
||||
MAP_DATA_NOT_EXIST("EMAP_DATA_NOT_EXIST"),
|
||||
|
||||
/**
|
||||
* 寻迹-已找到轨迹文件
|
||||
*/
|
||||
@@ -182,12 +200,10 @@ class TracingStatus(var state: Tracing = UNKNOWN): Status() {
|
||||
UNKNOWN;
|
||||
|
||||
fun isException(): Boolean {
|
||||
val c1 = when (this) {
|
||||
TRACK_FINDED, TRACK_NOT_EXIST, TRACK_LOAD_FAIL, ROUTE_FAILED, UNKNOWN -> true
|
||||
else -> false
|
||||
if (this == TRACK_LOADED || this == ROUTE_LOADED) {
|
||||
return false
|
||||
}
|
||||
val c2 = CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo().state != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE
|
||||
return c1 and c2
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,14 +228,46 @@ class TracingStatus(var state: Tracing = UNKNOWN): Status() {
|
||||
override fun isException(): Boolean = state.isException()
|
||||
}
|
||||
|
||||
fun String.toState(): Tracing? {
|
||||
fun String.toState(msg: String?): Tracing? {
|
||||
val ss = msg?.split("|")
|
||||
var extra: Map<String, String>? = null
|
||||
if (ss != null && ss.isNotEmpty()) {
|
||||
val sb = StringBuilder()
|
||||
for (element in ss) {
|
||||
sb.append(element)
|
||||
sb.append(",")
|
||||
}
|
||||
if (sb.isNotEmpty()) {
|
||||
sb.setLength(sb.length - 1)
|
||||
}
|
||||
extra = mutableMapOf("extra" to sb.toString())
|
||||
}
|
||||
return when(this) {
|
||||
"IMAP_TRA_EXIST" -> TRACK_FINDED
|
||||
"IMAP_TRA_LOADED" -> TRACK_LOADED
|
||||
"EMAP_TRA_NOT_EXIST" -> TRACK_NOT_EXIST
|
||||
"EMAP_TRA_LOAD_FAILED" -> TRACK_LOAD_FAIL
|
||||
"IMAP_TRA_ROUTING" -> ROUTE_LOADED
|
||||
"IMAP_TRA_EXIST" -> TRACK_FINDED.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"IMAP_TRA_LOADED" -> TRACK_LOADED.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"EMAP_TRA_NOT_EXIST" -> TRACK_NOT_EXIST.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"EMAP_TRA_LOAD_FAILED" -> TRACK_LOAD_FAIL.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"IMAP_TRA_ROUTING" -> ROUTE_LOADED.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"EMAP_HADMAP_ENGINE_NO_ROUTING_INFO" -> ROUTE_FAILED
|
||||
"IMAP_TRA_TYPE" -> MAP_TRA_TYPE.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"MAP_DATA_EXIST" -> MAP_DATA_EXIST.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
"MAP_DATA_NOT_EXIST" -> MAP_DATA_NOT_EXIST.apply {
|
||||
this.extra = extra
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ internal class CanImpl(ctx: Context): IFlow<CanStatus>(ctx), IMoGoAutopilotVehic
|
||||
|
||||
private fun timeOutCheck() {
|
||||
job?.safeCancel()
|
||||
launch(Dispatchers.Default) {
|
||||
launch(Dispatchers.Unconfined) {
|
||||
delay(4000)
|
||||
send(CanStatus(isCanEnabled()))
|
||||
}.also { job = it }
|
||||
|
||||
@@ -35,21 +35,29 @@ internal class GpsImpl(ctx: Context): IFlow<GpsStatus>(ctx) {
|
||||
}
|
||||
|
||||
private val onClose = {
|
||||
send(false, PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION))
|
||||
send(false, isGrandFineLocation())
|
||||
}
|
||||
|
||||
private val onOpen = {
|
||||
send(true, PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION))
|
||||
send(true, isGrandFineLocation())
|
||||
}
|
||||
|
||||
private fun isGrandFineLocation(): Boolean = try {
|
||||
PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
} catch (t: Throwable) {
|
||||
t.printStackTrace()
|
||||
false
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
val isGranted = PermissionUtils.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
val isGranted = isGrandFineLocation()
|
||||
send(isLocationEnabled(), isGranted)
|
||||
if (!isGranted) {
|
||||
PermissionUtils.requestAccessFineLocation(object : SimpleCallback {
|
||||
override fun onGranted() {
|
||||
Log.d(TAG,"权限: ${Manifest.permission.ACCESS_FINE_LOCATION} 被授予了....")
|
||||
send(enabled = isLocationEnabled(), isGranted = false)
|
||||
send(enabled = isLocationEnabled(), isGranted = true)
|
||||
}
|
||||
|
||||
override fun onDenied() {
|
||||
|
||||
@@ -78,12 +78,21 @@ internal class NetsImpl(ctx: Context): IFlow<NetStatus>(ctx) {
|
||||
private var loopCheckAndSendJob: Job? = null
|
||||
|
||||
private fun checkAndSend() {
|
||||
val connectionInfo = wifiMgr.connectionInfo
|
||||
val enabled = isNetConnected()
|
||||
val name = if (isLocationEnabled()) connectionInfo.ssid?.replace(Regex("[\\W]"), "") else "WI-FI"
|
||||
loopCheckAndSendJob?.safeCancel()
|
||||
launch(Dispatchers.Default) { delay(1000); checkAndSend() }.also { loopCheckAndSendJob = it }
|
||||
send(enabled, name)
|
||||
launch(Dispatchers.Unconfined) {
|
||||
val connectionInfo = wifiMgr.connectionInfo
|
||||
val enabled = isNetConnected()
|
||||
val name =
|
||||
try {
|
||||
if (isLocationEnabled()) connectionInfo.ssid?.replace(Regex("[\\W]"), "") else "WI-FI"
|
||||
} catch (t: Throwable) {
|
||||
t.printStackTrace()
|
||||
"WI-FI"
|
||||
}
|
||||
send(enabled, name)
|
||||
delay(1000);
|
||||
checkAndSend()
|
||||
}.also { loopCheckAndSendJob = it }
|
||||
}
|
||||
|
||||
private fun isLocationEnabled() =
|
||||
|
||||
@@ -44,7 +44,7 @@ internal class RTKImpl(ctx: Context): IFlow<RTKStatus>(ctx), IMoGoAutopilotStatu
|
||||
return
|
||||
}
|
||||
check?.takeIf { it.isActive }?.cancel()
|
||||
launch {
|
||||
launch(Dispatchers.Unconfined) {
|
||||
CallerAutoPilotManager.sendStatusQueryReq()
|
||||
delay(5000)
|
||||
isOldVersion.set(true)
|
||||
@@ -82,7 +82,7 @@ internal class RTKImpl(ctx: Context): IFlow<RTKStatus>(ctx), IMoGoAutopilotStatu
|
||||
if (isRTKEnabled()) {
|
||||
send(RTKStatus("RTK", 0))
|
||||
timeOutCheck?.takeIf { it.isActive }?.cancel()
|
||||
launch {
|
||||
launch(Dispatchers.Unconfined) {
|
||||
delay(4000)
|
||||
send(RTKStatus("", -1))
|
||||
}.also {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.zhjt.mogo_core_function_devatools.status.flow.trace
|
||||
|
||||
import android.content.*
|
||||
import android.util.*
|
||||
import com.mogo.eagle.core.data.autopilot.*
|
||||
import com.mogo.eagle.core.function.api.autopilot.*
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener.Companion.STATUS_AUTOPILOT_RUNNING
|
||||
import com.mogo.eagle.core.function.call.autopilot.*
|
||||
import com.zhjt.mogo_core_function_devatools.status.entity.*
|
||||
import com.zhjt.mogo_core_function_devatools.status.entity.TracingStatus.Tracing.*
|
||||
@@ -20,7 +20,8 @@ internal class TracingImpl(ctx: Context): IFlow<TracingStatus>(ctx), IMoGoAutopi
|
||||
|
||||
override fun onCreate() {
|
||||
val code = CallerAutoPilotStatusListenerManager.getAutoPilotReportMessageCode()
|
||||
val state = code.toState() ?: UNKNOWN
|
||||
val msg = CallerAutoPilotStatusListenerManager.getAutoPilotReportMessageContent()
|
||||
val state = code.toState(msg) ?: UNKNOWN
|
||||
old = state
|
||||
send(TracingStatus(state))
|
||||
CallerAutoPilotStatusListenerManager.addListener(TAG, this)
|
||||
@@ -30,7 +31,7 @@ internal class TracingImpl(ctx: Context): IFlow<TracingStatus>(ctx), IMoGoAutopi
|
||||
override fun onAutopilotGuardian(guardianInfo: MogoReportMessage?) {
|
||||
super.onAutopilotGuardian(guardianInfo)
|
||||
val current = guardianInfo?.code
|
||||
val newState = current?.toState()
|
||||
val newState = current?.toState(guardianInfo.msg)
|
||||
if (newState != null && newState != old) {
|
||||
send(TracingStatus(newState))
|
||||
old = newState
|
||||
@@ -40,17 +41,20 @@ internal class TracingImpl(ctx: Context): IFlow<TracingStatus>(ctx), IMoGoAutopi
|
||||
override fun onAutopilotIpcConnectStatusChanged(status: Int, reason: String?) {
|
||||
super.onAutopilotIpcConnectStatusChanged(status, reason)
|
||||
if (!CallerAutoPilotManager.isConnected()) {
|
||||
old = UNKNOWN
|
||||
send(TracingStatus(UNKNOWN))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) {
|
||||
super.onAutopilotStatusResponse(autoPilotStatusInfo)
|
||||
if (autoPilotStatusInfo.state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) {
|
||||
if (autoPilotStatusInfo.state != STATUS_AUTOPILOT_RUNNING) {
|
||||
old = UNKNOWN
|
||||
send(TracingStatus(UNKNOWN))
|
||||
return
|
||||
}
|
||||
if (old.isException() && autoPilotStatusInfo.state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
if (old.isException()) {
|
||||
old = TRACK_LOADED
|
||||
send(TracingStatus(TRACK_LOADED))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.widget.*
|
||||
import androidx.core.content.*
|
||||
import androidx.recyclerview.widget.*
|
||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.*
|
||||
import com.mogo.eagle.core.utilcode.util.*
|
||||
import com.zhjt.mogo_core_function_devatools.*
|
||||
import com.zhjt.mogo_core_function_devatools.R
|
||||
@@ -19,6 +20,10 @@ import kotlinx.coroutines.*
|
||||
|
||||
internal class StatusAdapter(val ctx: Context, var data: ArrayList<Status>): RecyclerView.Adapter<StatusViewHolder>() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "StatusAdapter"
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatusViewHolder =
|
||||
StatusViewHolder(LayoutInflater.from(ctx).inflate(R.layout.layout_status_bar_item, parent, false))
|
||||
|
||||
@@ -69,7 +74,7 @@ internal class StatusAdapter(val ctx: Context, var data: ArrayList<Status>): Rec
|
||||
}
|
||||
is TracingStatus -> {
|
||||
when(status.state) {
|
||||
ROUTE_FAILED, TRACK_LOAD_FAIL, TRACK_NOT_EXIST, TRACK_FINDED, UNKNOWN -> {
|
||||
MAP_DATA_NOT_EXIST, MAP_DATA_EXIST, MAP_TRA_TYPE, ROUTE_FAILED, TRACK_LOAD_FAIL, TRACK_NOT_EXIST, TRACK_FINDED, UNKNOWN -> {
|
||||
iv.background = ContextCompat.getDrawable(itemView.context, drawable.icon_dev_status_trace_unkown)
|
||||
}
|
||||
TRACK_LOADED -> {
|
||||
@@ -116,7 +121,26 @@ internal class StatusAdapter(val ctx: Context, var data: ArrayList<Status>): Rec
|
||||
else ->
|
||||
"定位异常"
|
||||
}
|
||||
is TracingStatus -> "轨迹类型:${ if (status.state == TRACK_LOADED) "循迹" else if (status.state == ROUTE_LOADED) "自主算路" else "暂无轨迹" }"
|
||||
is TracingStatus -> {
|
||||
val extra = status.state.extra
|
||||
val extraDesc = if (extra != null && extra.isNotEmpty()) extra.values.joinToString(",") else ""
|
||||
Logger.d(TAG, "traceing_state: $status -> extra: $extraDesc :: extra: $extra")
|
||||
when(status.state) {
|
||||
//"轨迹类型:${ if (status.state == TRACK_LOADED) "循迹" else if (status.state == ROUTE_LOADED) "自主算路" else "暂无轨迹" }"
|
||||
MAP_TRA_TYPE -> {
|
||||
"暂无轨迹"
|
||||
}
|
||||
MAP_DATA_EXIST -> "地图数据存在,正在加载${if (extraDesc.isEmpty()) "" else "[$extraDesc]" }"
|
||||
MAP_DATA_NOT_EXIST -> "地图数据不存在${if (extraDesc.isEmpty()) "" else "[$extraDesc]"}"
|
||||
TRACK_FINDED -> "轨迹类型:循迹[已找到轨迹$extraDesc]"
|
||||
TRACK_LOADED -> "轨迹类型:循迹[加载成功$extraDesc]"
|
||||
TRACK_NOT_EXIST -> "轨迹类型:循迹[不存在$extraDesc]"
|
||||
TRACK_LOAD_FAIL -> "轨迹类型:循迹[加载失败$extraDesc]"
|
||||
ROUTE_LOADED -> "轨迹类型:自主算路[加载成功$extraDesc]"
|
||||
ROUTE_FAILED -> "轨迹类型:自主算路[加载失败$extraDesc]"
|
||||
UNKNOWN -> "暂无轨迹"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,12 @@ class TraceManager : IMoGoCloudListener {
|
||||
FwBuild(false, 30, pkgName + ChainConstant.CHAIN_LINK_LOG_ADAS_TRAFFIC_LIGHT)
|
||||
fwBuildMap[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_OBJECTS] =
|
||||
FwBuild(false, 30, pkgName + ChainConstant.CHAIN_LINK_LOG_ADAS_PLANNING_OBJECTS)
|
||||
fwBuildMap[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_ACTIONS] =
|
||||
FwBuild(true, -1, pkgName + ChainConstant.CHAIN_LINK_LOG_ADAS_PLANNING_ACTIONS)
|
||||
fwBuildMap[ChainConstant.CHAIN_LINK_LOG_NATIVE_LEAK] =
|
||||
FwBuild(true, -1, pkgName + ChainConstant.CHAIN_LINK_LOG_RECORD_NATIVE_LEAK)
|
||||
|
||||
|
||||
|
||||
traceInfoCache[ChainConstant.CHAIN_LINK_LOG_CONNECT_STATUS] =
|
||||
ChainLogParam(true, "ADAS连接状态")
|
||||
@@ -70,8 +76,14 @@ class TraceManager : IMoGoCloudListener {
|
||||
ChainLogParam(false, "ADAS车前引导线")
|
||||
traceInfoCache[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_VEHICLE] =
|
||||
ChainLogParam(false, "ADAS车辆底盘数据")
|
||||
traceInfoCache[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_TRAFFIC_LIGHT] =
|
||||
ChainLogParam(false, "ADAS红绿灯数据")
|
||||
traceInfoCache[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_OBJECTS] =
|
||||
ChainLogParam(false, "ADAS PLANNING 感知障碍物")
|
||||
traceInfoCache[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_PLANNING_ACTIONS] =
|
||||
ChainLogParam(true, "ADAS PLANNING 决策行为")
|
||||
traceInfoCache[ChainConstant.CHAIN_LINK_LOG_NATIVE_LEAK] =
|
||||
ChainLogParam(true, "Native Leak Record")
|
||||
|
||||
FileWriteManager.getInstance()
|
||||
.init(context, MoGoAiCloudClientConfig.getInstance().sn, pkgName, fwBuildMap)
|
||||
|
||||
Reference in New Issue
Block a user