Merge branch 'dev_robotaxi-d_231206_6.2.4' into dev_sweeper-d_231206_6.2.4

This commit is contained in:
xuxinchao
2023-12-13 17:13:01 +08:00
12 changed files with 342 additions and 34 deletions

View File

@@ -0,0 +1,225 @@
package com.mogo.launcher.lancet;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.ViewCompat;
import com.knightboost.lancet.api.Origin;
import com.knightboost.lancet.api.Scope;
import com.knightboost.lancet.api.annotations.Group;
import com.knightboost.lancet.api.annotations.ImplementedInterface;
import com.knightboost.lancet.api.annotations.Insert;
import com.knightboost.lancet.api.annotations.ReplaceInvoke;
import com.knightboost.lancet.api.annotations.TargetClass;
import com.knightboost.lancet.api.annotations.TargetMethod;
import com.knightboost.lancet.api.annotations.Weaver;
import com.mogo.launcher.R;
@Weaver
@Group("view_pressed_state")
public class ViewPressedStateLancet {
@TargetClass(value = "android.view.View", scope = Scope.ALL)
@TargetMethod(methodName = "setOnClickListener")
@ReplaceInvoke
public static void setOnClickListener(View view, View.OnClickListener listener) {
if (view == null) {
return;
}
Object tag = view.getTag(R.id.click_pressed_attr_id);
checkSetBgIfNeed(view, tag == null ? null : (AttributeSet) tag);
view.setOnClickListener(listener);
}
@TargetClass(value = "android.view.View", scope = Scope.ALL)
@TargetMethod(methodName = "setOnLongClickListener")
@ReplaceInvoke
public static void setOnLongClickListener(View view, View.OnLongClickListener listener) {
if (view == null) {
return;
}
Object tag = view.getTag(R.id.click_pressed_attr_id);
checkSetBgIfNeed(view, tag == null ? null : (AttributeSet) tag);
view.setOnLongClickListener(listener);
}
@ImplementedInterface(value = "android.view.LayoutInflater$Factory", scope = Scope.LEAF)
@Insert(mayCreateSuper = true)
@TargetMethod(methodName = "onCreateView")
public View onCreateView(String name, Context context, AttributeSet attrs) {
View view = (View) Origin.call();
checkSetBgIfNeed(view, attrs);
return view;
}
@ImplementedInterface(value = "android.view.LayoutInflater$Factory2", scope = Scope.LEAF)
@Insert(mayCreateSuper = true)
@TargetMethod(methodName = "onCreateView")
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
View view = (View) Origin.call();
checkSetBgIfNeed(view, attrs);
return view;
}
private static void checkSetBgIfNeed(View view, AttributeSet attr) {
try {
TypedArray t = null;
float alpha;
boolean enabled;
try {
if (view == null) {
return;
}
Context context = view.getContext();
if (context == null) {
return;
}
if (attr == null) {
return;
}
t = context.obtainStyledAttributes(attr, R.styleable.ClickPressedStyle);
enabled = t.getBoolean(R.styleable.ClickPressedStyle_pressed_enabled, true);
if (!enabled) {
return;
}
alpha = t.getFloat(R.styleable.ClickPressedStyle_pressed_alpha, 0.6f);
if (alpha < 0.0f || alpha > 1.0f) {
throw new AssertionError("view custom attr \\'alpha\\' must be in [0.0, 1.0]");
}
view.setTag(R.id.click_pressed_attr_id, attr);
} finally {
if (t != null) {
t.recycle();
}
}
if (view instanceof ImageView) {
ImageView image = (ImageView) view;
Drawable replaced = checkAndReplaceDrawable(image.getBackground(), alpha);
if (replaced != null) {
ViewCompat.setBackground(image, replaced);
return;
}
replaced = checkAndReplaceDrawable(image.getDrawable(), alpha);
if (replaced != null) {
image.setImageDrawable(replaced);
return;
}
return;
}
if (view instanceof TextView) {
TextView text = (TextView) view;
Drawable replaced = checkAndReplaceDrawable(text.getBackground(), alpha);
if (replaced != null) {
ViewCompat.setBackground(text, replaced);
return;
}
ColorStateList textColor = text.getTextColors();
if (textColor != null) {
int pressed = textColor.getColorForState(new int[]{ android.R.attr.state_pressed }, Integer.MIN_VALUE);
if (pressed != Integer.MIN_VALUE) {
return;
}
int color = textColor.getColorForState(new int[] { android.R.attr.state_enabled }, Integer.MIN_VALUE);
int defaultColor = color;
if (color == Integer.MIN_VALUE) {
defaultColor = textColor.getDefaultColor();
}
int pressedColor = Color.argb((int)(Color.alpha(defaultColor) * alpha), Color.red(defaultColor), Color.green(defaultColor), Color.blue(defaultColor));
int disableColor = textColor.getColorForState(new int[] { -android.R.attr.state_enabled }, Integer.MIN_VALUE);
int size = 2;
if (disableColor != Integer.MIN_VALUE) {
size += 1;
}
int[][] states = new int[size][1];
int[] colors = new int[size];
states[0] = new int[] { android.R.attr.state_pressed };
colors[0] = pressedColor;
if (size > 2) {
states[1] = new int[] { -android.R.attr.state_enabled };
colors[1] = disableColor;
states[2] = new int[] { android.R.attr.state_enabled };
colors[2] = defaultColor;
} else {
states[1] = new int[] { -android.R.attr.state_pressed };
colors[1] = defaultColor;
}
ColorStateList newColor = new ColorStateList(states, colors);
text.setTextColor(newColor);
}
return;
}
Drawable replaced = checkAndReplaceDrawable(view.getBackground(), alpha);
if (replaced != null) {
ViewCompat.setBackground(view, replaced);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
private static Drawable checkAndReplaceDrawable(Drawable old, float alpha) {
if (old == null) {
return null;
}
if (old instanceof StateListDrawable) {
StateListDrawable drawable = (StateListDrawable) old;
int[] states = drawable.getState();
boolean hasPressed = false;
int index = 0;
int targetIndex = -1;
for (int state : states) {
if (!hasPressed && state == android.R.attr.state_pressed) {
hasPressed = true;
}
if (targetIndex == -1 && state != -android.R.attr.state_enabled) {
targetIndex = index;
}
if (hasPressed && targetIndex != -1) {
break;
}
index ++;
}
if (hasPressed) {
return null;
}
if (targetIndex != -1) {
Drawable origin= null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
origin = drawable.getStateDrawable(targetIndex);
} else {
origin = drawable.getCurrent();
}
if (origin != null) {
Drawable.ConstantState constantState = origin.getConstantState();
if (constantState != null) {
Drawable pressed = DrawableCompat.wrap(constantState.newDrawable().mutate());
pressed.setAlpha((int)(255 * alpha));
drawable.addState(new int[] {android.R.attr.state_pressed}, pressed);
return drawable;
}
}
return null;
}
return null;
}
Drawable.ConstantState constantState = old.getConstantState();
if (constantState != null) {
StateListDrawable result = new StateListDrawable();
result.addState(new int[] { -android.R.attr.state_pressed }, old);
Drawable pressed = DrawableCompat.wrap(constantState.newDrawable().mutate());
pressed.setAlpha((int)(255 * alpha));
result.addState(new int[] { android.R.attr.state_pressed }, pressed);
return result;
}
return null;
}
}

View File

@@ -221,7 +221,7 @@ ext {
weak_network : "com.mogo.weak:network:1.0.1",
btrace : "com.bytedance.btrace:rhea-core:2.0.0",
mofang_runtime : "com.mogo.eagle.core.mofang:runtime:2.0.7",
mofang_runtime : "com.mogo.eagle.core.mofang:runtime:2.0.10",
log_runtime : "com.mogo.eagle.core.log.record:runtime:1.0.30",
// 安全证书

View File

@@ -69,7 +69,9 @@ class ApmEnvProviderImpl: IApmEnvProvider, CoroutineScope {
var dockerVersionChanged = false
val version = ApmEnvConfig.getDockerVersion()
if (!TextUtils.isEmpty(version) && !TextUtils.isEmpty(dockerVersion) && version != dockerVersion) {
dockerVersionChanged = version?.endsWith("release", true) == true || dockerVersion.endsWith("release", true)
val f1 = version?.endsWith("release", true) == true
val f2 = dockerVersion.endsWith("release", true)
dockerVersionChanged = if (f1 && f2) false else f1 || f2
if (dockerVersionChanged) {
ApmEnvConfig.setDockerVersion(dockerVersion)
}

View File

@@ -13,6 +13,7 @@ import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.deva.badcase.AiDataEntity
import com.mogo.eagle.core.data.deva.badcase.BagDescriptionEntity
import com.mogo.eagle.core.data.deva.badcase.BagInfoEntity
import com.mogo.eagle.core.data.deva.badcase.BagManagerEntity
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener
import com.mogo.eagle.core.function.api.devatools.badcase.BadCaseNetListener
@@ -41,6 +42,7 @@ import org.json.JSONObject
import record_cache.RecordPanelOuterClass
import java.lang.StringBuilder
import java.util.*
import kotlin.collections.ArrayList
/**
* @author XuXinChao
@@ -65,6 +67,7 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
private lateinit var tvCollectCancel: TextView //取消按钮
private var collectReason: StringBuilder = StringBuilder()
private var collectList = ArrayList<String>()
private var aiDataListAdapter: AiDataListAdapter?= null
@@ -114,13 +117,6 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
"时间:${millis2String(System.currentTimeMillis(), TimeUtils.getHourMinSecondFormat())}"
//采集结果回调监听
CallerAutopilotRecordListenerManager.addListener(this.hashCode().toString(), this)
//开始录制AI数据采集Bag包
CallerAutoPilotControlManager.recordPackage(
99,
Random(SystemClock.elapsedRealtime()).nextInt(),
20,
12
)
val linearLayoutManager = LinearLayoutManager(mActivity)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
rvCollectList?.layoutManager = linearLayoutManager
@@ -128,25 +124,35 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
aiDataListAdapter?.setListener(object: AiDataListAdapter.AiDataClickListener{
override fun onClick(reason: String, isChecked: Boolean) {
if(isChecked){
collectReason.append(reason)
if(!collectList.contains(reason)){
collectList.add(reason)
}
}else{
val index = collectReason.indexOf(reason)
collectReason.delete(index,index+reason.length)
if(collectList.contains(reason)){
collectList.remove(reason)
}
}
}
})
rvCollectList?.adapter = aiDataListAdapter
//注册网络接口获取数据监听
CallerDevaToolsNetManager.addListener(TAG,this)
CallerDevaToolsNetManager.addListener(this.hashCode().toString(),this)
//获取数据
BadCaseNetManager.badCaseNetManager.getAiData()
//上报
tvCollectReport.setOnClickListener {
if(collectReason.isBlank()){
if(collectList.isEmpty()){
ToastUtils.showShort("请选择最少一个原因")
return@setOnClickListener
}
collectReason.clear()
for(index in collectList.indices){
if(index!=0){
collectReason.append("&")
}
collectReason.append(collectList[index])
}
//上报到工控机
CallerAutoPilotControlManager.recordCause(recordKey.toString(),recordFileName,"",
collectReason.toString())
@@ -262,13 +268,36 @@ class AIDataCollectWindow constructor(activity: Activity) : View.OnTouchListener
mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight() - 950
mWindowManager!!.addView(mFloatLayout, mWindowParams)
}
//开始录制AI数据采集Bag包
CallerAutoPilotControlManager.recordPackage(
99,
Random(SystemClock.elapsedRealtime()).nextInt(),
20,
12
)
}
fun showReportBIWindow(bagInfoEntity: BagInfoEntity){
if (mFloatLayout.parent == null) {
val metrics = DisplayMetrics()
// 默认固定位置,靠屏幕右边缘的中间
mWindowManager!!.defaultDisplay.getMetrics(metrics)
mWindowParams!!.x = metrics.widthPixels
mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight() - 950
mWindowManager!!.addView(mFloatLayout, mWindowParams)
}
//已经录包无需再次启动录包,只要将录包信息同步到弹窗
bagInfoEntity.let {
recordKey = it.key
recordFileName = it.bagPath
}
}
fun hideFloatWindow() {
//注销采集结果回调监听
CallerAutopilotRecordListenerManager.removeListener(this.hashCode().toString())
//注销网络接口监听
CallerDevaToolsNetManager.removeListener(this)
CallerDevaToolsNetManager.removeListener(this.hashCode().toString())
// 移除 ADAS车辆状态&定位 监听
CallerChassisLocationWGS84ListenerManager.removeListener(this.hashCode().toString())
if (mFloatLayout.parent != null) mWindowManager!!.removeView(mFloatLayout)

View File

@@ -204,7 +204,7 @@ class BadCaseManagerView @JvmOverloads constructor(
aiDataCollectWindow.hideFloatWindow()
}
})
aiDataCollectWindow.showFloatWindow()
aiDataCollectWindow.showReportBIWindow(bagInfoEntity)
}
override fun editDescription(key: Long, description: BagDescriptionEntity) {

View File

@@ -72,6 +72,7 @@ import org.json.JSONObject
import record_cache.RecordPanelOuterClass
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
/**
@@ -111,6 +112,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
private var audioFileName:String?=null //录音文件名称
private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签
private var uploadList = ArrayList<String>() //上报原因列表
private var reasonDetail: String = "" //语音转写
private var uploadReasonTotal: String = ""
@Volatile
@@ -180,10 +182,13 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
badReasonListAdapter?.setListener(object: BadReasonListAdapter.ReasonClickListener{
override fun onClick(reason: String, isChecked: Boolean) {
if(isChecked){
uploadReason.append(reason)
if(!uploadList.contains(reason)){
uploadList.add(reason)
}
}else{
val index = uploadReason.indexOf(reason)
uploadReason.delete(index,index+reason.length)
if(uploadList.contains(reason)){
uploadList.remove(reason)
}
}
}
})
@@ -214,10 +219,17 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
//上报
tvInitiativeReport.setOnClickListener {
if(uploadReason.isBlank()){
if(uploadList.isEmpty()){
ToastUtils.showShort("请选择最少一个原因")
return@setOnClickListener
}
uploadReason.clear()
for(index in uploadList.indices){
if(index!=0){
uploadReason.append("&")
}
uploadReason.append(uploadList[index])
}
tvInitiativeReport.text = "上报中..."
if(audioStatus){
audioStatus = false
@@ -665,7 +677,11 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
else->"自驾状态:未知"
}
val speed = "当前车速:${BadCaseConfig.currentSpeed}"
val site = "起点:${CallerAutoPilotStatusListenerManager.getLineStartName()};终点:${CallerAutoPilotStatusListenerManager.getLineEndName()}"
val site = if(CallerAutoPilotStatusListenerManager.getLineStartName().isNullOrEmpty() || CallerAutoPilotStatusListenerManager.getLineEndName().isNullOrEmpty()){
"路线起始点:无"
}else{
"路线起点:${CallerAutoPilotStatusListenerManager.getLineStartName()};终点:${CallerAutoPilotStatusListenerManager.getLineEndName()}"
}
val outBitmap = RecordBitmapUtils.drawTextOnBitmap(bitmap,time,lineId,state,speed,site,
BadCaseConfig.gpsStatus,BadCaseConfig.tracingStatus,BadCaseConfig.socketStatus

View File

@@ -89,6 +89,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
private var bagManagerEntity: BagManagerEntity = BagManagerEntity()
private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签
private var uploadList = ArrayList<String>() //上报原因列表
private var recordKey: String?=null //录制bag包key
private var recordFileName: String?=null //录制文件包名
private var receiveTime: String ?= null //接收时间
@@ -171,10 +172,13 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
override fun onClick(reason: String, isChecked: Boolean) {
hasOperated = true
if(isChecked){
uploadReason.append(reason)
if(!uploadList.contains(reason)){
uploadList.add(reason)
}
}else{
val index = uploadReason.indexOf(reason)
uploadReason.delete(index,index+reason.length)
if(uploadList.contains(reason)){
uploadList.remove(reason)
}
}
}
})
@@ -203,10 +207,17 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
tvPassiveReport.setOnClickListener {
hasOperated = true
if(uploadReason.isEmpty()){
if(uploadList.isEmpty()){
TipToast.shortTip("请选择至少一个Case")
return@setOnClickListener
}
uploadReason.clear()
for(index in uploadList.indices){
if(index!=0){
uploadReason.append("&")
}
uploadReason.append(uploadList[index])
}
tvPassiveReport.text = "上报中..."
if(audioStatus){
audioStatus = !audioStatus
@@ -632,7 +643,11 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
else->"自驾状态:未知"
}
val speed = "当前车速:${BadCaseConfig.currentSpeed}"
val site = "起点:${CallerAutoPilotStatusListenerManager.getLineStartName()};终点:${CallerAutoPilotStatusListenerManager.getLineEndName()}"
val site = if(CallerAutoPilotStatusListenerManager.getLineStartName().isNullOrEmpty() || CallerAutoPilotStatusListenerManager.getLineEndName().isNullOrEmpty()){
"路线起始点:无"
}else{
"路线起点:${CallerAutoPilotStatusListenerManager.getLineStartName()};终点:${CallerAutoPilotStatusListenerManager.getLineEndName()}"
}
val outBitmap = RecordBitmapUtils.drawTextOnBitmap(bitmap,time,lineId,state,speed,site,
BadCaseConfig.gpsStatus,BadCaseConfig.tracingStatus,BadCaseConfig.socketStatus

View File

@@ -1,5 +1,6 @@
package com.zhjt.mogo_core_function_devatools.badcase.biz.adapter
import android.os.Build
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
@@ -125,6 +126,12 @@ class BagManagerListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
//已上报的Bag不支持再查看,图标置为灰色,并且不可点击
holder.ivMapScreen.alpha = 0.5f
holder.ivMapScreen.isClickable = false
//已上报的Bag不能再进行编辑编辑图标置灰并且不可点击
holder.ivEditReason.alpha = 0.5f
holder.ivEditReason.isClickable = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
holder.etBagNameEdit.focusable = View.NOT_FOCUSABLE
}
}else{
//未上报
holder.tvBagReportStatus.text = "上报"
@@ -147,6 +154,15 @@ class BagManagerListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
}
}
}
//编辑文字按钮
holder.ivEditReason.setOnClickListener {
holder.etBagNameEdit.requestFocus()
holder.etBagNameEdit.performClick()
//调起软键盘
bagClickListener?.startEdit(holder.etBagNameEdit)
}
}
}
if(des.description.isEmpty()){
@@ -173,13 +189,7 @@ class BagManagerListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
holder.tvBagResource.setBackgroundResource(R.drawable.bag_auto_button_bg)
}
//编辑文字按钮
holder.ivEditReason.setOnClickListener {
holder.etBagNameEdit.requestFocus()
holder.etBagNameEdit.performClick()
//调起软键盘
bagClickListener?.startEdit(holder.etBagNameEdit)
}
if(bagInfoEntity.description?.hasAudio == true){
holder.ivBagAudio.visibility = View.VISIBLE

View File

@@ -83,7 +83,7 @@ object RecordBitmapUtils {
val mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
val canvas = Canvas(mutableBitmap)
val paint = Paint()
paint.color = Color.RED
paint.color = Color.WHITE
paint.textSize = 50f
paint.isAntiAlias = true
canvas.drawText(time, 100f, 100f, paint)

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="click_pressed_attr_id" type="id" />
</resources>

View File

@@ -13,4 +13,8 @@
</declare-styleable>
<declare-styleable name="ClickPressedStyle">
<attr name="pressed_alpha" format="float" />
<attr name="pressed_enabled" format="boolean" />
</declare-styleable>
</resources>

View File

@@ -30,6 +30,9 @@ LancetX {
main_block_check {
enable rootProject.isJunkDetectEnable()
}
view_pressed_state {
enable false
}
}
}