Merge branch 'dev_arch_opt_3.0' into dev_robosweeper-d_app-module_221230_1.1.0

This commit is contained in:
donghongyu
2023-02-13 18:47:04 +08:00
203 changed files with 4538 additions and 2341 deletions

View File

@@ -55,4 +55,11 @@ object CallerDevaToolsListenerManager : CallerBase<IMoGoDevaToolsListener>() {
}
}
fun invokeMoFangStatus(status:Boolean){
M_LISTENERS.forEach {
val listener = it.value
listener.mofangStatus(status)
}
}
}

View File

@@ -147,6 +147,13 @@ object CallerDevaToolsManager {
devaToolsProviderApi?.downLoadPackage(downloadKey, downloadUrl)
}
/**
* 更新下载进度
*/
fun updateUpgradeProgress() {
devaToolsProviderApi?.updateUpgradeProgress()
}
/**
* 展示状态栏
*/

View File

@@ -212,11 +212,4 @@ object CallerHmiManager {
hmiProviderApi?.updateStatusBarDownloadView(insert, tag, progress)
}
/**
* 更新魔方的链接状态
*/
fun updateMfStatusView(tag: String, status: Boolean) {
hmiProviderApi?.updateMfStatus(tag, status)
}
}

View File

@@ -45,8 +45,4 @@ object CallerHmiViewControlListenerManager : CallerBase<IViewControlListener>()
M_LISTENERS[tag]?.updateStatusBarDownloadView(insert, tag, progress)
}
fun updateMfStatus(tag: String, viewTag: String, status: Boolean) {
M_LISTENERS[tag]?.updateMfStatus(viewTag, status)
}
}

View File

@@ -0,0 +1,19 @@
package com.mogo.eagle.core.function.call.map
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_IDENTIFY
import com.mogo.eagle.core.function.api.map.marker.IMoGoIdentifyListener
import com.mogo.eagle.core.function.call.base.CallerBase
import mogo.telematics.pad.MessagePad
object CallerMapIdentifyManager : CallerBase<IMoGoIdentifyListener>() {
private val identifyApi: IMoGoIdentifyListener
get() = ARouter.getInstance().build(PATH_IDENTIFY)
.navigation() as IMoGoIdentifyListener
fun getIdentifyObj(uuid: String): MessagePad.TrackedObject? {
return identifyApi.getIdentifyObj(uuid)
}
}

View File

@@ -30,8 +30,8 @@ object CallerMapUIServiceManager {
return serviceProvider?.markerService
}
fun getOverlayManager(context: Context): IMogoOverlayManager?{
return serviceProvider?.getOverlayManager(context)
fun getOverlayManager(): IMogoOverlayManager?{
return serviceProvider?.overlayManager
}
fun getGDLocationServer(context: Context):IMogoGDLocationClient?{

View File

@@ -1,388 +1,24 @@
package com.mogo.eagle.core.function.call.map
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.util.*
import androidx.lifecycle.Lifecycle.Event
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.map.*
import com.mogo.eagle.core.data.map.MapRoadInfo.StopLine
import com.mogo.eagle.core.function.call.autopilot.*
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager.OnRoadListener
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.*
import com.mogo.eagle.core.utilcode.kotlin.lifeCycleOwner
import com.mogo.eagle.core.utilcode.kotlin.safeCancel
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
import com.mogo.map.uicontroller.VisualAngleMode
import com.zhidaoauto.map.sdk.open.tools.MapTools
import kotlinx.coroutines.*
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.internal.synchronized
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeUnit.SECONDS
import java.util.concurrent.atomic.*
import kotlin.math.*
import com.alibaba.android.arouter.launcher.*
import com.mogo.eagle.core.data.constants.*
import com.mogo.eagle.core.function.api.map.angle.*
/**
* 高精地图视角管理类
*/
object CallerVisualAngleManager {
private const val TAG = "VisualAngle"
@Volatile
private var hasCrossRoad = false
private var scope: CoroutineScope = acquireScope()
@Synchronized
get() {
if (field.isActive) {
return field
}
val scope = acquireScope()
field = scope
return field
}
private var defaultDelayJob: Job? = null
private fun acquireScope(): CoroutineScope {
return CoroutineScope(Handler(Looper.getMainLooper()).asCoroutineDispatcher("change-visual-angle") + SupervisorJob())
private val provider by lazy { ARouter.getInstance().build(MogoServicePaths.PATH_VISUAL_ANGLE)
.navigation() as? IMoGoVisualAngleChangeProvider
}
private interface IAttach {
val angle: VisualAngleMode
val priority: Int
val displayThreshold: Long //最大展示时长 > 0; 表示最长展示多长时间, -1 表示,一直展示,直到触发默认视角, 0: 默认视角专用值,
fun changeAngle(scene: Scene) {
provider?.changeAngle(scene)
}
private val triggerLocation = AtomicReference<MogoLocation>()
private val distanceOfCarToStopLine = AtomicReference(0.0)
private val travelled by lazy { AtomicReference(0.0) }
private val listener = object : OnRoadListener {
private val roadId = AtomicReference<String>()
private val triggerRoadId = AtomicReference<String>()
override fun onRoadIdInfo(roadId: String) {
this.roadId.set(roadId)
Log.d(TAG, "-- onRoadIdInfo --: prev: ${this.triggerRoadId.get()} -> curr: $roadId")
val loc = CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02()
var triggerClose = false
val distance = distanceOfCarToStopLine.get() + 5
if (hasCrossRoad && distance > 0) {
val prev = triggerLocation.get()
if (prev != null && loc != null) {
travelled.set(MapTools.distance(loc.longitude, loc.latitude, prev.longitude, prev.latitude) + travelled.get())
triggerLocation.set(loc)
}
val oldRoadId = triggerRoadId.get()
Log.d(TAG, "-- onRoadIdInfo --: travelled --: ${travelled.get()}")
if ((travelled.get() > distance) && oldRoadId != null && oldRoadId != roadId) {
distanceOfCarToStopLine.set(0.0)
hasCrossRoad = false
triggerRoadId.set(null)
travelled.set(0.0)
triggerLocation.set(null)
Log.d(TAG, "-- onRoadIdInfo --: trigger close --")
triggerClose = true
}
}
if (triggerClose) {
changeVisualAngle(CrossRoad(false))
}
}
override fun onStopLineInfo(info: StopLine) {
Log.d(TAG, "-- onStopLineInfo --: ${info.distanceOfCarToStopLine}")
if (!hasCrossRoad && info.distanceOfCarToStopLine <= 30.0) {
hasCrossRoad = true
triggerRoadId.set(this.roadId.get())
distanceOfCarToStopLine.set(info.distanceOfCarToStopLine)
triggerLocation.set(CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02())
changeVisualAngle(CrossRoad(true))
}
}
fun updateLongSightLevel(level: Boolean) {
provider?.updateLongSightLevel(level)
}
fun init(ctx: Context) {
if (Thread.currentThread() != Looper.getMainLooper().thread) {
scope.launch {
initListen(ctx)
}
} else {
initListen(ctx)
}
}
private fun initListen(ctx: Context) {
ctx.lifeCycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Event) {
if (event == ON_DESTROY) {
CallerMapRoadListenerManager.unRegisterRoadListener("VisualAngleChange")
}
}
})
CallerMapRoadListenerManager.registerRoadListener("VisualAngleChange", listener)
}
sealed class Scene private constructor(): IAttach {
/**
* 默认视图
* @param delay: 表示多少稍后默认值为2
* @param unit: 时间单位,默认为秒
*/
class Default(val delay: Long = 2, val unit: TimeUnit = SECONDS): Scene() {
override val angle: VisualAngleMode = VisualAngleMode.MODE_MEDIUM_SIGHT
override val priority: Int = 1
override val displayThreshold: Long
get() = 0
override fun toString(): String {
return "Default(delay=$delay, unit=$unit, angle=$angle, priority=$priority)"
}
}
/**
* 变道-接收到转向灯信息号
*/
class Turning(var open: Boolean = false): Scene() {
override val angle: VisualAngleMode = VisualAngleMode.MAP_STYLE_VR_ANGLE_TOP
override val priority: Int = 3
override val displayThreshold: Long
get() = -1
override fun toString(): String {
return "Turning(open: ${open}, priority=$priority, displayThreshold: $displayThreshold, priority=$priority)"
}
}
/**
* 后方车辆离自车过近
*/
object TooClose: Scene() {
override val angle: VisualAngleMode = VisualAngleMode.MAP_STYLE_VR_ANGLE_300
override val priority: Int = 2
override val displayThreshold: Long
get() = SECONDS.toMillis(8)
override fun toString(): String {
return "TooClose(priority=$priority, displayThreshold: $displayThreshold, priority=$priority)"
}
}
/**
* 道路事件
*/
object RoadEvent: Scene() {
override val angle: VisualAngleMode = VisualAngleMode.MODE_LONG_SIGHT
override val priority: Int = 5
override val displayThreshold: Long
get() = SECONDS.toMillis(8)
override fun toString(): String {
return "RoadEvent(priority=${priority}, displayThreshold: ${displayThreshold}, priority=${priority})"
}
}
/**
* 十字路口
*/
class CrossRoad(var open: Boolean = false): Scene() {
override val angle: VisualAngleMode = VisualAngleMode.MAP_STYLE_VR_ANGLE_CROSS
override val priority: Int = 4
override val displayThreshold: Long
get() = -1
override fun toString(): String {
return "CrossRoad(open: ${open}, priority=${priority}, displayThreshold: ${displayThreshold}, priority=${priority})"
}
}
}
/**
* 业务实体,不对外暴露
* @param target: 目标场景
* @param isDisplay: 是否正在展示
* @param triggerTime: 触发时间
*/
private data class Record(val target: Scene, var isDisplay: Boolean = false, var triggerTime: Long): Comparable<Record> {
override fun compareTo(other: Record): Int {
//如果时间一样,优先级越高,越靠近堆顶
return other.target.priority - target.priority
}
}
private val queue by lazy {
PriorityQueue<Record>()
}
fun changeVisualAngle(current: Scene) {
val appIdentityMode = FunctionBuildConfig.appIdentityMode
if (AppIdentityModeUtils.isBus(appIdentityMode) && AppIdentityModeUtils.isPassenger(appIdentityMode)) {
return
}
val triggerTime = SystemClock.elapsedRealtime()
scope.launch {
Log.d("${M_DEVA}${TAG}", "--- 1 ---")
val displayed = getDisplayed()
if (displayed == null) {
Log.d("${M_DEVA}${TAG}", "--- 2 ---")
if (current is Turning) {
if (!current.open) {
changeVisualAngle(Default())
return@launch
}
}
if (current is CrossRoad) {
if (!current.open) {
changeVisualAngle(Default())
return@launch
}
}
doRealVisualAngleChange(triggerTime, current, null)
} else {
val prev = displayed.target
Log.d("${M_DEVA}${TAG}", "--- 3 --- old: $prev -> cur: $current")
val prevTriggerTime = displayed.triggerTime
if (current !is Default && prev.priority > current.priority && (prev is RoadEvent || prev is TooClose)) {
val displayDuration = triggerTime - prevTriggerTime
Log.d("${M_DEVA}${TAG}", "--- 4 ---:场景[$prev], 已展示时长: duration: $displayDuration")
if (displayDuration < prev.displayThreshold) {
Log.d("${M_DEVA}${TAG}", "--- 5 --- 场景[$prev]:仍在保护展示时长内直接return")
return@launch
} else {
Log.d("${M_DEVA}${TAG}", "--- 6 --- 场景[$prev]:已过保护展示时长,从展示的队列中移除,显示默认视角")
queue -= displayed
changeVisualAngle(Default())
return@launch
}
}
if (prev is Turning && current is Turning) {
val isOpen = current.open
if (!isOpen) {
Log.d("${M_DEVA}${TAG}", "--- 7 --- 场景[$current], 收到关闭通知")
queue -= displayed
changeVisualAngle(Default())
return@launch
}
}
if (prev is CrossRoad && current is CrossRoad) {
val isOpen = current.open
if (!isOpen) {
Log.d("${M_DEVA}${TAG}", "--- 8 --- old: $prev -> cur: $current")
queue -= displayed
changeVisualAngle(Default())
return@launch
}
}
if (prev.priority == current.priority) {
Log.d("${M_DEVA}${TAG}", "--- 9 --- 场景[$prev]正在展示尚未收到关闭优先级一致直接return")
return@launch
}
if (prev.priority > current.priority && prev.displayThreshold < 0) {
Log.d("${M_DEVA}${TAG}", "--- 10 --- 场景[$prev]正在展示尚未收到关闭场景依然展示当前场景直接return")
return@launch
}
doRealVisualAngleChange(triggerTime, current, displayed)
}
}
}
private fun CoroutineScope.doRealVisualAngleChange(triggerTime: Long, target: Scene, displayed: Record? = null) {
if (target is Default) {
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 1 ---")
displayed?.also {
queue -= it
}
defaultDelayJob?.safeCancel()
launch {
val delay = target.unit.toMillis(target.delay)
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 2 ---")
delay(delay)
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 3 ---")
doChangeAngle(Record(target, triggerTime = triggerTime))
}.also { itx ->
itx.invokeOnCompletion {
if (it is CancellationException) {
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 4 ---")
}
}
defaultDelayJob = itx
}
} else {
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 5 ---")
defaultDelayJob?.safeCancel()
if (displayed == null || displayed.target.priority <= target.priority) {
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 6 ---")
displayed?.also {
queue -= it
}
if (target is Turning) {
if (!target.open) {
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 7 ---")
changeVisualAngle(Default())
return
}
}
if (target is CrossRoad) {
if (!target.open) {
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 8 ---")
changeVisualAngle(Default())
return
}
}
Log.d("${M_DEVA}${TAG}", "--- doRealVisualAngleChange --- 10 ---")
doChangeAngle(Record(target, triggerTime = triggerTime))
}
}
}
@OptIn(InternalCoroutinesApi::class)
private fun doChangeAngle(record: Record) {
val angle = record.target.angle
CallerMapUIServiceManager.getMapUIController()?.also {
Log.d("${M_DEVA}${TAG}", "--- doChangeAngle --- ${record.target}")
if (record.target !is Default) {
record.isDisplay = true
synchronized(queue) {
queue += record
}
}
it.changeMapVisualAngle(angle, null)
}
}
/**
* 是否有正在展示的
*/
@Synchronized
private fun getDisplayed() = queue.firstOrNull()
}