查看: 2819|回复: 0

[经验] RK3288 增加双屏异显 eDP+LVDS

[复制链接]
  • TA的每日心情
    开心
    2019-11-4 13:48
  • 签到天数: 14 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2019-2-18 17:25:36 | 显示全部楼层 |阅读模式
    分享到:
    CPU:RK3288
    系统:Android 5.1

    下面是官方文档中的信息。
    1、rk3288 支持的显示接口可以任意组合。
    2、双屏异显时,一个显示接口当主屏,另一个当副屏;主副屏由板级 dts 文件确定,启动后无法动态更改。
    3、当两路显示接口显示不同分辨率时,rk3288 只能为一路显示接口提供精确时钟,另一路显示接口时钟会有微小频偏。

    瑞芯微虽然提供了 Android 5.1 的补丁,但是本人在移植过程中出现一些问题(打补丁最好一行行核对,不要图方便直接使用指令)。
    设备 eDP 为主屏,lvds 为副屏。

    (1)首先修改两个屏参文件 lcd-xxx.dtsi。
    eDP 屏参文件补丁
    1. diff --git a/kernel/arch/arm/boot/dts/lcd-NV116FH1.dtsi b/kernel/arch/arm/boot/dts/lcd-NV116FH1.dtsi
    2. index 3862b05..7bf992f 100755
    3. --- a/kernel/arch/arm/boot/dts/lcd-NV116FH1.dtsi
    4. +++ b/kernel/arch/arm/boot/dts/lcd-NV116FH1.dtsi
    5. @@ -3,11 +3,9 @@
    6.   *
    7.   */

    8. -/ {
    9. -
    10. -        disp_timings: display-timings {
    11. -                        native-mode = <&timing0>;
    12. -                        timing0: timing0 {
    13. +        display-timings {
    14. +                        native-mode = <&nv116fhm>;
    15. +                        nv116fhm: timing0 {
    16.                  screen-type = <SCREEN_EDP>;
    17.                  out-face    = <OUT_P666>;
    18.                  clock-frequency = <205000000>;
    19. @@ -30,4 +30,3 @@
    20.                 swap-gb = <0>;
    21.                          };
    22.                };
    23. -};
    复制代码
    lvds 屏参文件补丁、
    1. diff --git a/kernel/arch/arm/boot/dts/lcd-ZJ080NA-08A.dtsi b/kernel/arch/arm/boot/dts/lcd-ZJ080NA-08A.dtsi
    2. old mode 100644
    3. new mode 100755
    4. index fc6385c..58f999be
    5. --- a/kernel/arch/arm/boot/dts/lcd-ZJ080NA-08A.dtsi
    6. +++ b/kernel/arch/arm/boot/dts/lcd-ZJ080NA-08A.dtsi
    7. @@ -3,11 +3,10 @@
    8.   *
    9.   */

    10. -/ {

    11. -        disp_timings: display-timings {
    12. -                        native-mode = <&timing0>;
    13. -                        timing0: timing0 {
    14. +        display-timings {
    15. +                        native-mode = <&zj080na>;
    16. +                        zj080na: timing0 {
    17.                  screen-type = <SCREEN_DUAL_LVDS>;
    18.                  lvds-format = <LVDS_8BIT_1>;
    19.                  out-face    = <OUT_P888>;
    20. @@ -30,4 +30,3 @@
    21.                 swap-gb = <0>;
    22.              };
    23.          };
    24. -};
    复制代码
    (2)根据官方提供,打上 kernel 补丁
    1. diff --git a/kernel/arch/arm/boot/dts/rk3288-tb_8846.dts b/kernel/arch/arm/boot/dts/rk3288-tb_8846.dts
    2. index 6a65163..fc48fc0 100755
    3. --- a/kernel/arch/arm/boot/dts/rk3288-tb_8846.dts
    4. +++ b/kernel/arch/arm/boot/dts/rk3288-tb_8846.dts
    5. @@ -565,12 +565,56 @@ clock-frequency = <50000000>;
    6. };

    7. &fb {
    8. -    rockchip,disp-mode = <DUAL>;
    9. -    rockchip,uboot-logo-on = <1>;
    10. +    rockchip,disp-mode = <DUAL_LCD>;
    11. +    rockchip,uboot-logo-on = <0>;
    12. };

    13. &rk_screen {
    14. -     display-timings = <&disp_timings>;
    15. +    status = "okay";
    16. +    screen0 {
    17. +        screen_prop = <PRMRY>;
    18. +        native-mode = <DEFAULT_MODE>;
    19. +        power_ctr {
    20. +            lcd_en {
    21. +                rockchip,power_type = <GPIO>;
    22. +                gpios = <&gpio7 GPIO_A5 GPIO_ACTIVE_HIGH>;
    23. +                rockchip,delay = <10>;
    24. +            };
    25. +            /*lcd_cs {
    26. +                rockchip,power_type = <GPIO>;
    27. +                gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
    28. +                rockchip,delay = <10>;
    29. +            };*/
    30. +        };
    31. +        #include "lcd-NV156FH1.dtsi"
    32. +    };
    33. +    screen1 {
    34. +        screen_prop = <EXTEND>;
    35. +        native-mode = <DEFAULT_MODE>;
    36. +        power_ctr {
    37. +            lcd_en {
    38. +                rockchip,power_type = <GPIO>;
    39. +                gpios = <&gpio7 GPIO_A3 GPIO_ACTIVE_HIGH>;
    40. +                rockchip,delay = <10>;
    41. +            };
    42. +            /*lcd_cs {
    43. +                rockchip,power_type = <GPIO>;
    44. +                gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
    45. +                rockchip,delay = <10>;
    46. +            };*/
    47. +        };
    48. +        #include "lcd-ZJ080NA-08A.dtsi"
    49. +    };
    50. +};
    51. +
    52. +&edp {
    53. +    status = "okay";
    54. +    prop = <PRMRY>;
    55. +};
    56. +
    57. +&lvds {
    58. +    status = "okay";
    59. +    prop = <EXTEND>;
    60. };

    61. /*lcdc0 as PRMRY(LCD),lcdc1 as EXTEND(HDMI)*/
    62. @@ -587,18 +631,18 @@ clock-frequency = <50000000>;
    63.              rockchip,delay = <5>;
    64.          };*/

    65. -        lcd_en:lcd_en {
    66. +        /*lcd_en:lcd_en {
    67.              rockchip,power_type = <GPIO>;
    68.              gpios = <&gpio7 GPIO_A3 GPIO_ACTIVE_HIGH>;
    69.              rockchip,delay = <200>;
    70.          };
    71.          
    72. -        /*lcd_cs:lcd_cs {
    73. +        lcd_cs:lcd_cs {
    74.              rockchip,power_type = <GPIO>;
    75.              gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
    76.              rockchip,delay = <10>;
    77. -        };*/
    78. -
    79. +        };
    80. +        */
    81.          /*lcd_rst:lcd_rst {
    82.              rockchip,power_type = <GPIO>;
    83.              gpios = <&gpio3 GPIO_D6 GPIO_ACTIVE_HIGH>;
    84. @@ -615,7 +659,7 @@ clock-frequency = <50000000>;
    85. };

    86. &hdmi {
    87. -    status = "okay";
    88. +    status = "disabled";
    89.      rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
    90. };

    91. diff --git a/kernel/drivers/video/rockchip/rk_fb.c b/kernel/drivers/video/rockchip/rk_fb.c
    92. index 533ce2b..4037cfd 100755
    93. --- a/kernel/drivers/video/rockchip/rk_fb.c
    94. +++ b/kernel/drivers/video/rockchip/rk_fb.c
    95. @@ -112,9 +112,8 @@ EXPORT_SYMBOL(video_data_to_mirroring);
    96. extern phys_addr_t uboot_logo_base;
    97. extern phys_addr_t uboot_logo_size;
    98. extern phys_addr_t uboot_logo_offset;
    99. -static struct rk_fb_trsm_ops *trsm_lvds_ops;
    100. -static struct rk_fb_trsm_ops *trsm_edp_ops;
    101. -static struct rk_fb_trsm_ops *trsm_mipi_ops;
    102. +static struct rk_fb_trsm_ops *trsm_prmry_ops;
    103. +static struct rk_fb_trsm_ops *trsm_extend_ops;
    104. static int uboot_logo_on;

    105. static int rk_fb_debug_lvl;
    106. @@ -148,53 +147,24 @@ int rk_fb_get_display_policy(void)

    107. int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
    108. {
    109. -    switch (type) {
    110. -    case SCREEN_RGB:
    111. -    case SCREEN_LVDS:
    112. -    case SCREEN_DUAL_LVDS:
    113. -    case SCREEN_LVDS_10BIT:
    114. -    case SCREEN_DUAL_LVDS_10BIT:
    115. -        trsm_lvds_ops = ops;
    116. -        break;
    117. -    case SCREEN_EDP:
    118. -        trsm_edp_ops = ops;
    119. -        break;
    120. -    case SCREEN_MIPI:
    121. -    case SCREEN_DUAL_MIPI:
    122. -        trsm_mipi_ops = ops;
    123. -        break;
    124. -    default:
    125. -        printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
    126. -               __func__, type);
    127. -        break;
    128. -    }
    129. +    if (type == PRMRY)
    130. +        trsm_prmry_ops = ops;
    131. +    else if (type == EXTEND)
    132. +        trsm_extend_ops = ops;
    133. +    else
    134. +        pr_err("%s, type:%d\n", __func__, type);
    135.      return 0;
    136. }

    137. struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
    138. {
    139.      struct rk_fb_trsm_ops *ops;
    140. -    switch (type) {
    141. -    case SCREEN_RGB:
    142. -    case SCREEN_LVDS:
    143. -    case SCREEN_DUAL_LVDS:
    144. -    case SCREEN_LVDS_10BIT:
    145. -    case SCREEN_DUAL_LVDS_10BIT:
    146. -        ops = trsm_lvds_ops;
    147. -        break;
    148. -    case SCREEN_EDP:
    149. -        ops = trsm_edp_ops;
    150. -        break;
    151. -    case SCREEN_MIPI:
    152. -    case SCREEN_DUAL_MIPI:
    153. -        ops = trsm_mipi_ops;
    154. -        break;
    155. -    default:
    156. -        ops = NULL;
    157. -        printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
    158. -               __func__, type);
    159. -        break;
    160. -    }
    161. +    if (type == PRMRY)
    162. +        ops = trsm_prmry_ops;
    163. +    else if (type == EXTEND)
    164. +        ops = trsm_extend_ops;
    165. +    else
    166. +        pr_err("%s, type:%d\n", __func__, type);
    167.      return ops;
    168. }

    169. @@ -318,10 +288,10 @@ static int rk_fb_data_fmt(int data_format, int bits_per_pixel)
    170. /*
    171.   * rk display power control parse from dts
    172.   */
    173. -int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
    174. +int rk_disp_pwr_ctr_parse_dt(struct device_node *np,
    175. +                 struct rk_screen *rk_screen)
    176. {
    177. -    struct device_node *root = of_get_child_by_name(dev_drv->dev->of_node,
    178. -                            "power_ctr");
    179. +    struct device_node *root = of_get_child_by_name(np, "power_ctr");
    180.      struct device_node *child;
    181.      struct rk_disp_pwr_ctr_list *pwr_ctr;
    182.      struct list_head *pos;
    183. @@ -330,10 +300,10 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
    184.      u32 debug = 0;
    185.      int ret;

    186. -    INIT_LIST_HEAD(&dev_drv->pwrlist_head);
    187. +    INIT_LIST_HEAD(rk_screen->pwrlist_head);
    188.      if (!root) {
    189. -        dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",
    190. -            dev_drv->id);
    191. +        dev_err(rk_screen->dev, "can't find power_ctr node for lcdc%d\n",
    192. +            rk_screen->lcdc_id);
    193.          return -ENODEV;
    194.      }

    195. @@ -346,7 +316,7 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
    196.                  pwr_ctr->pwr_ctr.type = GPIO;
    197.                  pwr_ctr->pwr_ctr.gpio = of_get_gpio_flags(child, 0, &flags);
    198.                  if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
    199. -                    dev_err(dev_drv->dev, "%s ivalid gpio\n",
    200. +                    dev_err(rk_screen->dev, "%s ivalid gpio\n",
    201.                          child->name);
    202.                      return -EINVAL;
    203.                  }
    204. @@ -354,7 +324,7 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
    205.                  ret = gpio_request(pwr_ctr->pwr_ctr.gpio,
    206.                             child->name);
    207.                  if (ret) {
    208. -                    dev_err(dev_drv->dev,
    209. +                    dev_err(rk_screen->dev,
    210.                          "request %s gpio fail:%d\n",
    211.                          child->name, ret);
    212.                  }
    213. @@ -365,7 +335,7 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
    214.                  ret = of_property_read_string(child, "rockchip,regulator_name",
    215.                                   &(pwr_ctr->pwr_ctr.rgl_name));
    216.                  if (ret || IS_ERR_OR_NULL(pwr_ctr->pwr_ctr.rgl_name))
    217. -                    dev_err(dev_drv->dev, "get regulator name failed!\n");
    218. +                    dev_err(rk_screen->dev, "get regulator name failed!\n");
    219.                  if (!of_property_read_u32(child, "rockchip,regulator_voltage", &val))
    220.                      pwr_ctr->pwr_ctr.volt = val;
    221.                  else
    222. @@ -377,13 +347,13 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
    223.              pwr_ctr->pwr_ctr.delay = val;
    224.          else
    225.              pwr_ctr->pwr_ctr.delay = 0;
    226. -        list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
    227. +        list_add_tail(&pwr_ctr->list, rk_screen->pwrlist_head);
    228.      }

    229.      of_property_read_u32(root, "rockchip,debug", &debug);

    230.      if (debug) {
    231. -        list_for_each(pos, &dev_drv->pwrlist_head) {
    232. +        list_for_each(pos, rk_screen->pwrlist_head) {
    233.              pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list,
    234.                           list);
    235.              printk(KERN_INFO "pwr_ctr_name:%s\n"
    236. @@ -411,9 +381,14 @@ int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv)
    237.      struct regulator *regulator_lcd = NULL;
    238.      int count = 10;

    239. -    if (list_empty(&dev_drv->pwrlist_head))
    240. +    if (!dev_drv->cur_screen->pwrlist_head) {
    241. +        pr_info("error:  %s, lcdc%d screen pwrlist null\n",
    242. +            __func__, dev_drv->id);
    243. +        return 0;
    244. +    }
    245. +    if (list_empty(dev_drv->cur_screen->pwrlist_head))
    246.          return 0;
    247. -    list_for_each(pos, &dev_drv->pwrlist_head) {
    248. +    list_for_each(pos, dev_drv->cur_screen->pwrlist_head) {
    249.          pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
    250.                        list);
    251.          pwr_ctr = &pwr_ctr_list->pwr_ctr;
    252. @@ -455,9 +430,14 @@ int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv)
    253.      struct regulator *regulator_lcd = NULL;
    254.      int count = 10;

    255. -    if (list_empty(&dev_drv->pwrlist_head))
    256. +    if (!dev_drv->cur_screen->pwrlist_head) {
    257. +        pr_info("error:  %s, lcdc%d screen pwrlist null\n",
    258. +            __func__, dev_drv->id);
    259.          return 0;
    260. -    list_for_each(pos, &dev_drv->pwrlist_head) {
    261. +    }
    262. +    if (list_empty(dev_drv->cur_screen->pwrlist_head))
    263. +        return 0;
    264. +    list_for_each(pos, dev_drv->cur_screen->pwrlist_head) {
    265.          pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
    266.                        list);
    267.          pwr_ctr = &pwr_ctr_list->pwr_ctr;
    268. @@ -586,7 +566,7 @@ int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
    269.          pr_err("parse display timing err\n");
    270.          return -EINVAL;
    271.      }
    272. -    dt = display_timings_get(disp_timing, disp_timing->native_mode);
    273. +    dt = display_timings_get(disp_timing, screen->native_mode);
    274.      rk_fb_video_mode_from_timing(dt, screen);
    275.      return 0;

    276. @@ -1676,6 +1656,7 @@ static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
    277.                  win->area[i].smem_start =
    278.                      reg_win_data->reg_area_data[i].smem_start;
    279.                                  if (inf->disp_mode == DUAL ||
    280. +                                    inf->disp_mode == DUAL_LCD ||
    281.                                      inf->disp_mode == NO_DUAL) {
    282.                          win->area[i].xpos =
    283.                                  reg_win_data->reg_area_data[i].xpos;
    284. @@ -3852,7 +3833,8 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi)
    285.          win = dev_drv->win[win_id];

    286.      if (!strcmp(fbi->fix.id, "fb0")) {
    287. -        fb_mem_size = get_fb_size(dev_drv->reserved_fb);
    288. +        fb_mem_size = get_fb_size(dev_drv->reserved_fb,
    289. +                      dev_drv->cur_screen);
    290. #if defined(CONFIG_ION_ROCKCHIP)
    291.          if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
    292.              return -ENOMEM;
    293. @@ -3873,7 +3855,8 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi)
    294.          if (dev_drv->prop == EXTEND && dev_drv->iommu_enabled) {
    295.              struct rk_lcdc_driver *dev_drv_prmry;
    296.              int win_id_prmry;
    297. -            fb_mem_size = get_fb_size(dev_drv->reserved_fb);
    298. +            fb_mem_size = get_fb_size(dev_drv->reserved_fb,
    299. +                          dev_drv->cur_screen);
    300. #if defined(CONFIG_ION_ROCKCHIP)
    301.              dev_drv_prmry = rk_get_prmry_lcdc_drv();
    302.              if (dev_drv_prmry == NULL)
    303. @@ -4036,14 +4019,9 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
    304.          dev_drv->area_support[i] = 1;
    305.      if (dev_drv->ops->area_support_num)
    306.          dev_drv->ops->area_support_num(dev_drv, dev_drv->area_support);
    307. -    rk_disp_pwr_ctr_parse_dt(dev_drv);
    308. -    if (dev_drv->prop == PRMRY) {
    309. -        rk_fb_set_prmry_screen(screen);
    310. -        rk_fb_get_prmry_screen(screen);
    311. -    }
    312. -    dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
    313. -    if (dev_drv->prop != PRMRY)
    314. -        rk_fb_get_extern_screen(screen);
    315. +    rk_fb_set_screen(screen, dev_drv->prop);
    316. +    rk_fb_get_screen(screen, dev_drv->prop);
    317. +    dev_drv->trsm_ops = rk_fb_trsm_ops_get(dev_drv->prop);
    318.      dev_drv->output_color = screen->color_mode;

    319.      return 0;
    320. @@ -4361,17 +4339,24 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
    321.          main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
    322. #endif
    323.      } else {
    324. -                struct fb_info *extend_fbi = rk_fb->fb[rk_fb->num_fb >> 1];
    325. -                extend_fbi->var.pixclock = rk_fb->fb[0]->var.pixclock;
    326. +        struct fb_info *extend_fbi = rk_fb->fb[rk_fb->num_fb >> 1];
    327. +        extend_fbi->var.pixclock = rk_fb->fb[0]->var.pixclock;
    328. +        extend_fbi->var.xres_virtual = rk_fb->fb[0]->var.xres_virtual;
    329. +        extend_fbi->var.yres_virtual = rk_fb->fb[0]->var.yres_virtual;
    330.          extend_fbi->fbops->fb_open(extend_fbi, 1);
    331. -#if defined(CONFIG_ROCKCHIP_IOMMU)
    332.          if (dev_drv->iommu_enabled) {
    333.              if (dev_drv->mmu_dev)
    334.                  rockchip_iovmm_set_fault_handler(dev_drv->dev,
    335.                                   rk_fb_sysmmu_fault_handler);
    336. +                if (dev_drv->ops->mmu_en)
    337. +                    dev_drv->ops->mmu_en(dev_drv);
    338.          }
    339. -#endif
    340.          rk_fb_alloc_buffer(extend_fbi);
    341. +        if (rk_fb->disp_mode == DUAL_LCD) {
    342. +            extend_fbi->fbops->fb_set_par(extend_fbi);
    343. +            extend_fbi->fbops->fb_pan_display(&extend_fbi->var,
    344. +                              extend_fbi);
    345. +        }
    346.      }
    347. #endif
    348.      return 0;
    349. diff --git a/kernel/drivers/video/rockchip/screen/rk_screen.c b/kernel/drivers/video/rockchip/screen/rk_screen.c
    350. index d5e3b15..87a82d9 100755
    351. --- a/kernel/drivers/video/rockchip/screen/rk_screen.c
    352. +++ b/kernel/drivers/video/rockchip/screen/rk_screen.c
    353. @@ -4,14 +4,23 @@
    354. #include "lcd.h"
    355. #include "../hdmi/rockchip-hdmi.h"

    356. -static struct rk_screen *rk_screen;
    357. +static struct rk_screen *prmry_screen;
    358. +static struct rk_screen *extend_screen;
    359. +
    360. +static void rk_screen_info_error(struct rk_screen *screen, int prop)
    361. +{
    362. +    pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
    363. +    pr_err(">>please init %s screen info in dtsi file<<\n",
    364. +           (prop == PRMRY) ? "prmry" : "extend");
    365. +    pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
    366. +}

    367. int rk_fb_get_extern_screen(struct rk_screen *screen)
    368. {
    369. -    if (unlikely(!rk_screen) || unlikely(!screen))
    370. +    if (unlikely(!extend_screen) || unlikely(!screen))
    371.          return -1;

    372. -    memcpy(screen, rk_screen, sizeof(struct rk_screen));
    373. +    memcpy(screen, extend_screen, sizeof(struct rk_screen));
    374.      screen->dsp_lut = NULL;
    375.      screen->cabc_lut = NULL;
    376.      screen->type = SCREEN_NULL;
    377. @@ -19,42 +28,84 @@ int rk_fb_get_extern_screen(struct rk_screen *screen)
    378.      return 0;
    379. }

    380. -int  rk_fb_get_prmry_screen(struct rk_screen *screen)
    381. +int rk_fb_get_prmry_screen(struct rk_screen *screen)
    382. {
    383. -    if (unlikely(!rk_screen) || unlikely(!screen))
    384. +    if (unlikely(!prmry_screen) || unlikely(!screen))
    385.          return -1;

    386. -    memcpy(screen, rk_screen, sizeof(struct rk_screen));
    387. +    memcpy(screen, prmry_screen, sizeof(struct rk_screen));
    388.      return 0;
    389. }

    390. -int rk_fb_set_prmry_screen(struct rk_screen *screen)
    391. +int rk_fb_get_screen(struct rk_screen *screen, int prop)
    392. {
    393. -    if (unlikely(!rk_screen) || unlikely(!screen))
    394. +    struct rk_screen *cur_screen = NULL;
    395. +
    396. +    if (unlikely(!screen))
    397.          return -1;

    398. -    rk_screen->lcdc_id = screen->lcdc_id;
    399. -    rk_screen->screen_id = screen->screen_id;
    400. -    rk_screen->x_mirror = screen->x_mirror;
    401. -    rk_screen->y_mirror = screen->y_mirror;
    402. -    rk_screen->overscan.left = screen->overscan.left;
    403. -    rk_screen->overscan.top = screen->overscan.left;
    404. -    rk_screen->overscan.right = screen->overscan.left;
    405. -    rk_screen->overscan.bottom = screen->overscan.left;
    406. +    if (prop == PRMRY) {
    407. +        if (unlikely(!prmry_screen)) {
    408. +            rk_screen_info_error(screen, prop);
    409. +            return -1;
    410. +        }
    411. +        cur_screen = prmry_screen;
    412. +    } else {
    413. +        if (unlikely(!extend_screen)) {
    414. +            rk_screen_info_error(screen, prop);
    415. +            return -1;
    416. +        }
    417. +        cur_screen = extend_screen;
    418. +    }
    419. +
    420. +    memcpy(screen, cur_screen, sizeof(struct rk_screen));
    421. +
    422.      return 0;
    423. }

    424. -size_t get_fb_size(u8 reserved_fb)
    425. +int rk_fb_set_screen(struct rk_screen *screen, int prop)
    426. +{
    427. +    struct rk_screen *cur_screen = NULL;
    428. +
    429. +    if (unlikely(!screen))
    430. +        return -1;
    431. +    if (prop == PRMRY) {
    432. +        if (unlikely(!prmry_screen)) {
    433. +            rk_screen_info_error(screen, prop);
    434. +            return -1;
    435. +        }
    436. +        cur_screen = prmry_screen;
    437. +    } else {
    438. +        if (unlikely(!extend_screen)) {
    439. +            rk_screen_info_error(screen, prop);
    440. +            return -1;
    441. +        }
    442. +        cur_screen = extend_screen;
    443. +    }
    444. +
    445. +    cur_screen->lcdc_id = screen->lcdc_id;
    446. +    cur_screen->screen_id = screen->screen_id;
    447. +    cur_screen->x_mirror = screen->x_mirror;
    448. +    cur_screen->y_mirror = screen->y_mirror;
    449. +    cur_screen->overscan.left = screen->overscan.left;
    450. +    cur_screen->overscan.top = screen->overscan.left;
    451. +    cur_screen->overscan.right = screen->overscan.left;
    452. +    cur_screen->overscan.bottom = screen->overscan.left;
    453. +
    454. +    return 0;
    455. +}
    456. +
    457. +size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen)
    458. {
    459.      size_t size = 0;
    460.      u32 xres = 0;
    461.      u32 yres = 0;

    462. -    if (unlikely(!rk_screen))
    463. +    if (unlikely(!screen))
    464.          return 0;

    465. -    xres = rk_screen->mode.xres;
    466. -    yres = rk_screen->mode.yres;
    467. +    xres = screen->mode.xres;
    468. +    yres = screen->mode.yres;

    469.      /* align as 64 bytes(16*4) in an odd number of times */
    470.      xres = ALIGN_64BYTE_ODD_TIMES(xres, ALIGN_PIXEL_64BYTE_RGB8888);
    471. @@ -73,22 +124,51 @@ size_t get_fb_size(u8 reserved_fb)
    472. static int rk_screen_probe(struct platform_device *pdev)
    473. {
    474.      struct device_node *np = pdev->dev.of_node;
    475. -    int ret;
    476. +    struct device_node *screen_np;
    477. +    struct rk_screen *rk_screen;
    478. +    int ret, screen_prop;

    479.      if (!np) {
    480.          dev_err(&pdev->dev, "Missing device tree node.\n");
    481.          return -EINVAL;
    482.      }
    483. -    rk_screen = devm_kzalloc(&pdev->dev,
    484. -            sizeof(struct rk_screen), GFP_KERNEL);
    485. -    if (!rk_screen) {
    486. -        dev_err(&pdev->dev, "kmalloc for rk screen fail!");
    487. -        return  -ENOMEM;
    488. +   
    489. +    for_each_child_of_node(np, screen_np) {
    490. +        rk_screen = devm_kzalloc(&pdev->dev,
    491. +                     sizeof(struct rk_screen), GFP_KERNEL);
    492. +        if (!rk_screen) {
    493. +            dev_err(&pdev->dev, "kmalloc for rk screen fail!");
    494. +            return  -ENOMEM;
    495. +        }
    496. +        rk_screen->pwrlist_head = devm_kzalloc(&pdev->dev,
    497. +                sizeof(struct list_head), GFP_KERNEL);
    498. +        if (!rk_screen->pwrlist_head) {
    499. +            dev_err(&pdev->dev, "kmalloc for rk_screen pwrlist_head fail!");
    500. +            return  -ENOMEM;
    501. +        }
    502. +        of_property_read_u32(screen_np, "screen_prop", &screen_prop);
    503. +        if (screen_prop == PRMRY)
    504. +            prmry_screen = rk_screen;
    505. +        else if (screen_prop == EXTEND)
    506. +            extend_screen = rk_screen;
    507. +        else
    508. +            dev_err(&pdev->dev, "unknow screen prop: %d\n",
    509. +                screen_prop);
    510. +        rk_screen->prop = screen_prop;
    511. +        of_property_read_u32(screen_np, "native-mode", &rk_screen->native_mode);
    512. +        rk_screen->dev = &pdev->dev;
    513. +        ret = rk_fb_prase_timing_dt(screen_np, rk_screen);
    514. +        pr_info("%s screen timing parse %s\n",
    515. +            (screen_prop == PRMRY) ? "prmry" : "extend",
    516. +            ret ? "failed" : "success");
    517. +        ret = rk_disp_pwr_ctr_parse_dt(screen_np, rk_screen);
    518. +        pr_info("%s screen power ctrl parse %s\n",
    519. +            (screen_prop == PRMRY) ? "prmry" : "extend",
    520. +            ret ? "failed" : "success");
    521.      }
    522. -    ret = rk_fb_prase_timing_dt(np, rk_screen);
    523. -    dev_info(&pdev->dev, "rockchip screen probe %s\n",
    524. -                ret ? "failed" : "success");
    525. -    return ret;
    526. +   
    527. +    dev_info(&pdev->dev, "rockchip screen probe success\n");
    528. +    return 0;
    529. }

    530. static const struct of_device_id rk_screen_dt_ids[] = {
    531. diff --git a/kernel/drivers/video/rockchip/transmitter/rk32_dp.c b/kernel/drivers/video/rockchip/transmitter/rk32_dp.c
    532. index 2b3457c..624089e 100755
    533. --- a/kernel/drivers/video/rockchip/transmitter/rk32_dp.c
    534. +++ b/kernel/drivers/video/rockchip/transmitter/rk32_dp.c
    535. @@ -119,7 +119,7 @@ static int rk32_edp_init_edp(struct rk32_edp *edp)
    536.      struct rk_screen *screen = &edp->screen;
    537.      u32 val = 0;

    538. -    rk_fb_get_prmry_screen(screen);
    539. +    rk_fb_get_screen(screen, edp->prop);

    540.      if (cpu_is_rk3288()) {
    541.          if (screen->lcdc_id == 1)  /*select lcdc*/
    542. @@ -1712,17 +1712,21 @@ static int rk32_edp_probe(struct platform_device *pdev)
    543.      struct resource *res;
    544.      struct device_node *np = pdev->dev.of_node;
    545.      int ret;
    546. +    int prop;

    547.      if (!np) {
    548.          dev_err(&pdev->dev, "Missing device tree node.\n");
    549.          return -EINVAL;
    550.      }
    551. +    of_property_read_u32(np, "prop", &prop);
    552. +    pr_info("Use EDP as %s screen\n", (prop == PRMRY) ? "prmry" : "extend");

    553.      edp = devm_kzalloc(&pdev->dev, sizeof(struct rk32_edp), GFP_KERNEL);
    554.      if (!edp) {
    555.          dev_err(&pdev->dev, "no memory for state\n");
    556.          return -ENOMEM;
    557.      }
    558. +    edp->prop = prop;
    559.      edp->dev = &pdev->dev;
    560.      edp->video_info.h_sync_polarity    = 0;
    561.      edp->video_info.v_sync_polarity    = 0;
    562. @@ -1734,7 +1738,7 @@ static int rk32_edp_probe(struct platform_device *pdev)

    563.      edp->video_info.link_rate    = LINK_RATE_1_62GBPS;
    564.      edp->video_info.lane_count    = LANE_CNT4;
    565. -    rk_fb_get_prmry_screen(&edp->screen);
    566. +    rk_fb_get_screen(&edp->screen, prop);
    567.      if (edp->screen.type != SCREEN_EDP) {
    568.          dev_err(&pdev->dev, "screen is not edp!\n");
    569.          return -EINVAL;
    570. @@ -1809,7 +1813,7 @@ static int rk32_edp_probe(struct platform_device *pdev)
    571.      if (!support_uboot_display())
    572.          rk32_edp_clk_disable(edp);
    573.      rk32_edp = edp;
    574. -    rk_fb_trsm_ops_register(&trsm_edp_ops, SCREEN_EDP);
    575. +    rk_fb_trsm_ops_register(&trsm_edp_ops, prop);
    576. #if defined(CONFIG_DEBUG_FS)
    577.      edp->debugfs_dir = debugfs_create_dir("edp", NULL);
    578.      if (IS_ERR(edp->debugfs_dir)) {
    579. diff --git a/kernel/drivers/video/rockchip/transmitter/rk32_dp.h b/kernel/drivers/video/rockchip/transmitter/rk32_dp.h
    580. index 08347b5..8ec3e26 100755
    581. --- a/kernel/drivers/video/rockchip/transmitter/rk32_dp.h
    582. +++ b/kernel/drivers/video/rockchip/transmitter/rk32_dp.h
    583. @@ -566,6 +566,7 @@ struct rk32_edp {
    584.      bool clk_on;
    585.      bool edp_en;
    586.      struct dentry *debugfs_dir;
    587. +    int prop;
    588. };


    589. diff --git a/kernel/drivers/video/rockchip/transmitter/rk32_lvds.c b/kernel/drivers/video/rockchip/transmitter/rk32_lvds.c
    590. index 692e33e..6180504 100755
    591. --- a/kernel/drivers/video/rockchip/transmitter/rk32_lvds.c
    592. +++ b/kernel/drivers/video/rockchip/transmitter/rk32_lvds.c
    593. @@ -78,7 +78,7 @@ static int rk32_lvds_en(void)
    594.      u32 val = 0;
    595.      u32 delay_times = 20;
    596.      
    597. -    rk_fb_get_prmry_screen(screen);
    598. +    rk_fb_get_screen(screen, lvds->prop);

    599.      /* enable clk */
    600.      rk32_lvds_clk_enable(lvds);
    601. @@ -169,19 +169,22 @@ static int rk32_lvds_probe(struct platform_device *pdev)
    602.      struct rk32_lvds *lvds;
    603.      struct resource *res;
    604.      struct device_node *np = pdev->dev.of_node;
    605. +    int prop;

    606.      if (!np) {
    607.          dev_err(&pdev->dev, "Missing device tree node.\n");
    608.          return -EINVAL;
    609.      }

    610. +    of_property_read_u32(np, "prop", &prop);
    611. +    pr_info("Use LVDS as %s screen\n", (prop == PRMRY) ? "prmry":"extend");
    612.      lvds = devm_kzalloc(&pdev->dev, sizeof(struct rk32_lvds), GFP_KERNEL);
    613.      if (!lvds) {
    614.          dev_err(&pdev->dev, "no memory for state\n");
    615.          return -ENOMEM;
    616.      }
    617.      lvds->dev = &pdev->dev;
    618. -    rk_fb_get_prmry_screen(&lvds->screen);
    619. +    rk_fb_get_screen(&lvds->screen, prop);
    620.      if ((lvds->screen.type != SCREEN_RGB) &&
    621.          (lvds->screen.type != SCREEN_LVDS) &&
    622.          (lvds->screen.type != SCREEN_DUAL_LVDS) &&
    623. @@ -214,7 +217,8 @@ static int rk32_lvds_probe(struct platform_device *pdev)
    624.      }

    625.      rk32_lvds = lvds;
    626. -    rk_fb_trsm_ops_register(&trsm_lvds_ops,SCREEN_LVDS);
    627. +    lvds->prop = prop;
    628. +    rk_fb_trsm_ops_register(&trsm_lvds_ops, prop);
    629.      dev_info(&pdev->dev, "rk32 lvds driver probe success\n");

    630.      return 0;
    631. diff --git a/kernel/drivers/video/rockchip/transmitter/rk32_lvds.h b/kernel/drivers/video/rockchip/transmitter/rk32_lvds.h
    632. index 198311a..0a8dd45 100755
    633. --- a/kernel/drivers/video/rockchip/transmitter/rk32_lvds.h
    634. +++ b/kernel/drivers/video/rockchip/transmitter/rk32_lvds.h
    635. @@ -34,6 +34,7 @@ struct rk32_lvds {
    636.      struct clk              *pd;
    637.      struct rk_screen    screen;
    638.      bool            clk_on;
    639. +    int prop;
    640. };

    641. static int inline lvds_writel(struct rk32_lvds *lvds, u32 offset, u32 val)
    642. diff --git a/kernel/include/dt-bindings/rkfb/rk_fb.h b/kernel/include/dt-bindings/rkfb/rk_fb.h
    643. index b903f92..05f908f 100755
    644. --- a/kernel/include/dt-bindings/rkfb/rk_fb.h
    645. +++ b/kernel/include/dt-bindings/rkfb/rk_fb.h
    646. @@ -12,6 +12,7 @@
    647. #define NO_DUAL        0
    648. #define ONE_DUAL    1
    649. #define DUAL        2
    650. +#define DUAL_LCD    3

    651. #define OUT_P888            0    //24bit screen,connect to lcdc D0~D23
    652. #define OUT_P666            1    //18bit screen,connect to lcdc D0~D17
    653. @@ -74,6 +75,13 @@
    654. #define DISPLAY_POLICY_BOX    1
    655. #define DISPLAY_POLICY_BOX_TEMP    2

    656. +#define DEFAULT_MODE    0
    657. +#define HDMI_720P    0
    658. +#define HDMI_1080P    1
    659. +#define HDMI_2160P    2
    660. +#define NTSC_CVBS    3
    661. +#define PAL_CVBS    4
    662. +
    663. /*          lvds connect config      
    664.   *                                       
    665.   *              LVDS_8BIT_1    LVDS_8BIT_2     LVDS_8BIT_3     LVDS_6BIT
    666. diff --git a/kernel/include/linux/rk_fb.h b/kernel/include/linux/rk_fb.h
    667. index e17c49c..21beff7 100755
    668. --- a/kernel/include/linux/rk_fb.h
    669. +++ b/kernel/include/linux/rk_fb.h
    670. @@ -713,11 +713,12 @@ extern int rk_fb_register(struct rk_lcdc_driver *dev_drv,
    671.                  struct rk_lcdc_win *win, int id);
    672. extern int rk_fb_unregister(struct rk_lcdc_driver *dev_drv);
    673. extern struct rk_lcdc_driver *rk_get_lcdc_drv(char *name);
    674. -extern int rk_fb_get_extern_screen(struct rk_screen *screen);
    675. extern int rk_fb_get_prmry_screen( struct rk_screen *screen);
    676. -extern int rk_fb_set_prmry_screen(struct rk_screen *screen);
    677. +extern int rk_fb_get_screen(struct rk_screen *screen, int prop);
    678. +extern int rk_fb_set_screen(struct rk_screen *screen, int prop);
    679. extern u32 rk_fb_get_prmry_screen_pixclock(void);
    680. -extern int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv);
    681. +extern int rk_disp_pwr_ctr_parse_dt(struct device_node *np,
    682. +                    struct rk_screen *rk_screen);
    683. extern int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv);
    684. extern int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv);
    685. extern bool is_prmry_rk_lcdc_registered(void);
    686. diff --git a/kernel/include/linux/rk_screen.h b/kernel/include/linux/rk_screen.h
    687. index af0ffe7..9e57081 100755
    688. --- a/kernel/include/linux/rk_screen.h
    689. +++ b/kernel/include/linux/rk_screen.h
    690. @@ -61,12 +61,16 @@ struct overscan {
    691. *ft: the time need to display one frame time
    692. */
    693. struct rk_screen {
    694. +    struct device    *dev;
    695. +    int prop;
    696. +    struct list_head *pwrlist_head;
    697.      u16 type;
    698.      u16 lvds_format;
    699.      u16 face;
    700.      u16 color_mode;
    701.      u8 lcdc_id;   
    702.      u8 screen_id;
    703. +    int native_mode;
    704.      struct fb_videomode mode;
    705.      u32 post_dsp_stx;
    706.      u32 post_dsp_sty;
    707. @@ -144,7 +148,7 @@ struct rk29fb_info {
    708. };

    709. extern void set_lcd_info(struct rk_screen *screen, struct rk29lcd_info *lcd_info);
    710. -extern size_t get_fb_size(u8 reserved_fb);
    711. +extern size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen);

    712. extern void set_tv_info(struct rk_screen *screen);
    713. extern void set_hdmi_info(struct rk_screen *screen);
    复制代码
    (3)根据官方提供,打上 hardware 补丁
    1. diff --git a/hardware/rockchip/hwcomposer/rk_hwcomposer.cpp b/hardware/rockchip/hwcomposer/rk_hwcomposer.cpp
    2. index 9f4d7ce..a12bfca 100755
    3. --- a/hardware/rockchip/hwcomposer/rk_hwcomposer.cpp
    4. +++ b/hardware/rockchip/hwcomposer/rk_hwcomposer.cpp
    5. @@ -62,6 +62,7 @@ static int  hwc_device_close(struct hw_device_t * dev);

    6. int         hwc_sprite_replace(hwcContext * Context, hwc_display_contents_1_t * list);
    7. void*       hwc_control_3dmode_thread(void *arg);
    8. +int         hwc_parse_screen_info(int *outX, int *outY);

    9. void*   hotplug_try_register(void *arg);
    10. void    hotplug_get_resolution(int* w,int* h);
    11. @@ -9428,6 +9429,10 @@ int hotplug_get_config(int flag){
    12.      int outX = 0;
    13.      int outY = 0;
    14.      hotplug_parse_mode(&outX, &outY);
    15. +    if (hwc_get_int_property("ro.htg.force", "0"))
    16. +        hwc_parse_screen_info(&outX, &outY);
    17. +    else
    18. +        hotplug_parse_mode(&outX, &outY);
    19.      info.xres = outX;
    20.      info.yres = outY;
    21.      info.yres_virtual = info.yres * 3;
    22. @@ -9723,6 +9728,29 @@ OnError:

    23. }

    24. +int hwc_parse_screen_info(int *outX, int *outY)
    25. +{
    26. +    char buf[100];
    27. +    int width = 0;
    28. +    int height = 0;
    29. +    int fdExternal = -1;
    30. +    fdExternal = open("/sys/class/graphics/fb4/screen_info", O_RDONLY);
    31. +    if(fdExternal < 0){
    32. +        ALOGE("hotplug_get_config:open fb screen_info error,cvbsfd=%d",fdExternal);
    33. +        return -errno;
    34. +    }
    35. +    if(read(fdExternal,buf,sizeof(buf)) < 0){
    36. +        ALOGE("error reading fb screen_info: %s", strerror(errno));
    37. +        return -1;
    38. +    }
    39. +    close(fdExternal);
    40. +    sscanf(buf,"xres:%d yres:%d",&width,&height);
    41. +    ALOGD("hotplug_get_config:width=%d,height=%d",width,height);
    42. +    *outX = width;
    43. +    *outY = height;
    44. +    return 0;
    45. +}
    46. +
    47. int hotplug_parse_mode(int *outX, int *outY)
    48. {
    49.     int fd = open("/sys/class/display/HDMI/mode", O_RDONLY);
    50. @@ -9894,7 +9922,12 @@ void *hotplug_try_register(void *arg)
    51.      if(getHdmiMode() == 1){
    52.          handle_hotplug_event(1, 6);
    53.          ALOGI("hotplug_try_register at line = %d",__LINE__);
    54. -    }else{
    55. +    } else if (hwc_get_int_property("ro.htg.force", "0")) {
    56. +        hotplug_free_dimbuffer();
    57. +        hotplug_get_config(0);
    58. +        handle_hotplug_event(1, 6);
    59. +        ALOGI("hotplug_try_register at line = %d",__LINE__);
    60. +    } else {
    61. #if (defined(RK3368_BOX) || defined(RK3288_BOX))
    62. #if RK3288_BOX
    63.          if(context->mLcdcNum == 1){
    复制代码
    (4)根据官方提供,打上 framework 补丁

    1. diff --git a/frameworks/base/api/current.txt b/frameworks/base/api/current.txt
    2. index c537823..c1cc9a6 100755
    3. --- a/frameworks/base/api/current.txt
    4. +++ b/frameworks/base/api/current.txt
    5. @@ -3332,7 +3332,9 @@ package android.app {
    6.      method public boolean isImmersive();
    7.      method public boolean isTaskRoot();
    8.      method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
    9. -    method public boolean moveTaskToBack(boolean);
    10. +    method public void moveAppToDisplay(int);
    11. +    method public void moveExtendDisplay();
    12. +    method public boolean moveTaskToBack(boolean);
    13.      method public boolean navigateUpTo(android.content.Intent);
    14.      method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
    15.      method public void onActionModeFinished(android.view.ActionMode);
    16. @@ -3474,7 +3476,8 @@ package android.app {
    17.      method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
    18.      method public void stopLockTask();
    19.      method public deprecated void stopManagingCursor(android.database.Cursor);
    20. -    method public void takeKeyEvents(boolean);
    21. +    method public void syncDualDisplay();
    22. +    method public void takeKeyEvents(boolean);
    23.      method public void triggerSearch(java.lang.String, android.os.Bundle);
    24.      method public void unregisterForContextMenu(android.view.View);
    25.      field public static final int DEFAULT_KEYS_DIALER = 1; // 0x1
    26. @@ -7206,7 +7209,8 @@ package android.content {
    27.      method public abstract deprecated void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
    28.      method public abstract deprecated void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    29.      method public abstract deprecated void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    30. -    method public abstract void setTheme(int);
    31. +    method public abstract void setDualScreen(boolean);
    32. +    method public abstract void setTheme(int);
    33.      method public abstract deprecated void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
    34.      method public abstract deprecated void setWallpaper(java.io.InputStream) throws java.io.IOException;
    35.      method public abstract void startActivities(android.content.Intent[]);
    36. @@ -7371,7 +7375,8 @@ package android.content {
    37.      method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
    38.      method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    39.      method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    40. -    method public void setTheme(int);
    41. +    method public void setDualScreen(boolean);
    42. +    method public void setTheme(int);
    43.      method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
    44.      method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
    45.      method public void startActivities(android.content.Intent[]);
    46. @@ -29564,7 +29569,8 @@ package android.test.mock {
    47.      method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
    48.      method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    49.      method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    50. -    method public void setTheme(int);
    51. +    method public void setDualScreen(boolean);
    52. +    method public void setTheme(int);
    53.      method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
    54.      method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
    55.      method public void startActivities(android.content.Intent[]);
    56. @@ -34808,7 +34814,9 @@ package android.view {
    57.      method public abstract boolean isFloating();
    58.      method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
    59.      method public final void makeActive();
    60. -    method protected abstract void onActive();
    61. +    method public abstract void moveAppToDisplay(int);
    62. +    method public abstract void moveExtendDisplay();
    63. +    method protected abstract void onActive();
    64.      method public abstract void onConfigurationChanged(android.content.res.Configuration);
    65.      method public abstract void openPanel(int, android.view.KeyEvent);
    66.      method public abstract android.view.View peekDecorView();
    67. @@ -34875,7 +34883,8 @@ package android.view {
    68.      method public abstract boolean superDispatchKeyShortcutEvent(android.view.KeyEvent);
    69.      method public abstract boolean superDispatchTouchEvent(android.view.MotionEvent);
    70.      method public abstract boolean superDispatchTrackballEvent(android.view.MotionEvent);
    71. -    method public abstract void takeInputQueue(android.view.InputQueue.Callback);
    72. +    method public abstract void syncDualDisplay();
    73. +    method public abstract void takeInputQueue(android.view.InputQueue.Callback);
    74.      method public abstract void takeKeyEvents(boolean);
    75.      method public abstract void takeSurface(android.view.SurfaceHolder.Callback2);
    76.      method public abstract void togglePanel(int, android.view.KeyEvent);
    77. diff --git a/frameworks/base/api/system-current.txt b/frameworks/base/api/system-current.txt
    78. index ef86f85..0a1feda 100755
    79. --- a/frameworks/base/api/system-current.txt
    80. +++ b/frameworks/base/api/system-current.txt
    81. @@ -3414,7 +3414,9 @@ package android.app {
    82.      method public boolean isTaskRoot();
    83.      method public boolean isVoiceInteraction();
    84.      method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
    85. -    method public boolean moveTaskToBack(boolean);
    86. +    method public void moveAppToDisplay(int);
    87. +    method public void moveExtendDisplay();
    88. +    method public boolean moveTaskToBack(boolean);
    89.      method public boolean navigateUpTo(android.content.Intent);
    90.      method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
    91.      method public void onActionModeFinished(android.view.ActionMode);
    92. @@ -3557,7 +3559,8 @@ package android.app {
    93.      method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
    94.      method public void stopLockTask();
    95.      method public deprecated void stopManagingCursor(android.database.Cursor);
    96. -    method public void takeKeyEvents(boolean);
    97. +    method public void syncDualDisplay();
    98. +    method public void takeKeyEvents(boolean);
    99.      method public void triggerSearch(java.lang.String, android.os.Bundle);
    100.      method public void unregisterForContextMenu(android.view.View);
    101.      field public static final int DEFAULT_KEYS_DIALER = 1; // 0x1
    102. @@ -7444,7 +7447,8 @@ package android.content {
    103.      method public abstract deprecated void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
    104.      method public abstract deprecated void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    105.      method public abstract deprecated void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    106. -    method public abstract void setTheme(int);
    107. +    method public abstract void setDualScreen(boolean);
    108. +    method public abstract void setTheme(int);
    109.      method public abstract deprecated void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
    110.      method public abstract deprecated void setWallpaper(java.io.InputStream) throws java.io.IOException;
    111.      method public abstract void startActivities(android.content.Intent[]);
    112. @@ -7615,7 +7619,8 @@ package android.content {
    113.      method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
    114.      method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    115.      method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    116. -    method public void setTheme(int);
    117. +    method public void setDualScreen(boolean);
    118. +    method public void setTheme(int);
    119.      method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
    120.      method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
    121.      method public void startActivities(android.content.Intent[]);
    122. @@ -31798,7 +31803,8 @@ package android.test.mock {
    123.      method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
    124.      method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    125.      method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
    126. -    method public void setTheme(int);
    127. +    method public void setDualScreen(boolean);
    128. +    method public void setTheme(int);
    129.      method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
    130.      method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
    131.      method public void startActivities(android.content.Intent[]);
    132. @@ -37042,6 +37048,8 @@ package android.view {
    133.      method public abstract boolean isFloating();
    134.      method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
    135.      method public final void makeActive();
    136. +    method public abstract void moveAppToDisplay(int);
    137. +    method public abstract void moveExtendDisplay();
    138.      method protected abstract void onActive();
    139.      method public abstract void onConfigurationChanged(android.content.res.Configuration);
    140.      method public abstract void openPanel(int, android.view.KeyEvent);
    141. @@ -37110,6 +37118,7 @@ package android.view {
    142.      method public abstract boolean superDispatchKeyShortcutEvent(android.view.KeyEvent);
    143.      method public abstract boolean superDispatchTouchEvent(android.view.MotionEvent);
    144.      method public abstract boolean superDispatchTrackballEvent(android.view.MotionEvent);
    145. +    method public abstract void syncDualDisplay();
    146.      method public abstract void takeInputQueue(android.view.InputQueue.Callback);
    147.      method public abstract void takeKeyEvents(boolean);
    148.      method public abstract void takeSurface(android.view.SurfaceHolder.Callback2);
    149. diff --git a/frameworks/base/core/java/android/app/Activity.java b/frameworks/base/core/java/android/app/Activity.java
    150. index ce65cf3..5159661 100755
    151. --- a/frameworks/base/core/java/android/app/Activity.java
    152. +++ b/frameworks/base/core/java/android/app/Activity.java
    153. @@ -6495,4 +6495,22 @@ public class Activity extends ContextThemeWrapper
    154.           */
    155.          public void onTranslucentConversionComplete(boolean drawComplete);
    156.      }
    157. +
    158. +    public void moveAppToDisplay(int id) {
    159. +    if (mWindow != null) {
    160. +            mWindow.moveAppToDisplay(id);
    161. +        }
    162. +    }
    163. +
    164. +    public void syncDualDisplay() {
    165. +    if (mWindow != null) {
    166. +        mWindow.syncDualDisplay();
    167. +    }
    168. +    }
    169. +
    170. +    public void moveExtendDisplay() {
    171. +    if (mWindow != null) {
    172. +        mWindow.moveExtendDisplay();
    173. +    }
    174. +    }
    175. }
    176. diff --git a/frameworks/base/core/java/android/app/ContextImpl.java b/frameworks/base/core/java/android/app/ContextImpl.java
    177. index 6c9c804..ebee424 100755
    178. --- a/frameworks/base/core/java/android/app/ContextImpl.java
    179. +++ b/frameworks/base/core/java/android/app/ContextImpl.java
    180. @@ -122,6 +122,7 @@ import android.os.SystemVibrator;
    181. import android.os.UserManager;
    182. import android.os.storage.IMountService;
    183. import android.os.storage.StorageManager;
    184. +import android.provider.Settings;
    185. import android.print.IPrintManager;
    186. import android.print.PrintManager;
    187. import android.service.fingerprint.IFingerprintService;
    188. @@ -2224,6 +2225,32 @@ class ContextImpl extends Context {
    189.          return mDisplayAdjustments;
    190.      }

    191. +    @Override
    192. +    public void setDualScreen(boolean enable) {
    193. +
    194. +    int value = 0;
    195. +    if (enable) {
    196. +        value = 1;
    197. +    } else {
    198. +        Settings.System.putInt(getContentResolver(), Settings.System.DUAL_SCREEN_ICON_USED, 0);
    199. +    }
    200. +    Settings.System.putInt(getContentResolver(), Settings.System.DUAL_SCREEN_MODE, value);
    201. +
    202. +    try {
    203. +                IActivityManager am = ActivityManagerNative.getDefault();
    204. +                Configuration config = am.getConfiguration();
    205. +
    206. +                // Will set userSetLocale to indicate this isn't some passing default - the user
    207. +                // wants this remembered
    208. +                config.setDualScreenFlag(enable);
    209. +
    210. +                am.updateConfiguration(config);
    211. +
    212. +        } catch (RemoteException e) {
    213. +                // Intentionally left blank
    214. +         }
    215. +    }
    216. +
    217.      private File getDataDirFile() {
    218.          if (mPackageInfo != null) {
    219.              return mPackageInfo.getDataDirFile();
    220. diff --git a/frameworks/base/core/java/android/content/Context.java b/frameworks/base/core/java/android/content/Context.java
    221. index 7028dfe..25268fc 100755
    222. --- a/frameworks/base/core/java/android/content/Context.java
    223. +++ b/frameworks/base/core/java/android/content/Context.java
    224. @@ -3460,4 +3460,6 @@ public abstract class Context {
    225.      public boolean isRestricted() {
    226.          return false;
    227.      }
    228. +   
    229. +    public abstract void setDualScreen(boolean enable);
    230. }
    231. diff --git a/frameworks/base/core/java/android/content/ContextWrapper.java b/frameworks/base/core/java/android/content/ContextWrapper.java
    232. index cfae1cf..4ecbea6 100755
    233. --- a/frameworks/base/core/java/android/content/ContextWrapper.java
    234. +++ b/frameworks/base/core/java/android/content/ContextWrapper.java
    235. @@ -710,4 +710,9 @@ public class ContextWrapper extends Context {
    236.      public DisplayAdjustments getDisplayAdjustments(int displayId) {
    237.          return mBase.getDisplayAdjustments(displayId);
    238.      }
    239. +   
    240. +    @Override
    241. +    public void setDualScreen(boolean enable) {
    242. +        mBase.setDualScreen(enable);
    243. +    }
    244. }
    245. diff --git a/frameworks/base/core/java/android/view/IWindowSession.aidl b/frameworks/base/core/java/android/view/IWindowSession.aidl
    246. index 3fb19c2..3192265 100755
    247. --- a/frameworks/base/core/java/android/view/IWindowSession.aidl
    248. +++ b/frameworks/base/core/java/android/view/IWindowSession.aidl
    249. @@ -232,4 +232,7 @@ interface IWindowSession {
    250.      void updatePositionAndSize(IWindow window,int x,int y,int widht,int height);

    251.      void setOnlyShowInExtendDisplay(IWindow window,int transit);
    252. +   
    253. +    void moveAppToDisplay(IWindow window, int id);
    254. +    void syncDualDisplay();
    255. }
    256. diff --git a/frameworks/base/core/java/android/view/Window.java b/frameworks/base/core/java/android/view/Window.java
    257. index f74d92c..03744d3 100755
    258. --- a/frameworks/base/core/java/android/view/Window.java
    259. +++ b/frameworks/base/core/java/android/view/Window.java
    260. @@ -1896,5 +1896,7 @@ public abstract class Window {
    261.       */
    262.      public abstract void setNavigationBarColor(int color);

    263. -
    264. +    public abstract void moveAppToDisplay(int id);
    265. +    public abstract void syncDualDisplay();
    266. +    public abstract void moveExtendDisplay();
    267. }
    268. diff --git a/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
    269. index 5333c35..c309cc3 100755
    270. --- a/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
    271. +++ b/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
    272. @@ -5136,5 +5136,24 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
    273.          }
    274.      }
    275.       
    276. +    @Override
    277. +    public void moveAppToDisplay(int id) {
    278. +        try {
    279. +            mDecor.getRootWindowSession().moveAppToDisplay(mDecor.getWindow(), id);
    280. +        } catch (RemoteException ex) {}
    281. +    }

    282. +    @Override
    283. +    public void syncDualDisplay() {
    284. +        try {
    285. +                mDecor.getRootWindowSession().syncDualDisplay();
    286. +        } catch (RemoteException ex) {}
    287. +    }
    288. +
    289. +    @Override
    290. +    public void moveExtendDisplay() {
    291. +        try {
    292. +            mDecor.getRootWindowSession().setOnlyShowInExtendDisplay(mDecor.getWindow(),-1);
    293. +        } catch (RemoteException ex) {}
    294. +    }
    295. }
    296. diff --git a/frameworks/base/services/core/java/com/android/server/wm/Session.java b/frameworks/base/services/core/java/com/android/server/wm/Session.java
    297. index ec92751..0f70d64 100755
    298. --- a/frameworks/base/services/core/java/com/android/server/wm/Session.java
    299. +++ b/frameworks/base/services/core/java/com/android/server/wm/Session.java
    300. @@ -216,6 +216,14 @@ final class Session extends IWindowSession.Stub
    301.      public void setOnlyShowInExtendDisplay(IWindow window,int transit){
    302.          mService.setOnlyShowInExtendDisplay(this, window,transit);
    303.      }   
    304. +
    305. +    public void moveAppToDisplay(IWindow window, int id) {
    306. +        mService.moveAppToDisplay(this, window, id);
    307. +    }
    308. +
    309. +    public void syncDualDisplay() {
    310. +        mService.syncDualDisplay();
    311. +    }

    312.      public void performDeferredDestroy(IWindow window) {
    313.          mService.performDeferredDestroyWindow(this, window);
    314. diff --git a/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java b/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    315. index 37281ca..433a161 100755
    316. --- a/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    317. +++ b/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    318. @@ -10050,6 +10050,7 @@ public class WindowManagerService extends IWindowManager.Stub
    319.          public static final int SET_MULTIWINDOW_MODE_ACTION = 41;
    320.          public static final int DO_TASK_DISPLAY_CHANGED = 42;
    321.          public static final int MULTIWINDOW_MOVE_BACK_ACTION = 43;
    322. +        public static final int MOVE_APP_TO_DISPLAY = 44;
    323.          @Override
    324.          public void handleMessage(Message msg) {
    325.              if (DEBUG_WINDOW_TRACE) {
    326. @@ -10621,6 +10622,11 @@ public class WindowManagerService extends IWindowManager.Stub
    327.                      } catch (RemoteException e) {
    328.                      }
    329.                      break;
    330. +                case MOVE_APP_TO_DISPLAY:
    331. +                    synchronized (mWindowMap) {
    332. +                        moveAppToIdDisplay(msg.arg1, msg.arg2, (int)msg.obj);
    333. +                    }
    334. +                    break;
    335.              }
    336.              if (DEBUG_WINDOW_TRACE) {
    337.                  Slog.v(TAG, "handleMessage: exit");
    338. @@ -14493,6 +14499,216 @@ if(mCurConfiguration.enableMultiWindow()&&false){
    339.      }
    340.      Binder.restoreCallingIdentity(origId);
    341.      }
    342. +   
    343. +    public void moveAppToDisplay(Session session, IWindow client, int displayid) {
    344. +        long origId = Binder.clearCallingIdentity();
    345. +            synchronized(mWindowMap){
    346. +                    if(mDisplayContents == null || mDisplayContents.size() <= 1){
    347. +                            return;
    348. +                    }
    349. +                    final int displayCount = mDisplayContents.size();
    350. +                    DisplayContent defaultContent = getDefaultDisplayContentLocked();
    351. +                    int displayId = 0;
    352. +            boolean hasTargetDisplay = false;
    353. +                    for(int i = 0; i < displayCount;i++){
    354. +                            final DisplayContent content = mDisplayContents.valueAt(i);
    355. +                                displayId = content.getDisplayId();
    356. +                if (displayId == displayid) {
    357. +                    hasTargetDisplay = true;
    358. +                                    break;
    359. +                }
    360. +                    }
    361. +                    if(!hasTargetDisplay){
    362. +                            return;
    363. +                    }
    364. +                    if(!okToDisplay()){
    365. +                            return;
    366. +                    }
    367. +                    WindowState current = windowForClientLocked(session, client, false);
    368. +                    if(isHomeWindow(current)){
    369. +                            return;
    370. +                    }
    371. +                    AppWindowToken wtoken = current.mAppToken;
    372. +                    if(wtoken == null){
    373. +                            return;
    374. +                    }
    375. +
    376. +            if(current.getDisplayId() == displayid) return;
    377. +
    378. +                    Settings.System.putInt(mContext.getContentResolver(),
    379. +                            Settings.System.DUAL_SCREEN_ICON_USED, 1);
    380. +                    int groupId = wtoken.groupId;
    381. +                    mH.sendMessage(mH.obtainMessage(H.MOVE_APP_TO_DISPLAY, groupId, displayid, current.getDisplayId()));
    382. +            }
    383. +            Binder.restoreCallingIdentity(origId);
    384. +    }
    385. +
    386. +    public void syncDualDisplay() {
    387. +        updateDisplayShowSynchronization();
    388. +    }
    389. +
    390. +    // case as follow:
    391. +    // 1. mast screen -> external screen
    392. +    // 2. external screen -> mast screen
    393. +    // 3. external screen -> external screen
    394. +    private void moveAppToIdDisplay(int groupId, int displayid, int currentid) {
    395. +        long origId = Binder.clearCallingIdentity();
    396. +        int curMoveTaskId = -1;
    397. +        synchronized(mWindowMap){
    398. +                if(mDisplayContents == null || mDisplayContents.size() <= 1) {
    399. +                        return;
    400. +                }
    401. +        DisplayContent defaultContent = getDefaultDisplayContentLocked();
    402. +        int defaultDisplayId = defaultContent.getDisplayId();
    403. +        final int displayCount = mDisplayContents.size();
    404. +        int displayId = 0;
    405. +        DisplayContent currentContent = null;
    406. +        DisplayContent targetContent = null;
    407. +        for(int i = 0; i < displayCount;i++) {
    408. +                        final DisplayContent content = mDisplayContents.valueAt(i);
    409. +                        if (content.getDisplayId() == displayid) {
    410. +                                targetContent = content;
    411. +                        }
    412. +            if (content.getDisplayId() == currentid) {
    413. +                currentContent = content;
    414. +            }
    415. +                }
    416. +
    417. +        if (targetContent == null) return;
    418. +        if (currentContent == null) return;
    419. +
    420. +        if(!okToDisplay()){
    421. +                        return;
    422. +                }
    423. +
    424. +        WindowState win = null;
    425. +                WindowList windows = currentContent.getWindowList();
    426. +        try {
    427. +                        SurfaceControl.openTransaction();
    428. +            if (displayid == defaultDisplayId) {
    429. +                int max = 1;
    430. +                    int countOfTwoScreen = 0;
    431. +                WindowList defaultWindows = defaultContent.getWindowList();
    432. +                HashMap<Integer,AppWindowToken> visibleAppsOfTwoScreen = new HashMap<Integer,AppWindowToken>();
    433. +                ArrayList<AppWindowToken> pendingRemoveOfTwoScreen = new ArrayList<AppWindowToken>();
    434. +                for(int j = 0; j < windows.size(); j++) {
    435. +                    win = windows.get(j);
    436. +                    if (win == null) continue;
    437. +                    if (ignoreWindow(win,false) || win.mAppToken == null) continue;
    438. +                    if(isHomeWindow(win)) break;
    439. +                    if(!win.isDefaultDisplay()) {
    440. +                        AppWindowToken tk = win.mAppToken;
    441. +                        if(!visibleAppsOfTwoScreen.containsKey(tk.groupId)){
    442. +                                            visibleAppsOfTwoScreen.put(tk.groupId, tk);
    443. +                            if (tk.groupId == groupId) {
    444. +                                pendingRemoveOfTwoScreen.add(tk);
    445. +                            }
    446. +                        }
    447. +                        /*if(!visibleAppsOfTwoScreen.containsKey(tk.groupId)){
    448. +                                            visibleAppsOfTwoScreen.put(tk.groupId, tk);
    449. +                                            countOfTwoScreen++;
    450. +                                            if(countOfTwoScreen > max){
    451. +                                                    pendingRemoveOfTwoScreen.add(tk);
    452. +                                            }
    453. +                                    }*/
    454. +                    }
    455. +                }
    456. +                if(pendingRemoveOfTwoScreen.size() > 0){
    457. +                    for(int k =0;k < pendingRemoveOfTwoScreen.size(); k++){
    458. +                        int removeTaskId = pendingRemoveOfTwoScreen.get(k).groupId;
    459. +                        for(int m = 0; m < windows.size(); m++){
    460. +                            WindowState ws = windows.get(m);
    461. +                            int mGroupId = ws.mAppToken.groupId;
    462. +                            if (mGroupId == removeTaskId) {
    463. +                                final ArrayList<TaskStack> stacks = defaultContent.getStacks();
    464. +                                final int numStacks = stacks.size();
    465. +                                int stackNdx = 1;
    466. +                                final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
    467. +                                final int numTasks = tasks.size();
    468. +                                for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
    469. +                                                                if (tasks.get(taskNdx).taskId != ws.taskId)  continue;
    470. +                                                                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    471. +                                                                if (!tokens.contains(ws.mAppToken)) { // wrong happened
    472. +                                                                        tasks.get(taskNdx).addAppToken(tokens.size(), ws.mAppToken);
    473. +                                                                }
    474. +                                                                //break;
    475. +                                                        }
    476. +                                windows.remove(ws);
    477. +                                ws.mDisplayContent = defaultContent;
    478. +                                                    if(ws.mWinAnimator != null){
    479. +                                                            int layerStack = defaultContent.getDisplay().getLayerStack();
    480. +                                                            if(ws.mWinAnimator.mSurfaceControl != null){
    481. +                                                                    ws.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);
    482. +                                                            }
    483. +                                                    }
    484. +                                                    defaultWindows.add(ws);
    485. +                            }
    486. +                        }
    487. +                    }
    488. +                }
    489. +            } else if (currentid == defaultDisplayId) {
    490. +                WindowList targetDisplayAddList = new WindowList();
    491. +                            WindowList targetDisplayWindows = targetContent.getWindowList();
    492. +                for(int i=windows.size()-1; i >= 0; i--){
    493. +                    win = windows.get(i);
    494. +                                    if(win == null){
    495. +                                            continue;
    496. +                                    }
    497. +                                    if (win.mAppToken == null){
    498. +                                            continue;
    499. +                                    }
    500. +                    int mGroupId = win.mAppToken.groupId;
    501. +                                    if(mGroupId == groupId){
    502. +
    503. +                                            final ArrayList<TaskStack> stacks = currentContent.getStacks();
    504. +                                            final int numStacks = stacks.size();
    505. +                                            int stackNdx = 1;
    506. +                        final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
    507. +
    508. +                        final int numTasks = tasks.size();
    509. +                        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
    510. +                            if (tasks.get(taskNdx).taskId != win.taskId) continue;
    511. +                            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    512. +                            for (int n = 0; n<tokens.size();) {
    513. +                                AppWindowToken awt = tokens.get(n);
    514. +                                if (tokens.contains(awt) || awt.removed) {  // no useful
    515. +                                    tasks.get(taskNdx).removeAppToken(awt);
    516. +                                }
    517. +                            }
    518. +                        }
    519. +                                            windows.remove(win);
    520. +                                            win.mDisplayContent = targetContent;
    521. +
    522. +                                            if(win.mWinAnimator != null){
    523. +                                                    int layerStack = targetContent.getDisplay().getLayerStack();
    524. +                                                    if(win.mWinAnimator.mSurfaceControl!= null){
    525. +                                                            win.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);
    526. +                                                    }
    527. +                                            }
    528. +                                            targetDisplayAddList.add(0, win);
    529. +                                    }
    530. +                }
    531. +                targetDisplayWindows.addAll(targetDisplayAddList);
    532. +            } else {
    533. +                // external screen -> external screen
    534. +            }
    535. +
    536. +            for (int i = 0; i < displayCount; i++) {
    537. +                                final DisplayContent content = mDisplayContents.valueAt(i);
    538. +                                assignLayersLocked(content.getWindowList());
    539. +                                content.layoutNeeded = true;
    540. +                        }
    541. +            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false);
    542. +                        mAppTransition.setReady();
    543. +                        performLayoutAndPlaceSurfacesLocked();
    544. +            
    545. +                }finally {
    546. +                        SurfaceControl.closeTransaction();
    547. +                }
    548. +
    549. +        }
    550. +        Binder.restoreCallingIdentity(origId);
    551. +    }

    552.      public void moveWindowToSecondDisplay() {
    553.          int topId = -100;
    554. diff --git a/frameworks/base/test-runner/src/android/test/mock/MockContext.java b/frameworks/base/test-runner/src/android/test/mock/MockContext.java
    555. index 3378872..cd24654 100755
    556. --- a/frameworks/base/test-runner/src/android/test/mock/MockContext.java
    557. +++ b/frameworks/base/test-runner/src/android/test/mock/MockContext.java
    558. @@ -643,4 +643,9 @@ public class MockContext extends Context {
    559.      public File[] getExternalMediaDirs() {
    560.          throw new UnsupportedOperationException();
    561.      }
    562. +   
    563. +    @Override
    564. +    public void setDualScreen(boolean enable) {
    565. +        throw new UnsupportedOperationException();
    566. +    }
    567. }
    复制代码
    (5)官方提供的补丁打完了,但是此时编译可能会报错,如下:
    1. cts/tests/tests/view/src/android/view/cts/WindowTest.java:846: error: WindowTest.MockWindow is not abstract and does not override abstract method moveExtendDisplay() in Window
    2. public class MockWindow extends Window {
    3. ^
    4. Note: Some input files use or override a deprecated API.
    5. Note: Recompile with -Xlint:deprecation for details.
    6. 1 error
    7. make: *** [out/target/common/obj/APPS/CtsViewTestCases_intermediates/classes-full-debug.jar] Error 41
    8. make: *** Waiting for unfinished jobs....
    9. Note: Some input files use or override a deprecated API.
    10. Note: Recompile with -Xlint:deprecation for details.
    11. Note: Some input files use unchecked or unsafe operations.
    12. Note: Recompile with -Xlint:unchecked for details.
    13. Note: Some input files use or override a deprecated API.
    14. Note: Recompile with -Xlint:deprecation for details.
    15. Note: Some input files use unchecked or unsafe operations.
    16. Note: Recompile with -Xlint:unchecked for details.
    17. Warning: AndroidManifest.xml already defines minSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest.
    18. Warning: AndroidManifest.xml already defines targetSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest.

    19. #### make failed to build some targets (03:55 (mm:ss)) ####
    复制代码
    根据编译错误提示,需要修改 cts/tests/tests/view/src/android/view/cts/WindowTest.java 文件。
    1. diff --git a/cts/tests/tests/view/src/android/view/cts/WindowTest.java b/cts/tests/tests/view/src/android/view/cts/WindowTest.java
    2. index 3c5386d..8732ae7 100755
    3. --- a/cts/tests/tests/view/src/android/view/cts/WindowTest.java
    4. +++ b/cts/tests/tests/view/src/android/view/cts/WindowTest.java
    5. @@ -998,6 +998,19 @@ public class WindowTest extends ActivityInstrumentationTestCase2<WindowCtsActivi
    6.          }

    7.          @Override
    8. +        public void moveAppToDisplay(int id) {
    9. +        }
    10. +
    11. +        @Override
    12. +        public void syncDualDisplay() {
    13. +        }
    14. +
    15. +        @Override
    16. +        public void moveExtendDisplay() {
    17. +        }
    18. +
    19. +
    20. +        @Override
    21.          public void setDefaultWindowFormat(int format) {
    22.              super.setDefaultWindowFormat(format);
    23.          }
    复制代码
    (6)此时可以编译成功,在屏参正确的前提下,主屏显示正常,副屏出现花屏,需要在 system.prop 里添加属性 ro.htg.force=1。
    1. diff --git a/device/rockchip/rk3288/system.prop b/device/rockchip/rk3288/system.prop
    2. index 26a2b09..c4f2c3d 100755
    3. --- a/device/rockchip/rk3288/system.prop
    4. +++ b/device/rockchip/rk3288/system.prop
    5. @@ -12,6 +12,7 @@ rild.libpath=/system/lib/libril-rk29-dataonly.so
    6. rild.libargs=-d /dev/ttyACM0
    7. persist.tegra.nvmmlite = 1
    8. ro.audio.monitorOrientation=true
    9. +ro.htg.force=1

    10. #NFC
    11. debug.nfc.fw_download=false
    复制代码
    此时大功告成,双屏可以正常显示,也可以实现双屏异显。

    如果 lcd 出现重复性黑屏亮屏,找到对应的屏参文件,在正常范围内调节频率 clk 值即可。
    1. display-timings {
    2.                         native-mode = <&ee101ia>;
    3.                         ee101ia: timing0 {
    4.                 screen-type = <SCREEN_DUAL_LVDS>;
    5.                 lvds-format = <LVDS_8BIT_1>;
    6.                 out-face    = <OUT_P888>;
    7.                 color-mode = <COLOR_RGB>;
    8.                 // 调节 lcd 频率
    9.                 clock-frequency = <148500000>;
    10.                 hactive = <1920>;
    11.                 vactive = <1080>;
    复制代码

    本文作者 LeeAaron
    来源 博客园





    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条



    手机版|小黑屋|与非网

    GMT+8, 2025-1-12 23:41 , Processed in 0.109636 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.