fWX228941 / project

all by myself
1 stars 0 forks source link

双通双待 #60

Open fWX228941 opened 6 months ago

fWX228941 commented 6 months ago

双待双通方案设计

  1. Launcher的设计方案 2 1.1. 基本需求 2 1.2. 方案设计与实现 2 1.2.1. 整体方案 2 1.2.2. 具体设计与实现 3 1.2.2.1. 主界面 3 1.2.2.2. 菜单设置项 8 1.2.2.3. 未读数 9 1.2.2.4. 按键的处理 10 1.2.2.5. 后台的通话悬浮窗 11 1.2.2.6. 状态栏图标 13
  2. 按键的设计方案 13 2.1. 按键的注册 13 2.2. 按键的配置 13 2.3. 按键的分发 14 2.4. 按键的处理 16
  3. CalttaSettings 16
  4. SettingsProvider 16
  5. 快捷键 16
  6. 息屏显示 17
  7. 指示灯 17

1.Launcher的设计方案 1.1.基本需求 1)Launcher增加一屏,变为两屏小部件显示; 2)两屏之间通过左右键来切换,支持循环切换; 3)第一屏永远为PTT键控制的模式; 4)不在该应用小部件界面,需要显示该应用后台通话悬浮窗; 5)小部件菜单进入对应工作模式的菜单列表,需去掉“工作模式”设置项; 1.2.方案设计与实现 1.2.1.整体方案 该方案基本原则: 尽量不对echat, pdt这些模式模式应用进行修改,应用在其对应的工作模式正常运行即可。

方案设计: 1)针对模式应用,查询当前系统工作模式,得到是应用当前正常运行应该所处的工作模式。

如果是echat-dmd双通模式,echat应用调用上面接口查询时,得到永远是工作模式6(echat模式),而不是数据库保存的真正值。而如果是pdt应用查询时,得到的是数据库真正保存的模式值,可能是dmd(2数字常规),也可能是dma(1模拟常规) 。而对于Launcher来说,查询的结果应该是数据库的值。 由于目前Launcher小部件,菜单,按键,未读数等都是依赖具体的工作模式值, 并且echat, pdt应用也是按照其对应的工作模式进行配置的,如果查询得到的不是应用对应的工作模式,应用需要进行该工作模式配置,否则运行会出错,因此改动较大。

2)系统需要提供接口,表示当前双待双通具体对应哪两种模式,第一屏应该显示哪个工作模式(即PTT键控制的工作模式)。 例如:双通对应echat, pdt的数字常规模式, 第一屏显示为pdt模式,设计如下:

当进行PTT按键,以及侧上键自定义配置后,会更新该双通模式值。

利用该值,可以作为系统是否为双通模式的功能定制,如下:

注意: 双通模式保存的PDT模式仅用于表示为PDT模式,具体是PDT哪个模式,是数字常规DMD,还是模拟常规DMA, 需要通过调用下面接口得到:

因为假如双通配置的是PDT的DMD模式,在切换到模拟信道后,工作模式会切换到PDT的DMA模式,而这个时候双通配置的模式还是DMD跟echat模式,因此会出现不匹配问题。

3)Launcher上很多场景需要根据当前小部件页面,得到对应的应用工作模式,然后根据该模式,跳转到不同应用的界面或执行不同的逻辑。实现如下:

1.2.2.具体设计与实现 1.2.2.1.主界面 1)要求: 双屏小部件显示,循环切换,状态栏是独立,不属于两屏小部件页面。

2)之前应用界面架构设计如下:

小部件页面fragment布局为:

3)如果是双通模式,应用界面架构设计为:

小部件页面Fragment布局为:

整个UI实现逻辑: 1)根据双通模式,选择加载launcher的布局为R.layout.layout_launcher_dual_pass,该布局主要包含状态栏以及页面容器ViewPager,状态栏不再属于小部件页面的一部分。如下:

2)状态栏显示控制,通过创建StatusbarViewController控制器来统一管理。如下:

StatusbarViewController初始化了状态栏信号,状态图标,通知,电量等所有相关业务控制器,最后用于控制状态栏LauncherStatusbarView对应View的显示,如下:

(之前这些业务控制器是放在小部件界面AppWidgetFragment初始化的,因为其不仅控制状态栏相关view的显示,同时还要控制下拉快捷设置的显示等)

3)往页面容器ViewPager添加两屏的小部件界面, 每个小部件界面设计为ModeWidgetFragment,同时FragmentPageAdapter设计为页面可循环切换。

小部件界面显示实现: 1)之前的小部件显示流程如下:

其中的loadWorkspace方法去获取当前工作模式下,解析应用meta-data配置的小部件,分配小部件id,生成小部件信息LauncherAppWidgetInfo, 将其保存到内存全局变量中。如下:

然后bindWidget方法,根据小部件appWidgetId, 生成小部件hostView,添加到小部件容器widget_container。

由于startLoader整个流程结束后,AppwidgetFragment还没有进入onCreateView方法,因此需要在onCreateView中调用getWidgetInfo方法获取解析到小部件信息,然后生成hostView,添加到小部件容器中。

2)如果是双通模式,流程如下: 2.1)loadWorkspaces方法,去加载两屏小部件页面对应的小部件信息。根据配置的双通模式,获取两个页面pageIndex对应的真正的工作模式值,然后分别解析工作模式对应的应用meta-data配置的小部件信息,分配小部件id,最后生成两屏小部件页面对应的小部件信息LauncherAppWidgetInfo, 将其保存到内存全局变量中,如下:

2.2)LauncherActivity的bindWidgets方法,根据页面pageIndex, 选择对应的小部件信息,最后调用对应页面fragment的bindWidget,构造小部件hostView,添加到小部件容器。如下:

ModeWidgetFragment需要在onCreateView中调用getWidgetInfo(int pageIndex)方法获取解析到小部件信息,然后生成hostView,添加到小部件容器中。

2.3)LauncherMode需要监听双通模式配置变化,重新loadWorkspaces以及bindWidgets用于触发两屏小部件界面刷新。 1.2.2.2.菜单设置项

1)要求: 点击当前小部件界面的菜单,进入该模式对应的菜单设置列表界面。如下:

同时需要去掉“工作模式”菜单项。

2)之前菜单界面是通过CalttaMenuActivity,内部加载CalttaMenuFragment实现的。 菜单项数据是通过子线程,通过MetaDataProvider解析当前模式下的各应用配置的菜单项来完成的。

每个应用只需要在其Activity进行相关配置即可,如下:

3)如果是双通模式,则需要判断是从第几屏小部件进入的菜单界面,知道第几屏后,就可以获取到对应的工作模式workMode,从而去调用MetaDataProvider加载各应用配置的菜单项,然后进行显示。(注意:小部件里的菜单可能是点击,也可能是按键触发的)

实现流程: 1)进入CalttaMenuFragment的onCreate方法时,获取ViewPager当前所在页index即第几屏。如下:

2)查询双通模式,根据当前页index,获取对应的工作模式值workMode。如下:

3)将工作模式workMode值传递给reloadAllTiles方法加载菜单项即可,如下:

4)去掉工作模式菜单项,只需要判断是双通模式,在加载的菜单项数据中过滤掉“工作模式”该菜单即可。 1.2.2.3.未读数 1)要求: 未读数显示包含两部分: 1.1)当前小部件界面的未读图标,仅显示当前小部件所在工作模式是否存在未读。 1.2)小部件菜单进入后各菜单项显示的未读数,仅对应该工作模式,同菜单设置项一样。 如下:

2)之前的设计 2.1)小部件界面上的未读图标,是通过获取当前工作模式,然后查询当前模式下所有应用配置的未读数的总和,如果总数>0则显示图标,否则不显示。 2.2)菜单每个设置项,是通过获取当前工作模式,然后查询当前模式下该菜单设置项配置的未读数,最后进行显示。 2.3)监听未读数变化,及时刷新。

3)如果是双通模式,未读数的实现基本与之前是相同的,最主要是根据当前所在页,去获取对应的工作模式,然后去查询数据库值。 1.2.2.4.按键的处理 1)要求: 左右键能够切换小部件界面, 左中右三个按键,触发当前小部件界面下面三个按钮。 拨号数字键跳转到当前小部件界面应用对应的拨号盘界面。 通话键跳转到当前小部件界面应用对应的通话记录界面

2)之前设计,Launcher应用处于前台时,按键交由LauncherActivity拦截分发。 左右键未处理。 左中右三个按键,由小部件界面AppWidgetFragment处理,按键启动的Activity的intent为:

获取当前工作模式,然后选择不同的三个按键启动的intent,然后跳转到对应模式应用界面。

拨号数字键,获取当前工作模式,选择拨号盘intent,然后跳转。

而对于拨号键,目前只针对PDT,btrunc进行跳转,在代码里都是写死的,获取当前模式,然后进行跳转对应应用的通话记录activity。

3)如果是双通模式,最主要就是获取当前所在页对应的工作模式,然后将该工作模式传递给要启动的intent。 左右键切换页面实现比较简单:计算要切换到的下一页pageIndex,然后调用mViewPager的setCurrentItem(pageIndex)即可。 1.2.2.5.后台的通话悬浮窗 1)要求: 应用在通话时,如果当前正处于该应用小部件界面,并且是处于前台则不需要显示该应用后台通话悬浮窗。否则都需要显示后台通话悬浮窗。

2)之前应用通话是否需要显示悬浮窗,是由Launcher发送广播进行通知的。实现方式如下:

各应用监听该广播,根据参数is_in_home_page决定是否要显示通话悬浮窗。 通知场景: Launcher应用处于前台时,并且当前页面是小部件界面,则通知is_in_home_page=true Launcher应用处于后台时,并且当前页面是小部件界面,则通知is_in_home_page=false

Launcher应用 ViewPager切换页面,如果当前页面是小部件界面,则通知is_in_home_page=true,否则通知is_in_home_page=false

3)如果是双通模式,处于两个模式应用echat, pdt应用尽量不修改的原则,根据应用场景,通过指定包名显示广播还是隐式广播发送,用于特定应用接收还是所有应用都能接收。

4)各种场景如下: 4.1)Launcher应用处于前台时,获取当前页index,然后得到当前页对应的工作模式workMode值。根据工作模式,通过解析应用小部件meta-data配置的对应工作模式workMode的包名, 然后指定该包名发送显式广播,通知该应用。

4.2)Launcher应用处于前台,页面切换时,通知当前模式对应应用不显示悬浮窗,另一个模式应用需要显示悬浮窗。

4.3)Launcher应用处于后台时,则需要通知两个模式应用,显示通话悬浮窗。不指定包名发送广播进行通知,保证两个模式应用都能够收到。

4.4)由于当前echat, pdt这些模式应用的后台通话悬浮窗都显示在屏幕的最右上方,因此会出现两个悬浮窗重叠现象。因此需额外对PDT应用的悬浮窗位置进行定制修改。 1.2.2.6.状态栏图标 当前状态栏是独立于双通模式下的echat, pdt小部件界面的,由于对当前小部件界面上的状态栏图标显示没有要求,当在echat或pdt小部件界面,状态栏上可以同时显示pdt, echat状态图标。如果后续要求,可以进行修改。

2.按键的设计方案 2.1.按键的注册 正常情况下,只有当前模式的应用才会注册按键事件,非当前模式的应用会取消按键的注册。为了能让多个应用都可能收到按键事件,需要应用去掉模式的判断,不管什么模式,都注册按键。 考虑到尽可能不修改应用,所以按如下思路实现:

终端默认数模常规 修改Settings数据库,如果是eChat应用来获取模式,固定返回eChat模式(让eChat应用误以为是eChat模式,从而注册按键),其他应用获取,按实际情况返回 去掉限制eChat仅在eChat模式下才能启动的限制 2.2.按键的配置 CalttaSettings提供UI给用户配置按键,具体以交互为准,这里不做考虑。为了扩展,配置结果的保存方式,不考虑具体需求,采用通用的规则 以“config_keytarget”+具体键值为key,应用的包名为value,多个包名之间用英文逗号间隔,代表这个键要给这些应用。比如config_key_target_287 = com.zte.pdt,代表287这个键需要传递给PDT应用 以“config_key_main”为key,应用的包名为value,代表按键以哪个应用为主,对于用户来说,就是平时以哪个种业务为主。 “config_keyreplace”+具体键值为key,valeu也为具体键值,代表需要在分发的时候将特定的键值替换成另一个键值来分发。 “config_key_target”的优先级高于“config_key_main”,即对于一个具体的按键,如果没有配置“config_key_target”,则传递给“config_key_main”对应的应用。 以上规则只适用于GotaKeyMonitor分发按键,如果是Android原生的按键传递方式,则不受上述配置影响

按定制需求,按键的配置如下: PTT键:config_key_target_287默认为com.mcptt,允许用户修改 侧上键:config_key_target_288默认为com.zte.pdt,允许用户修改,config_key_replace_288默认为287,不允许用户修改 挂断键:config_key_target_6默认为com.mcptt,不允许用户修改(常规无法挂断呼叫,所以挂断键只需要给eChat) 拨号键:config_key_target_5默认为com.mcptt,不允许用户修改(PDT应用不需要通过GotaKeyMonitor传递拨号键) SOS键、旋钮键:默认不配置,也不允许用户修改,跟着PTT键走

注:这套配置规则中的value都是包名,后续不利于融合应用来实现双通,如果是融合应用实现双通,不管用户怎么配置,value都是融合应用的包名,但是融合应用收到PTT键的时候,也不知道发起什么呼叫好,需要用额外的key来帮助融合应用判断发起什么业务。value如果不是包名,而是具体业务类型,那么按键分发的时候,按键服务就得知道哪个业务类型对应哪个包名。各有利弊 2.3.按键的分发 按键的分发由GotaKeyMonitor负责。正常情况下,GotaKeyMonitor只将按键发给最后一个注册按键的应用,为了实现双PTT键的效果,需要GotaKeyMonitor根据配置情况调整分发流程:

分发过程中,要对工厂模式做特殊处理,工厂模式下无视一切配置,只给工厂模式分发按键。避免工厂模式按键无法测试 2.4.按键的处理 按键的处理主要由PhoneWindowManager负责。当前处理按键的时候,判断了模式,不同模式下,可能处理逻辑不一样,但现在需要去掉模式的判断,因为模式永远都是PDT模式,但也需要判断eChat的情况。可能的修改如下: 侧上键:非工厂模式下要拦截,不要通过Android的按键传递到应用,避免触发快捷功能 Power键:PDT和eChat都不在通话中时,回到launcher。PDT在通话中时不传递挂断键,eChat通话中时,通过GotaKeyMonitor传递挂断键键值 拨号键:PDT和eChat任意一个在通话中时,按拨号键拉起luancher(当只有一路通话时launcher如何知道显示哪一路的小部件)并拦截拨号键。两者都不在通话中时,不要拦截拨号键,传递给当前界面。 3.CalttaSettings 系统设置需要增加按键的配置入口,具体参考交互。用户修改按键配置时,需要修改同时修改以下几个数据库值 PTT键和侧上键,互斥,不允许配置同一种业务 修改config_key_target与用户的设置结果保存一致 修改config_key_main的值,与PTT键的值保持一致 修改dual_pass_mode的值,PTT键对应的模式在前,侧上键对应的模式在后,英文逗号间隔 4.SettingsProvider 当前SettingsProvider提供了工作模式(cluster_mode_pdt_mpt)的数据库查询接口,为了实现双待双通,额外增加了双通模式的(dual_pass_mode)的保存,用于判断当前是哪两个模式双通,且第一个模式作为PTT键控制的模式。结合需求,需要修改的点如下: 当有应用获取工作模式(cluster_mode_pdt_mpt)时,判断包名,如果是eChat应用则固定返回eChat模式(6),其他应用则返回真实的数据 当PDT应用修改工作模式(cluster_mode_pdt_mpt)为模拟常规或着数字常规时,在SettingsProvider的服务端把双通模式中的PDT模式值也一并修改 默认配置dual_pass_mode为6,2;cluster_mode_pdt_mpt为2 5.快捷键 当前的快捷键功能,有部分是与模式相关的,比如短信功能,在DMR模式下打开的是DMR的短信,在eChat模式下打开的是eChat的短信。双待双通下,这类功能只响应PTT键对应的业务,比如PTT键控制eChat业务,则短信只会拉起eChat的短信。 同时部分快捷功能与双待双通冲突,也需要一起去掉。 要修改的点如下: 去掉侧上键快捷设置 去掉工作模式的快捷功能 判断工作模式的时候,优先判断双通模式dual_pass_mode,不存在时,才根据cluster_mode_pdt_mpt获取当前的模式 6.息屏显示 当前息屏的时候只会显示当前模式的信息,双待双通下,需求明确只显示PTT键对应的业务信息。所以息屏显示应用做出如下调整: 监听数据库dual_pass_mode字段的变化,提取第一个模式,并显示该模式对应的业务信息 dual_pass_mode的优先级高于cluster_mode_pdt_mpt

7.指示灯 当前的指示灯,按通知的优先级来控制灯,同等优先级下,以最后一个通知为准。双待双通时,可能存在两路通话,一路在讲,一路在听,此时指示灯的状态可能显示的是讲的状态,也可能是听的状态。这点改起来比较麻烦,需求层面,不对指示灯做具体要求,保持现状。

fWX228941 commented 6 months ago

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image

Image