Xiaofei He

320 papers A* 119A 3C 2Misc 1Journal 171Unranked 21
YearRankTypeTitle / Venue / Authors
2026 A* conf
WWW
Yaming Yang, Zhe Wang, Ziyu Guan, Wei Zhao, Weigang Lu, Xinyan Huang, Jiangtao Cui, Xiaofei He
2026 J jnl
CoRR
Yang Yang, Tianyi Zhang, Wei Huang, Jinwei Chen, Boxi Wu, Xiaofei He, Deng Cai, Bo Li, Peng-Tao Jiang
2026 A* conf
AAAI
Weihang Pan, Zhengxu Yu, Yong Wu, Xun Liang, Zhongming Jin, Qiang Fu, Penghui Shang, Binbin Lin, Xiaofei He, Jieping Ye
2026 J jnl
CoRR
Zhiyuan Shi, Qibo Qiu, Feng Xue, Zhonglin Jiang, Li Yu, Jian Jiang, Xiaofei He, Wenxiao Wang
2026 J jnl
CoRR
Yibo Zhao, Hengjia Li, Xiaofei He, Boxi Wu
2025 J jnl
CoRR
Yang Yang, Siming Zheng, Jinwei Chen, Boxi Wu, Xiaofei He, Deng Cai, Bo Li, Peng-Tao Jiang
2025 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Tu Zheng, Yifei Huang, Yang Liu, Binbin Lin, Zheng Yang, Deng Cai, Xiaofei He
2025 J jnl
IEEE Trans. Intell. Transp. Syst.
Weihang Pan, Binbin Lin, Yafei Wang, Zhengxu Yu, Xinkui Zhao, Xiaofei He, Jieping Ye
2025 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Ziyu Guan, Wanqing Zhao, Hongmin Liu, Yuta Nakashima, Noboru Babaguchi, Xiaofei He
2025 A* conf
ICLR
Honghui Yang, Di Huang, Wei Yin, Chunhua Shen, Haifeng Liu, Xiaofei He, Binbin Lin, Wanli Ouyang, Tong He
2025 J jnl
CoRR
Haoran Cheng, Qide Dong, Liang Peng, Zhizhou Sha, Weiguo Feng, Jinghui Xie, Zhao Song, Shilei Wen, Xiaofei He, Boxi Wu
2025 J jnl
IEEE Access
Long Wei, Zhengxu Yu, Zhongming Jin, Liang Xie, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2025 A* conf
ICLR
Sinan Fan, Liang Xie, Chen Shen, Ge Teng, Xiaosong Yuan, Xiaofeng Zhang, Chenxi Huang, Wenxiao Wang, Xiaofei He, Jieping Ye
2025 J jnl
CoRR
Sinan Fan, Liang Xie, Chen Shen, Ge Teng, Xiaosong Yuan, Xiaofeng Zhang, Chenxi Huang, Wenxiao Wang, Xiaofei He, Jieping Ye
2025 J jnl
IEEE Trans. Knowl. Data Eng.
Weihang Pan, Minghao Chen, Binbin Lin, Yafei Wang, Xinkui Zhao, Xiaofei He, Jieping Ye
2025 J jnl
IEEE Trans. Image Process.
Yang Yang, Wen Wang, Liang Peng, Chaotian Song, Yao Chen, Hengjia Li, Xiaolong Yang, Qinglin Lu, Deng Cai, Xiaofei He, Boxi Wu, Wei Liu
2025 A* conf
AAAI
Yibo Zhao, Liang Peng, Yang Yang, Zekai Luo, Hengjia Li, Yao Chen, Zheng Yang, Xiaofei He, Wei Zhao, Qinglin Lu, Wei Liu, Boxi Wu
2025 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Qibo Qiu, Honghui Yang, Jian Jiang, Shun Zhang, Haochao Ying, Haiming Gao, Wenxiao Wang, Xiaofei He
2025 Misc conf
ICASSP
Haoran Cheng, Junkai Xu, Liang Peng, Zheng Yang, Xiaofei He, Boxi Wu
2025 A* conf
ICLR
Yuqi Lin, Hengjia Li, Wenqi Shao, Zheng Yang, Jun Zhao, Xiaofei He, Ping Luo, Kaipeng Zhang
2025 J jnl
CoRR
Yuqi Lin, Hengjia Li, Wenqi Shao, Zheng Yang, Jun Zhao, Xiaofei He, Ping Luo, Kaipeng Zhang
2025 J jnl
CoRR
Liang Peng, Boxi Wu, Haoran Cheng, Yibo Zhao, Xiaofei He
2025 J jnl
CoRR
Yaming Yang, Zhe Wang, Ziyu Guan, Wei Zhao, Xinyan Huang, Xiaofei He
2025 J jnl
IEEE Trans. Knowl. Data Eng.
Yaming Yang, Zhe Wang, Ziyu Guan, Wei Zhao, Xinyan Huang, Xiaofei He
2024 conf
ECCV (57)
Yanting Yang, Minghao Chen, Qibo Qiu, Jiahao Wu, Wenxiao Wang, Binbin Lin, Ziyu Guan, Xiaofei He
2024 J jnl
CoRR
Yanting Yang, Minghao Chen, Qibo Qiu, Jiahao Wu, Wenxiao Wang, Binbin Lin, Ziyu Guan, Xiaofei He
2024 A* conf
NeurIPS
Minghao Chen, Yihang Li, Yanting Yang, Shiyu Yu, Binbin Lin, Xiaofei He
2024 J jnl
CoRR
Minghao Chen, Yihang Li, Yanting Yang, Shiyu Yu, Binbin Lin, Xiaofei He
2024 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Wenxiao Wang, Wei Chen, Qibo Qiu, Long Chen, Boxi Wu, Binbin Lin, Xiaofei He, Wei Liu
2024 J jnl
CoRR
Honghui Yang, Di Huang, Wei Yin, Chunhua Shen, Haifeng Liu, Xiaofei He, Binbin Lin, Wanli Ouyang, Tong He
2024 A* conf
NeurIPS
Qibo Qiu, Shun Zhang, Haiming Gao, Honghui Yang, Haochao Ying, Wenxiao Wang, Xiaofei He
2024 A* conf
NeurIPS
Yuxin Xiao, Chaoqun Wan, Yonggang Zhang, Wenxiao Wang, Binbin Lin, Xiaofei He, Xu Shen, Jieping Ye
2024 J jnl
CoRR
Yuxin Xiao, Chaoqun Wan, Yonggang Zhang, Wenxiao Wang, Binbin Lin, Xiaofei He, Xu Shen, Jieping Ye
2024 A* conf
ICLR
Hengjia Li, Yang Liu, Linxuan Xia, Yuqi Lin, Wenxiao Wang, Tu Zheng, Zheng Yang, Xiaohui Zhong, Xiaobo Ren, Xiaofei He
2024 J jnl
CoRR
Wenxiao Wang, Wei Chen, Yicong Luo, Yongliu Long, Zhengkai Lin, Liye Zhang, Binbin Lin, Deng Cai, Xiaofei He
2024 J jnl
IEEE Trans. Image Process.
Xing Zhao, Haoran Liang, Peipei Li, Guodao Sun, Dongdong Zhao, Ronghua Liang, Xiaofei He
2024 J jnl
CoRR
Chenshu Hou, Liang Peng, Xiaopei Wu, Wenxiao Wang, Xiaofei He
2024 J jnl
CoRR
Wenxiao Wang, Lihui Gu, Liye Zhang, Yunxiang Luo, Yi Dai, Chen Shen, Liang Xie, Binbin Lin, Xiaofei He, Jieping Ye
2024 J jnl
CoRR
Haoran Cheng, Liang Peng, Linxuan Xia, Yuepeng Hu, Hengjia Li, Qinglin Lu, Xiaofei He, Boxi Wu
2024 J jnl
Knowl. Based Syst.
Qibo Qiu, Wenxiao Wang, Haochao Ying, Dingkun Liang, Haiming Gao, Xiaofei He
2024 A* conf
IJCAI
Bin Zhang, Yuanjie Dang, Peng Chen, Ronghua Liang, Nan Gao, Ruohong Huan, Xiaofei He
2024 J jnl
IEEE Trans. Image Process.
Haoran Cheng, Liang Peng, Zheng Yang, Binbin Lin, Xiaofei He, Boxi Wu
2024 A* conf
CVPR
Honghui Yang, Sha Zhang, Di Huang, Xiaoyang Wu, Haoyi Zhu, Tong He, Shixiang Tang, Hengshuang Zhao, Qibo Qiu, Binbin Lin, Xiaofei He, Wanli Ouyang
2023 J jnl
CoRR
Minghao Chen, Zepeng Gao, Shuai Zhao, Qibo Qiu, Wenxiao Wang, Binbin Lin, Xiaofei He
2023 A* conf
CVPR
Yuqi Lin, Minghao Chen, Wenxiao Wang, Boxi Wu, Ke Li, Binbin Lin, Haifeng Liu, Xiaofei He
2023 J jnl
CoRR
Wenxiao Wang, Wei Chen, Qibo Qiu, Long Chen, Boxi Wu, Binbin Lin, Xiaofei He, Wei Liu
2023 J jnl
CoRR
Dong Yao, Shengyu Zhang, Zhou Zhao, Jieming Zhu, Wenqiao Zhang, Rui Zhang, Xiaofei He, Fei Wu
2023 J jnl
CoRR
Jie Zhao, Ziyu Guan, Wei Zhao, Yue Jiang, Xiaofei He
2023 J jnl
CoRR
Hengjia Li, Yang Liu, Linxuan Xia, Yuqi Lin, Tu Zheng, Zheng Yang, Wenxiao Wang, Xiaohui Zhong, Xiaobo Ren, Xiaofei He
2023 A* conf
CVPR
Honghui Yang, Tong He, Jiaheng Liu, Hua Chen, Boxi Wu, Binbin Lin, Xiaofei He, Wanli Ouyang
2023 J jnl
CoRR
Liang Xie, Yibo Yang, Wenxiao Wang, Binbin Lin, Deng Cai, Xiaofei He
2023 J jnl
CoRR
Qibo Qiu, Honghui Yang, Wenxiao Wang, Shun Zhang, Haiming Gao, Haochao Ying, Wei Hua, Xiaofei He
2023 J jnl
Int. J. Mach. Learn. Cybern.
Yuanhai Lv, Chen Jiao, Wanqing Zhao, Wei Zhao, Ziyu Guan, Xiaofei He
2023 J jnl
Neurocomputing
Liang Xie, Yibo Yang, Deng Cai, Xiaofei He
2023 J jnl
Int. J. Mach. Learn. Cybern.
Chao Xiang, Zhongming Jin, Zhengxu Yu, Xian-Sheng Hua, Yao Hu, Wei Qian, Kaili Zhu, Deng Cai, Xiaofei He
2023 A* conf
CVPR
Honghui Yang, Wenxiao Wang, Minghao Chen, Binbin Lin, Tong He, Hua Chen, Xiaofei He, Wanli Ouyang
2023 J jnl
CoRR
Honghui Yang, Wenxiao Wang, Minghao Chen, Binbin Lin, Tong He, Hua Chen, Xiaofei He, Wanli Ouyang
2023 A* conf
ICRA
Qibo Qiu, Haiming Gao, Wei Hua, Gang Huang, Xiaofei He
2023 J jnl
CoRR
Qibo Qiu, Haiming Gao, Wenxiao Wang, Zhiyi Su, Tian Xie, Wei Hua, Xiaofei He
2023 A* conf
AAAI
Boxi Wu, Jie Jiang, Haidong Ren, Zifan Du, Wenxiao Wang, Zhifeng Li, Deng Cai, Xiaofei He, Binbin Lin, Wei Liu
2023 J jnl
CoRR
Honghui Yang, Sha Zhang, Di Huang, Xiaoyang Wu, Haoyi Zhu, Tong He, Shixiang Tang, Hengshuang Zhao, Qibo Qiu, Binbin Lin, Xiaofei He, Wanli Ouyang
2023 J jnl
IEEE Trans. Knowl. Data Eng.
Xin Guo, Zhengxu Yu, Pengfei Wang, Zhongming Jin, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2023 J jnl
IEEE Trans. Image Process.
Liang Xie, Guodong Xu, Deng Cai, Xiaofei He
2022 J jnl
CoRR
Shengyu Zhang, Bofang Li, Dong Yao, Fuli Feng, Jieming Zhu, Wenyan Fan, Zhou Zhao, Xiaofei He, Tat-Seng Chua, Fei Wu
2022 J jnl
CoRR
Yuqi Lin, Minghao Chen, Wenxiao Wang, Boxi Wu, Ke Li, Binbin Lin, Haifeng Liu, Xiaofei He
2022 A* conf
CVPR
Tu Zheng, Yifei Huang, Yang Liu, Wenjian Tang, Zheng Yang, Deng Cai, Xiaofei He
2022 J jnl
CoRR
Tu Zheng, Yifei Huang, Yang Liu, Wenjian Tang, Zheng Yang, Deng Cai, Xiaofei He
2022 A* conf
ICLR
Wenxiao Wang, Lu Yao, Long Chen, Binbin Lin, Deng Cai, Xiaofei He, Wei Liu
2022 A* conf
AAAI
Yang Liu, Tu Zheng, Jie Song, Deng Cai, Xiaofei He
2022 J jnl
CoRR
Honghui Yang, Tong He, Jiaheng Liu, Hua Chen, Boxi Wu, Binbin Lin, Xiaofei He, Wanli Ouyang
2022 conf
ECCV (8)
Honghui Yang, Zili Liu, Xiaopei Wu, Wenxiao Wang, Wei Qian, Xiaofei He, Deng Cai
2022 J jnl
CoRR
Honghui Yang, Zili Liu, Xiaopei Wu, Wenxiao Wang, Wei Qian, Xiaofei He, Deng Cai
2022 A* conf
CVPR
Yang Liu, Weifeng Zhang, Chao Xiang, Tu Zheng, Deng Cai, Xiaofei He
2022 A* conf
CVPR
Aoxiong Yin, Zhou Zhao, Weike Jin, Meng Zhang, Xingshan Zeng, Xiaofei He
2022 J jnl
CoRR
Xing Zhao, Haoran Liang, Peipei Li, Guodao Sun, Dongdong Zhao, Ronghua Liang, Xiaofei He
2022 J jnl
CoRR
Liang Xie, Yibo Yang, Deng Cai, Xiaofei He
2022 J jnl
Int. J. Mach. Learn. Cybern.
Kuoliang Wu, Guodong Xu, Zili Liu, Haifeng Liu, Deng Cai, Xiaofei He
2022 J jnl
CoRR
Qibo Qiu, Haiming Gao, Wei Hua, Gang Huang, Xiaofei He
2022 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Wei Zhao, Cai Xu, Ziyu Guan, Xunlian Wu, Wanqing Zhao, Qiguang Miao, Xiaofei He, Quan Wang
2022 conf
ECCV (13)
Boxi Wu, Jindong Gu, Zhifeng Li, Deng Cai, Xiaofei He, Wei Liu
2022 J jnl
CoRR
Boxi Wu, Jindong Gu, Zhifeng Li, Deng Cai, Xiaofei He, Wei Liu
2022 J jnl
CoRR
Boxi Wu, Jie Jiang, Haidong Ren, Zifan Du, Wenxiao Wang, Zhifeng Li, Deng Cai, Xiaofei He, Binbin Lin, Wei Liu
2022 J jnl
CoRR
Jiong Wang, Zhou Zhao, Weike Jin, Xinyu Duan, Zhen Lei, Baoxing Huai, Yiling Wu, Xiaofei He
2022 A* conf
ICLR
Liang Peng, Senbo Yan, Boxi Wu, Zheng Yang, Xiaofei He, Deng Cai
2022 J jnl
CoRR
Liang Peng, Senbo Yan, Boxi Wu, Zheng Yang, Xiaofei He, Deng Cai
2021 A* conf
ICML
Wenxiao Wang, Minghao Chen, Shuai Zhao, Long Chen, Jinming Hu, Haifeng Liu, Deng Cai, Xiaofei He, Wei Liu
2021 J jnl
CoRR
Boxi Wu, Heng Pan, Li Shen, Jindong Gu, Shuai Zhao, Zhifeng Li, Deng Cai, Xiaofei He, Wei Liu
2021 J jnl
Neurocomputing
Wenxiao Wang, Zhengxu Yu, Cong Fu, Deng Cai, Xiaofei He
2021 J jnl
CoRR
Wenxiao Wang, Lu Yao, Long Chen, Deng Cai, Xiaofei He, Wei Liu
2021 J jnl
CoRR
Yang Liu, Tu Zheng, Jie Song, Deng Cai, Xiaofei He
2021 J jnl
CoRR
Xin Guo, Zhongming Jin, Chong Chen, Helei Nie, Jianqiang Huang, Deng Cai, Xiaofei He, Xiansheng Hua
2021 A* conf
NeurIPS
Boxi Wu, Jinghui Chen, Deng Cai, Xiaofei He, Quanquan Gu
2021 J jnl
CoRR
Dong Shen, Shuai Zhao, Jinming Hu, Hao Feng, Deng Cai, Xiaofei He
2021 J jnl
IEEE Trans. Image Process.
Dong Shen, Shuai Zhao, Jinming Hu, Hao Feng, Deng Cai, Xiaofei He
2021 J jnl
IEEE Trans. Cybern.
Shangming Yang, Lei Zhang, Xiaofei He, Zhang Yi
2021 J jnl
CoRR
Liang Peng, Fei Liu, Senbo Yan, Xiaofei He, Deng Cai
2021 A* conf
ICCV
Hao Fang, Daoxin Zhang, Yi Zhang, Minghao Chen, Jiawei Li, Yao Hu, Deng Cai, Xiaofei He
2021 J jnl
CoRR
Hao Fang, Daoxin Zhang, Yi Zhang, Minghao Chen, Jiawei Li, Yao Hu, Deng Cai, Xiaofei He
2021 A* conf
ACM Multimedia
Zhijie Lin, Zhou Zhao, Haoyuan Li, Jinglin Liu, Meng Zhang, Xingshan Zeng, Xiaofei He
2021 J jnl
CoRR
Zhijie Lin, Zhou Zhao, Haoyuan Li, Jinglin Liu, Meng Zhang, Xingshan Zeng, Xiaofei He
2021 A* conf
ACM Multimedia
Aoxiong Yin, Zhou Zhao, Jinglin Liu, Weike Jin, Meng Zhang, Xingshan Zeng, Xiaofei He
2021 J jnl
CoRR
Aoxiong Yin, Zhou Zhao, Jinglin Liu, Weike Jin, Meng Zhang, Xingshan Zeng, Xiaofei He
2021 A* conf
ACM Multimedia
Jiong Wang, Zhou Zhao, Weike Jin, Xinyu Duan, Zhen Lei, Baoxing Huai, Yiling Wu, Xiaofei He
2021 A* conf
ACM Multimedia
Jiahao Xun, Shengyu Zhang, Zhou Zhao, Jieming Zhu, Qi Zhang, Jingjie Li, Xiuqiang He, Xiaofei He, Tat-Seng Chua, Fei Wu
2021 J jnl
CoRR
Jiahao Xun, Shengyu Zhang, Zhou Zhao, Jieming Zhu, Qi Zhang, Jingjie Li, Xiuqiang He, Xiaofei He, Tat-Seng Chua, Fei Wu
2021 J jnl
CoRR
Liang Xie, Guodong Xu, Deng Cai, Xiaofei He
2020 J jnl
CoRR
Zhengxu Yu, Yilun Zhao, Bin Hong, Zhongming Jin, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2020 J jnl
Neurocomputing
Yaming Yang, Hongmin Liu, Ziyu Guan, Xiaofei He, Gaoliang Liu
2020 J jnl
ACM Trans. Knowl. Discov. Data
Yu Yang, Xiangbo Mao, Jian Pei, Xiaofei He
2020 J jnl
Neurocomputing
Long Wei, Zhenyong Wei, Zhongming Jin, Qianxiao Wei, Jianqiang Huang, Xian-Sheng Hua, Deng Cai, Xiaofei He
2020 J jnl
IEEE Trans. Knowl. Data Eng.
Wei Zhao, Ziyu Guan, Yuhui Huang, Tingting Xi, Huan Sun, Zhiheng Wang, Xiaofei He
2020 J jnl
CoRR
Boxi Wu, Jinghui Chen, Deng Cai, Xiaofei He, Quanquan Gu
2020 J jnl
CoRR
Jia Guo, Chen Zhu, Yilun Zhao, Heda Wang, Yao Hu, Xiaofei He, Deng Cai
2020 A* conf
IJCAI
Zhengxu Yu, Shuxian Liang, Long Wei, Zhongming Jin, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2020 A* conf
AAAI
Liang Xie, Chao Xiang, Zhengxu Yu, Guodong Xu, Zheng Yang, Deng Cai, Xiaofei He
2020 J jnl
IEEE Trans. Image Process.
Long Wei, Zhenyong Wei, Zhongming Jin, Zhengxu Yu, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2020 J jnl
CoRR
Jia Guo, Minghao Chen, Yao Hu, Chen Zhu, Xiaofei He, Deng Cai
2020 J jnl
CoRR
Zhengxu Yu, Pengfei Wang, Junkai Xu, Liang Xie, Zhongming Jin, Jianqiang Huang, Xiaofei He, Deng Cai, Xian-Sheng Hua
2019 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Minkyu Kim, Abinash Mohanty, Deepak Kadetotad, Luning Wei, Xiaofei He, Yu Cao, Jae-sun Seo
2019 A* conf
ICCV
Yang Liu, Jishun Guo, Deng Cai, Xiaofei He
2019 A* conf
IJCAI
Wenxiao Wang, Cong Fu, Jishun Guo, Deng Cai, Xiaofei He
2019 J jnl
CoRR
Wenxiao Wang, Cong Fu, Jishun Guo, Deng Cai, Xiaofei He
2019 J jnl
CoRR
Boyuan Pan, Yazheng Yang, Zhou Zhao, Yueting Zhuang, Deng Cai, Xiaofei He
2019 A* conf
KDD
Jun Zhao, Zhou Zhou, Ziyu Guan, Wei Zhao, Wei Ning, Guang Qiu, Xiaofei He
2019 J jnl
CoRR
Jun Zhao, Zhou Zhou, Ziyu Guan, Wei Zhao, Wei Ning, Guang Qiu, Xiaofei He
2019 J jnl
CoRR
Boyuan Pan, Yazheng Yang, Hao Li, Zhou Zhao, Yueting Zhuang, Deng Cai, Xiaofei He
2019 A* conf
IJCAI
Zhu Zhang, Zhou Zhao, Zhijie Lin, Jingkuan Song, Xiaofei He
2019 J jnl
CoRR
Zhu Zhang, Zhou Zhao, Zhijie Lin, Jingkuan Song, Xiaofei He
2019 J jnl
CoRR
Liang Xie, Chao Xiang, Zhengxu Yu, Guodong Xu, Zheng Yang, Deng Cai, Xiaofei He
2019 A* conf
IJCAI
Zhengxu Yu, Zhongming Jin, Long Wei, Jishun Guo, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2019 J jnl
CoRR
Zhengxu Yu, Zhongming Jin, Long Wei, Jishun Guo, Jianqiang Huang, Deng Cai, Xiaofei He, Xian-Sheng Hua
2019 J jnl
J. Mach. Learn. Res.
Bin Hong, Weizhong Zhang, Wei Liu, Jieping Ye, Deng Cai, Xiaofei He, Jie Wang
2018 A* conf
IJCAI
Zhou Zhao, Lingtao Meng, Jun Xiao, Min Yang, Fei Wu, Deng Cai, Xiaofei He, Yueting Zhuang
2018 A* conf
KDD
Jun Zhao, Guang Qiu, Ziyu Guan, Wei Zhao, Xiaofei He
2018 J jnl
CoRR
Jun Zhao, Guang Qiu, Ziyu Guan, Wei Zhao, Xiaofei He
2018 A* conf
SIGIR
Zheqian Chen, Rongqin Yang, Zhou Zhao, Deng Cai, Xiaofei He
2018 conf
ACL (1)
Boyuan Pan, Yazheng Yang, Zhou Zhao, Yueting Zhuang, Deng Cai, Xiaofei He
2018 J jnl
IEEE Trans. Knowl. Data Eng.
Weizhong Zhang, Tingjin Luo, Shuang Qiu, Jieping Ye, Deng Cai, Xiaofei He, Jie Wang
2018 J jnl
Neurocomputing
Ge Wen, Huaguan Chen, Deng Cai, Xiaofei He
2018 A* conf
NeurIPS
Boyuan Pan, Yazheng Yang, Hao Li, Zhou Zhao, Yueting Zhuang, Deng Cai, Xiaofei He
2018 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xiantong Zhen, Mengyang Yu, Xiaofei He, Shuo Li
2018 A* conf
IJCAI
Zhou Zhao, Xinghua Jiang, Deng Cai, Jun Xiao, Xiaofei He, Shiliang Pu
2018 J jnl
Neurocomputing
Kuoliang Wu, Deng Cai, Xiaofei He
2018 J jnl
IEEE Trans. Intell. Transp. Syst.
Peng Chen, Yuanjie Dang, Ronghua Liang, Wei Zhu, Xiaofei He
2018 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Zechao Li, Jinhui Tang, Xiaofei He
2018 J jnl
IEEE Trans. Multim.
Zhou Zhao, Qifan Yang, Hanqing Lu, Tim Weninger, Deng Cai, Xiaofei He, Yueting Zhuang
2018 J jnl
Neurocomputing
Ge Wen, Yi Mao, Deng Cai, Xiaofei He
2018 A* conf
IJCAI
Wei Qian, Cong Fu, Yu Zhu, Deng Cai, Xiaofei He
2018 J jnl
IEEE Trans. Knowl. Data Eng.
Wei Zhao, Ziyu Guan, Long Chen, Xiaofei He, Deng Cai, Beidou Wang, Quan Wang
2017 conf
ASP-DAC
Minkyu Kim, Abinash Mohanty, Deepak Kadetotad, Naveen Suda, Luning Wei, Pooja Saseendran, Xiaofei He, Yu Cao, Jae-sun Seo
2017 C conf
ISCAS
Minkyu Kim, Abinash Mohanty, Deepak Kadetotad, Naveen Suda, Luning Wei, Pooja Saseendran, Xiaofei He, Yu Cao, Jae-sun Seo
2017 A* conf
AAAI
Zhou Zhao, Hanqing Lu, Vincent W. Zheng, Deng Cai, Xiaofei He, Yueting Zhuang
2017 J jnl
CoRR
Zheqian Chen, Rongqin Yang, Zhou Zhao, Deng Cai, Xiaofei He
2017 J jnl
CoRR
Boyuan Pan, Hao Li, Zhou Zhao, Deng Cai, Xiaofei He
2017 J jnl
CoRR
Junying Li, Deng Cai, Xiaofei He
2017 A* conf
IJCAI
Zhou Zhao, Ben Gao, Vincent W. Zheng, Deng Cai, Xiaofei He, Yueting Zhuang
2017 J jnl
CoRR
Boyuan Pan, Hao Li, Zhou Zhao, Bin Cao, Deng Cai, Xiaofei He
2017 A* conf
IJCAI
Zhou Zhao, Hanqing Lu, Deng Cai, Xiaofei He, Yueting Zhuang
2017 A* conf
IJCAI
Xin Guo, Boyuan Pan, Deng Cai, Xiaofei He
2017 A* conf
ICML
Weizhong Zhang, Bin Hong, Wei Liu, Jieping Ye, Deng Cai, Xiaofei He, Jie Wang
2017 J jnl
CoRR
Zheqian Chen, Rongqin Yang, Bin Cao, Zhou Zhao, Deng Cai, Xiaofei He
2017 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Weizhong Zhang, Lijun Zhang, Zhongming Jin, Rong Jin, Deng Cai, Xuelong Li, Ronghua Liang, Xiaofei He
2017 A* conf
ACM Multimedia
Zhou Zhao, Jinghao Lin, Xinghua Jiang, Deng Cai, Xiaofei He, Yueting Zhuang
2017 A* conf
IJCAI
Zhou Zhao, Qifan Yang, Deng Cai, Xiaofei He, Yueting Zhuang
2016 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xiaofei He, Chiyuan Zhang, Lijun Zhang, Xuelong Li
2016 A* conf
AAAI
Weizhong Zhang, Lijun Zhang, Rong Jin, Deng Cai, Xiaofei He
2016 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
Yao Hu, Chen Zhao, Deng Cai, Xiaofei He, Xuelong Li
2016 conf
SIGMOD Conference
Yu Yang, Xiangbo Mao, Jian Pei, Xiaofei He
2016 J jnl
IEEE Trans. Cybern.
Haoran Liang, Ronghua Liang, Mingli Song, Xiaofei He
2016 A* conf
IJCAI
Zhou Zhao, Qifan Yang, Deng Cai, Xiaofei He, Yueting Zhuang
2016 J jnl
IEEE Trans. Knowl. Data Eng.
Zhou Zhao, Xiaofei He, Deng Cai, Lijun Zhang, Wilfred Ng, Yueting Zhuang
2016 J jnl
Neurocomputing
Yu Zhu, Ziyu Guan, Shulong Tan, Haifeng Liu, Deng Cai, Xiaofei He
2016 J jnl
IEEE Trans. Knowl. Data Eng.
Jiajun Bu, Xin Shen, Bin Xu, Chun Chen, Xiaofei He, Deng Cai
2016 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Mengyang Yu, Ling Shao, Xiantong Zhen, Xiaofei He
2016 A* conf
IJCAI
Wei Qian, Bin Hong, Deng Cai, Xiaofei He, Xuelong Li
2016 J jnl
Neurocomputing
Bin Hong, Long Wei, Yao Hu, Deng Cai, Xiaofei He
2016 A* conf
ACM Multimedia
Zhou Zhao, Hanqing Lu, Deng Cai, Xiaofei He, Yueting Zhuang
2016 J jnl
CoRR
Weizhong Zhang, Bin Hong, Jieping Ye, Deng Cai, Xiaofei He, Jie Wang
2016 J jnl
Neurocomputing
Hongyang Xue, Yao Liu, Deng Cai, Xiaofei He
2016 J jnl
IEEE Trans. Knowl. Data Eng.
Zhou Zhao, Hanqing Lu, Deng Cai, Xiaofei He, Yueting Zhuang
2015 J jnl
IEEE Trans. Image Process.
Shangming Yang, Zhang Yi, Xiaofei He, Xuelong Li
2015 J jnl
IEEE Trans. Knowl. Data Eng.
Bin Xu, Jiajun Bu, Chun Chen, Can Wang, Deng Cai, Xiaofei He
2015 conf
IScIDE (2)
Debing Zhang, Long Wei, Bin Hong, Yao Hu, Deng Cai, Xiaofei He
2015 J jnl
IEEE Trans. Knowl. Data Eng.
Zhou Zhao, Lijun Zhang, Xiaofei He, Wilfred Ng
2015 ed.
IScIDE (2)
Xiaofei He, Xinbo Gao, Yanning Zhang, Zhi-Hua Zhou, Zhiyong Liu, Baochuan Fu, Fuyuan Hu, Zhancheng Zhang
2015 ed.
IScIDE (1)
Xiaofei He, Xinbo Gao, Yanning Zhang, Zhi-Hua Zhou, Zhiyong Liu, Baochuan Fu, Fuyuan Hu, Zhancheng Zhang
2015 J jnl
Neurocomputing
Yao Hu, Zhongming Jin, Yi Shi, Debing Zhang, Deng Cai, Xiaofei He
2015 A* conf
IJCAI
Zhou Zhao, Ruihua Song, Xing Xie, Xiaofei He, Yueting Zhuang
2015 J jnl
IEEE Trans. Image Process.
Shibiao Xu, Feihu Zhang, Xiaofei He, Xukun Shen, Xiaopeng Zhang
2015 J jnl
IEEE Trans. Knowl. Data Eng.
Chuan-Xian Ren, Dao-Qing Dai, Xiaofei He, Hong Yan
2015 J jnl
Neurocomputing
Zhanying He, Chun Chen, Jiajun Bu, Can Wang, Lijun Zhang, Deng Cai, Xiaofei He
2014 J jnl
IEEE Trans. Knowl. Data Eng.
Shangming Yang, Zhang Yi, Mao Ye, Xiaofei He
2014 J jnl
IEEE Trans. Cybern.
Zhongming Jin, Debing Zhang, Yao Hu, Shiding Lin, Deng Cai, Xiaofei He
2014 A* conf
ICML
Binbin Lin, Ji Yang, Xiaofei He, Jieping Ye
2014 J jnl
CoRR
Binbin Lin, Ji Yang, Xiaofei He, Jieping Ye
2014 J jnl
IEEE Trans. Knowl. Data Eng.
Shulong Tan, Yang Li, Huan Sun, Ziyu Guan, Xifeng Yan, Jiajun Bu, Chun Chen, Xiaofei He
2014 A* conf
ACM Multimedia
Yao Hu, Zhongming Jin, Hongyi Ren, Deng Cai, Xiaofei He
2014 J jnl
Neurocomputing
Ji Yang, Bin Xu, Binbin Lin, Xiaofei He
2014 J jnl
Signal Process.
Haixia Wang, Qian Kemao, Ronghua Liang, Huayin Wang, Ming Zhao, Xiaofei He
2014 J jnl
IEEE Trans. Knowl. Data Eng.
Ronghua Liang, Hai Zhuge, Xiaorui Jiang, Qiang Zeng, Xiaofei He
2014 A* conf
AAAI
Weizhong Zhang, Lijun Zhang, Yao Hu, Rong Jin, Deng Cai, Xiaofei He
2014 J jnl
Neurocomputing
Xiaofei He, Changyin Sun
2013 A* conf
IJCAI
Debing Zhang, Genmao Yang, Yao Hu, Zhongming Jin, Deng Cai, Xiaofei He
2013 A* conf
SIGIR
Xinyan Lu, Fei Wu, Siliang Tang, Zhongfei Zhang, Xiaofei He, Yueting Zhuang
2013 A* conf
IJCAI
Yao Hu, Debing Zhang, Zhongming Jin, Deng Cai, Xiaofei He
2013 J jnl
Int. J. Softw. Informatics
Xiaofei He
2013 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Yao Hu, Debing Zhang, Jieping Ye, Xuelong Li, Xiaofei He
2013 J jnl
Neurocomputing
Guanhong Yao, Ke Lu, Xiaofei He
2013 A* conf
IJCAI
Bin Xu, Jiajun Bu, Yue Lin, Chun Chen, Xiaofei He, Deng Cai
2013 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Chiyuan Zhang, Xiaofei He
2013 J jnl
IEEE Trans. Image Process.
Yan Chen, Jiemi Zhang, Deng Cai, Wei Liu, Xiaofei He
2013 J jnl
CoRR
Lijun Zhang, Tianbao Yang, Rong Jin, Xiaofei He
2013 conf
ICML (3)
Lijun Zhang, Tianbao Yang, Rong Jin, Xiaofei He
2013 conf
ICML (3)
Lijun Zhang, Jinfeng Yi, Rong Jin, Ming Lin, Xiaofei He
2013 J jnl
ACM Trans. Knowl. Discov. Data
Ming Ji, Binbin Lin, Xiaofei He, Deng Cai, Jiawei Han
2013 A* conf
ACM Multimedia
Xiangbo Mao, Binbin Lin, Deng Cai, Xiaofei He, Jian Pei
2013 J jnl
J. Mach. Learn. Res.
Binbin Lin, Xiaofei He, Chiyuan Zhang, Ming Ji
2013 conf
IScIDE
Chuhang Zou, Yao Hu, Deng Cai, Xiaofei He
2013 A* conf
WWW
Beidou Wang, Can Wang, Jiajun Bu, Chun Chen, Wei Vivian Zhang, Deng Cai, Xiaofei He
2012 J jnl
IEEE Trans. Image Process.
Lijun Zhang, Chun Chen, Jiajun Bu, Xiaofei He
2012 A* conf
KDD
Yao Hu, Debing Zhang, Jun Liu, Jieping Ye, Xiaofei He
2012 A* conf
AAAI
Zhanying He, Chun Chen, Jiajun Bu, Can Wang, Lijun Zhang, Deng Cai, Xiaofei He
2012 A* conf
AAAI
Lijun Zhang, Rong Jin, Chun Chen, Jiajun Bu, Xiaofei He
2012 J jnl
IEEE Trans. Knowl. Data Eng.
Deng Cai, Xiaofei He
2012 A* conf
CVPR
Debing Zhang, Yao Hu, Jieping Ye, Xuelong Li, Xiaofei He
2012 conf
NIPS
Binbin Lin, Sen Yang, Chiyuan Zhang, Jieping Ye, Xiaofei He
2012 A* conf
KDD
Ming Ji, Binbin Lin, Xiaofei He, Deng Cai, Jiawei Han
2012 J jnl
IEEE Trans. Multim.
Jianping Fan, Xiaofei He, Ning Zhou, Jinye Peng, Ramesh C. Jain
2012 A* conf
AAAI
Yue Lin, Rong Jin, Deng Cai, Xiaofei He
2012 A* conf
ACM Multimedia
Jiajun Bu, Bin Xu, Chenxia Wu, Chun Chen, Jianke Zhu, Deng Cai, Xiaofei He
2011 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xiaofei He, Ming Ji, Chiyuan Zhang, Hujun Bao
2011 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Lijun Zhang, Chun Chen, Jiajun Bu, Deng Cai, Xiaofei He, Thomas S. Huang
2011 J jnl
Neurocomputing
Wei Hua, Xiaofei He
2011 A* conf
SIGIR
Bin Xu, Jiajun Bu, Chun Chen, Deng Cai, Xiaofei He, Wei Liu, Jiebo Luo
2011 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Deng Cai, Xiaofei He, Jiawei Han, Thomas S. Huang
2011 J jnl
Pattern Recognit.
Can Wang, Xiaofei He, Jiajun Bu, Zhengguang Chen, Chun Chen, Ziyu Guan
2011 J jnl
IEEE Trans. Knowl. Data Eng.
Xiaofei He, Deng Cai, Yuanlong Shao, Hujun Bao, Jiawei Han
2011 A* conf
SIGIR
Ming Ji, Jun Yan, Siyu Gu, Jiawei Han, Xiaofei He, Wei Vivian Zhang, Zheng Chen
2011 J jnl
IEEE Trans. Knowl. Data Eng.
Deng Cai, Xiaofei He, Jiawei Han
2011 A* conf
CVPR
Yan Chen, Hujun Bao, Xiaofei He
2011 conf
IScIDE
Binbin Lin, Chiyuan Zhang, Xiaofei He
2011 conf
NIPS
Binbin Lin, Chiyuan Zhang, Xiaofei He
2011 A* conf
CVPR
Deng Cai, Hujun Bao, Xiaofei He
2011 J jnl
VLDB J.
Deng Cai, Xiaofei He, Jiawei Han
2011 ch.
Social Media Modeling and Computing
Shulong Tan, Jiajun Bu, Chun Chen, Xiaofei He
2011 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
Shulong Tan, Jiajun Bu, Chun Chen, Bin Xu, Can Wang, Xiaofei He
2010 J jnl
Pattern Recognit.
Binbin Lin, Xiaofei He, Yuan Zhou, Ligang Liu, Ke Lu
2010 J jnl
Expert Syst. Appl.
Guang Qiu, Xiaofei He, Feng Zhang, Yuan Shi, Jiajun Bu, Chun Chen
2010 A* conf
ACM Multimedia
Lijun Zhang, Chun Chen, Jiajun Bu, Zhengguang Chen, Shulong Tan, Xiaofei He
2010 A* conf
WWW
Ziyu Guan, Can Wang, Jiajun Bu, Chun Chen, Kun Yang, Deng Cai, Xiaofei He
2010 conf
ICIMCS
Zhou Yu, Deng Cai, Xiaofei He
2010 A* conf
AAAI
Jialu Liu, Deng Cai, Xiaofei He
2010 A* conf
ACM Multimedia
Feng Xie, Yi Shen, Xiaofei He
2010 J jnl
IEEE Trans. Image Process.
Xiaofei He
2010 J jnl
Scholarpedia
Xiaofei He
2010 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Yahong Han, Fei Wu, Yueting Zhuang, Xiaofei He
2010 A* conf
ACM Multimedia
Jiajun Bu, Shulong Tan, Chun Chen, Can Wang, Hao Wu, Lijun Zhang, Xiaofei He
2010 A* conf
KDD
Deng Cai, Chiyuan Zhang, Xiaofei He
2009 A* conf
CVPR
Xiaofei He, Ming Ji, Hujun Bao
2009 A* conf
ICCV
Xiaofei He, Deng Cai
2009 A* conf
WWW
Hao Wu, Guang Qiu, Xiaofei He, Yuan Shi, Mingcheng Qu, Jing Shen, Jiajun Bu, Chun Chen
2009 A* conf
ACM Multimedia
Lijun Zhang, Chun Chen, Wei Chen, Jiajun Bu, Deng Cai, Xiaofei He
2009 A* conf
IJCAI
Xiaofei He, Ming Ji, Hujun Bao
2009 J jnl
Neurocomputing
Can Wang, Jun Zhao, Xiaofei He, Chun Chen, Jiajun Bu
2009 A* conf
IJCAI
Deng Cai, Xiaofei He, Xuanhui Wang, Hujun Bao, Jiawei Han
2009 A* conf
WWW
Junfeng Wang, Xiaofei He, Can Wang, Jian Pei, Jiajun Bu, Chun Chen, Ziyu Guan, Gang Lu
2009 A* conf
ICML
Deng Cai, Xuanhui Wang, Xiaofei He
2009 A* conf
WWW
Mingcheng Qu, Guang Qiu, Xiaofei He, Cheng Zhang, Hao Wu, Jiajun Bu, Chun Chen
2009 A* conf
ACM Multimedia
Yuanlong Shao, Yuan Zhou, Xiaofei He, Deng Cai, Hujun Bao
2009 A* conf
WWW
Junyan Zhu, Can Wang, Xiaofei He, Jiajun Bu, Chun Chen, Shujie Shang, Mingcheng Qu, Gang Lu
2008 J jnl
IEEE Trans. Knowl. Data Eng.
Xiaofei He, Deng Cai, Jiawei Han
2008 J jnl
Neurocomputing
Jidong Zhao, Ke Lu, Xiaofei He
2008 A* conf
ICDM
Deng Cai, Xiaofei He, Xiaoyun Wu, Jiawei Han
2008 J jnl
Pattern Recognit.
Xiaofei He, Pradhuman Jhala
2008 J jnl
IEEE Trans. Knowl. Data Eng.
Deng Cai, Xiaofei He, Jiawei Han
2008 A* conf
AAAI
Deng Cai, Xiaofei He, Jiawei Han
2008 A* conf
ICDE
Deng Cai, Xiaofei He, Jiawei Han
2007 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
Xiaofei He, Deng Cai, Ji-Rong Wen, Wei-Ying Ma, Hong-Jiang Zhang
2007 A* conf
ICDM
Deng Cai, Xiaofei He, Jiawei Han
2007 A* conf
AAAI
Deng Cai, Xiaofei He, Jiawei Han
2007 A* conf
SIGIR
Xiaofei He, Wanli Min, Deng Cai, Kun Zhou
2007 A* conf
CVPR
Deng Cai, Xiaofei He, Yuxiao Hu, Jiawei Han, Thomas S. Huang
2007 A* conf
IJCAI
Deng Cai, Xiaofei He, Kun Zhou, Jiawei Han, Hujun Bao
2007 A* conf
SIGIR
Wei Vivian Zhang, Xiaofei He, Benjamin Rey, Rosie Jones
2007 A conf
CIKM
Deng Cai, Xiaofei He, Wei Vivian Zhang, Jiawei Han
2007 conf
Multimedia Information Retrieval
Deng Cai, Xiaofei He, Jiawei Han
2007 A* conf
ICCV
Deng Cai, Xiaofei He, Jiawei Han
2007 A* conf
ICCV
Deng Cai, Xiaofei He, Jiawei Han
2007 A* conf
ICDM
Deng Cai, Xiaofei He, Jiawei Han
2007 A* conf
ACM Multimedia
Deng Cai, Xiaofei He, Jiawei Han
2006 J jnl
IEEE Trans. Image Process.
Deng Cai, Xiaofei He, Jiawei Han, HongJiang Zhang
2006 conf
ISNN (2)
Ke Lu, Xiaofei He, Jidong Zhao
2006 A* conf
SIGIR
Deng Cai, Xiaofei He, Jiawei Han
2005 conf
PKDD
Deng Cai, Zheng Shao, Xiaofei He, Xifeng Yan, Jiawei Han
2005 J jnl
IEEE Trans. Knowl. Data Eng.
Deng Cai, Xiaofei He, Jiawei Han
2005 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xiaofei He, Shuicheng Yan, Yuxiao Hu, Partha Niyogi, HongJiang Zhang
2005 A* conf
ACM Multimedia
Xiaofei He, Deng Cai, Haifeng Liu, Jiawei Han
2005 J jnl
Pattern Recognit.
Ke Lu, Xiaofei He
2005 conf
NIPS
Xiaofei He, Deng Cai, Partha Niyogi
2005 conf
LinkKDD
Deng Cai, Zheng Shao, Xiaofei He, Xifeng Yan, Jiawei Han
2005 A* conf
ICCV
Xiaofei He, Deng Cai, Shuicheng Yan, HongJiang Zhang
2005 A* conf
SIGIR
Deng Cai, Xiaofei He
2005 A* conf
ICML
Xiaofei He, Deng Cai, Wanli Min
2005 conf
NIPS
Xiaofei He, Deng Cai, Partha Niyogi
2004 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Shuicheng Yan, Xiaofei He, Yuxiao Hu, HongJiang Zhang, Mingjing Li, QianSheng Cheng
2004 A* conf
SIGIR
Deng Cai, Xiaofei He, Ji-Rong Wen, Wei-Ying Ma
2004 A* conf
ACM Multimedia
Deng Cai, Xiaofei He, Zhiwei Li, Wei-Ying Ma, Ji-Rong Wen
2004 C conf
CIS
Ke Lu, Xiaofei He, Jiazhi Zeng
2004 A* conf
ACM Multimedia
Xiaofei He
2004 A* conf
ACM Multimedia
Xiaofei He, Wei-Ying Ma, HongJiang Zhang
2004 A* conf
ACM Multimedia
Xin Zheng, Deng Cai, Xiaofei He, Wei-Ying Ma, Xueyin Lin
2004 A* conf
SIGIR
Xiaofei He, Deng Cai, Haifeng Liu, Wei-Ying Ma
2004 J jnl
Pattern Recognit.
Wanli Min, Ke Lu, Xiaofei He
2004 A conf
ICME
Deng Cai, Xiaofei He, Wei-Ying Ma, Ji-Rong Wen, HongJiang Zhang
2003 A conf
ICME
Xiaofei He, Wei-Ying Ma, Hong-Jiang Zhang
2003 A* conf
ACM Multimedia
Kai Yu, Wei-Ying Ma, Volker Tresp, Zhao Xu, Xiaofei He, HongJiang Zhang, Hans-Peter Kriegel
2003 A* conf
ICCV
Xiaofei He, Shuicheng Yan, Yuxiao Hu, HongJiang Zhang
2003 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Xiaofei He, Oliver King, Wei-Ying Ma, Mingjing Li, HongJiang Zhang
2003 conf
NIPS
Xiaofei He, Partha Niyogi
2002 A* conf
ACM Multimedia
Xiaofei He, Wei-Ying Ma, Oliver King, Mingjing Li, HongJiang Zhang
tests/unit/test_apk_extractors.py
← Index tests/unit/test_apk_extractors.py python
"""
Unit tests for APK extractors.

Tests tag(), get_clickhouse_table(), extract(), and prepare_export_data()
for all 8 APK extractors. Uses mocked androguard APK objects.
"""
import pytest
import os
import hashlib
import tempfile
import zipfile
from dataclasses import asdict
from unittest.mock import MagicMock, patch, PropertyMock

pytestmark = [pytest.mark.unit, pytest.mark.apk]


# ============================================================================
# Helpers
# ============================================================================

def _create_fake_apk(tmp_path, files=None):
    """Create a minimal valid ZIP file that pretends to be an APK.

    Args:
        tmp_path: Directory to write the fake APK into.
        files: Dict of {filename: content_bytes} to include in the ZIP.

    Returns:
        Path to the fake APK file.
    """
    apk_path = os.path.join(tmp_path, "test.apk")
    default_files = {
        "AndroidManifest.xml": b"<manifest/>",
        "classes.dex": b"dex\n035\x00" + b"\x00" * 100,
        "res/drawable/icon.png": b"\x89PNG" + b"\x00" * 50,
    }
    if files:
        default_files.update(files)

    with zipfile.ZipFile(apk_path, "w") as zf:
        for name, data in default_files.items():
            zf.writestr(name, data)
    return apk_path


def _make_mock_apk():
    """Create a mock androguard APK object with common return values."""
    mock_apk = MagicMock()
    mock_apk.get_package.return_value = "com.example.test"
    mock_apk.get_app_name.return_value = "Test App"
    mock_apk.get_androidversion_code.return_value = "10"
    mock_apk.get_androidversion_name.return_value = "1.2.3"
    mock_apk.get_min_sdk_version.return_value = "21"
    mock_apk.get_target_sdk_version.return_value = "33"
    mock_apk.get_effective_target_sdk_version.return_value = "33"
    mock_apk.get_main_activity.return_value = "com.example.test.MainActivity"
    mock_apk.get_attribute_value.return_value = None
    mock_apk.get_libraries.return_value = []
    mock_apk.get_files.return_value = [
        "AndroidManifest.xml", "classes.dex",
        "res/drawable/icon.png", "lib/armeabi-v7a/libnative.so",
        "assets/data.bin",
    ]
    mock_apk.get_permissions.return_value = [
        "android.permission.INTERNET",
        "android.permission.CAMERA",
    ]
    mock_apk.get_declared_permissions.return_value = {}
    mock_apk.get_activities.return_value = ["com.example.test.MainActivity"]
    mock_apk.get_services.return_value = ["com.example.test.MyService"]
    mock_apk.get_receivers.return_value = ["com.example.test.BootReceiver"]
    mock_apk.get_providers.return_value = []
    mock_apk.get_uses_implied_permission_list.return_value = []
    mock_apk.is_valid_APK.return_value = True
    mock_apk.get_certificates.return_value = []
    mock_apk.get_certificates_v1.return_value = []
    mock_apk.get_certificates_v2.return_value = []
    mock_apk.get_certificates_v3.return_value = []
    mock_apk.get_signature_names.return_value = []
    mock_apk.is_signed_v1.return_value = True
    mock_apk.is_signed_v2.return_value = True
    mock_apk.is_signed_v3.return_value = False
    return mock_apk


@pytest.fixture
def fake_apk_env(tmp_path):
    """Create a fake APK file and mock APK object."""
    apk_path = _create_fake_apk(str(tmp_path))
    mock_apk = _make_mock_apk()
    mock_logger = MagicMock()
    mock_exporters = [MagicMock()]
    return apk_path, mock_apk, mock_logger, mock_exporters


# ============================================================================
# APKFeaturesExtractor
# ============================================================================

class TestAPKFeaturesExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_features"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_features"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor
        from redb.models.dataclasses import APKFeatures

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKFeatures)
        assert result.package_name == "com.example.test"
        assert result.app_name == "Test App"
        assert result.version_code == 10
        assert result.version_name == "1.2.3"
        assert result.min_sdk_version == 21
        assert result.target_sdk_version == 33
        assert result.main_activity == "com.example.test.MainActivity"

    def test_extract_detects_native_code(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.has_native_code is True
        assert result.has_assets is True

    def test_extract_invalid_apk_returns_none(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.is_valid_APK.return_value = False
        # APKExtractor sets self.apk to the mock_apk directly; _is_valid_apk checks self.apk is not None
        # For invalid APK, set apk to None
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=None)
        # Override _is_valid_apk to simulate parsing failure
        ext.apk = None
        result = ext.extract()
        assert result is None

    def test_extract_handles_missing_version_code(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_androidversion_code.return_value = None
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.version_code == 0

    def test_prepare_export_data_clickhouse(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        ext.extract()
        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is not None
        data, column_names, column_type_names = result
        assert "sha256" in column_names
        assert "package_name" in column_names
        assert "analysis_date" in column_names
        assert len(column_names) == len(column_type_names)
        assert len(data) == 1  # One row
        assert len(data[0]) == len(column_names)

    def test_prepare_export_data_no_extract(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        # Don't call extract() first
        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is None


# ============================================================================
# APKManifestExtractor
# ============================================================================

class TestAPKManifestExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_manifest"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_manifest"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor
        from redb.models.dataclasses import APKManifest

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Setup intent filter mocking
        mock_apk.get_intent_filters.return_value = {}
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKManifest)
        assert result.activity_count == 1
        assert result.service_count == 1
        assert result.receiver_count == 1
        assert result.provider_count == 0

    def test_extract_counts_components(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_activities.return_value = ["A1", "A2", "A3"]
        mock_apk.get_services.return_value = ["S1", "S2"]
        mock_apk.get_intent_filters.return_value = {}
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.activity_count == 3
        assert result.service_count == 2


# ============================================================================
# APKPermissionsExtractor
# ============================================================================

class TestAPKPermissionsExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_permissions"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_permissions"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor
        from redb.models.dataclasses import APKPermissions

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKPermissions)
        assert result.total_permission_count == 2
        assert "android.permission.INTERNET" in result.permissions
        assert "android.permission.CAMERA" in result.permissions

    def test_extract_classifies_dangerous(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        # CAMERA is dangerous, INTERNET is normal
        assert result.dangerous_permission_count >= 1
        assert "android.permission.CAMERA" in result.dangerous_permissions

    def test_extract_no_permissions(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_permissions.return_value = []
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.total_permission_count == 0
        assert result.dangerous_permission_count == 0


# ============================================================================
# APKSignatureExtractor
# ============================================================================

class TestAPKSignatureExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_signature"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_signature"

    def test_extract_unsigned_apk(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor
        from redb.models.dataclasses import APKCodeSigningInfo

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.is_signed_v1.return_value = False
        mock_apk.is_signed_v2.return_value = False
        mock_apk.is_signed_v3.return_value = False
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKCodeSigningInfo)

    def test_extract_detects_signature_schemes(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.is_signed_v1.return_value = True
        mock_apk.is_signed_v2.return_value = True
        mock_apk.is_signed_v3.return_value = True
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert 1 in result.signature_scheme_versions
        assert 2 in result.signature_scheme_versions
        assert 3 in result.signature_scheme_versions

    def test_certificate_subject_uses_short_names(self, fake_apk_env):
        """Ensure subject/issuer use RFC 4514 short names (CN=, O=) not long names."""
        from unittest.mock import MagicMock
        from asn1crypto import x509
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env

        # Build a real asn1crypto Name so the conversion is exercised
        subject_name = x509.Name.build({
            'country_name': 'US',
            'state_or_province_name': 'California',
            'organization_name': 'Android',
            'common_name': 'Android Debug',
        })

        mock_cert = MagicMock()
        mock_cert.subject = subject_name
        mock_cert.issuer = subject_name
        mock_cert.serial_number = 12345
        mock_cert.not_valid_before = '2020-01-01 00:00:00'
        mock_cert.not_valid_after = '2030-01-01 00:00:00'
        mock_cert.hash_algo = 'sha256'
        mock_cert.public_key.bit_size = 2048
        mock_cert.dump.return_value = b'fake_cert_der_data'

        mock_apk.is_signed_v1.return_value = False
        mock_apk.is_signed_v2.return_value = True
        mock_apk.is_signed_v3.return_value = False
        mock_apk.get_certificates_v2.return_value = [mock_cert]

        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert result.apk_signer_subject is not None
        assert 'CN=' in result.apk_signer_subject
        assert 'O=' in result.apk_signer_subject
        assert 'Common Name' not in result.apk_signer_subject
        assert 'Organization' not in result.apk_signer_subject

        # Also check the certificate list
        assert len(result.x509_certificates) == 1
        cert = result.x509_certificates[0]
        assert 'CN=' in cert.subject
        assert 'Common Name' not in cert.subject


# ============================================================================
# APKDexExtractor
# ============================================================================

class TestAPKDexExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_dex"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_dex"

    def test_extract_returns_list(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Mock DEX data access
        mock_apk.get_dex_names.return_value = ["classes.dex"]
        mock_apk.get_all_dex.return_value = [b"dex\n035\x00" + b"\x00" * 100]

        # Mock the androguard DEX parser
        mock_dex_class = MagicMock()
        mock_dex_instance = MagicMock()
        mock_dex_instance.get_classes.return_value = []
        mock_dex_instance.get_methods.return_value = []
        mock_dex_instance.get_strings.return_value = []
        mock_dex_class.return_value = mock_dex_instance

        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        with patch.dict('sys.modules', {'androguard.core.dex': MagicMock(DEX=mock_dex_class)}):
            result = ext.extract()

        assert result is not None
        assert isinstance(result, list)
        assert len(result) == 1
        assert result[0].filename == "classes.dex"

    def test_extract_computes_tlsh(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Need enough data for TLSH (>50 bytes of varied content)
        import os
        dex_data = os.urandom(256)
        mock_apk.get_dex_names.return_value = ["classes.dex"]
        mock_apk.get_all_dex.return_value = [dex_data]

        mock_dex_class = MagicMock()
        mock_dex_instance = MagicMock()
        mock_dex_instance.get_classes.return_value = []
        mock_dex_instance.get_methods.return_value = []
        mock_dex_instance.get_strings.return_value = []
        mock_dex_instance.get_encoded_methods.return_value = []
        mock_dex_class.return_value = mock_dex_instance

        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        with patch.dict('sys.modules', {'androguard.core.dex': MagicMock(DEX=mock_dex_class)}):
            result = ext.extract()

        assert result is not None
        assert result[0].tlsh is not None
        assert result[0].tlsh.startswith("T1")

    def test_extract_tlsh_none_for_small_dex(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Too small / uniform for TLSH
        dex_data = b"\x00" * 10
        mock_apk.get_dex_names.return_value = ["classes.dex"]
        mock_apk.get_all_dex.return_value = [dex_data]

        mock_dex_class = MagicMock()
        mock_dex_instance = MagicMock()
        mock_dex_instance.get_classes.return_value = []
        mock_dex_instance.get_methods.return_value = []
        mock_dex_instance.get_strings.return_value = []
        mock_dex_instance.get_encoded_methods.return_value = []
        mock_dex_class.return_value = mock_dex_instance

        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        with patch.dict('sys.modules', {'androguard.core.dex': MagicMock(DEX=mock_dex_class)}):
            result = ext.extract()

        assert result is not None
        # TLSH returns empty string for insufficient data, which we convert to None
        assert result[0].tlsh is None

    def test_prepare_export_clickhouse_includes_tlsh(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor
        from redb.models.dataclasses import APKDexFile

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        # Manually set dex_files to test export
        ext.dex_files = [APKDexFile(
            filename="classes.dex",
            sha256="aa" * 32,
            class_count=10,
            method_count=50,
            string_count=100,
            tlsh="T1" + "B" * 68,
        )]

        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is not None
        dex_export = result['dex']
        assert 'dex_tlsh' in dex_export['column_names']
        tlsh_idx = dex_export['column_names'].index('dex_tlsh')
        assert dex_export['data'][0][tlsh_idx] == "T1" + "B" * 68
        assert len(dex_export['column_names']) == len(dex_export['column_type_names'])

    def test_extract_no_dex_returns_none(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_dex_names.return_value = []
        mock_apk.get_all_dex.return_value = []
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is None


# ============================================================================
# APKResourceExtractor
# ============================================================================

class TestAPKResourceExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_resources"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_resources"

    def test_extract_returns_dict(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        # Returns dict with 'resources' key containing list of APKResource
        assert result is None or isinstance(result, dict)
        if result:
            assert "resources" in result
            assert "total_resource_count" in result
            assert isinstance(result["resources"], list)


# ============================================================================
# APKResourceExtractor — _identify_android_format
# ============================================================================

class TestIdentifyAndroidFormat:
    """Unit tests for Android-specific binary format magic detection."""

    def _make_extractor(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor
        apk_path, mock_apk, logger, exporters = fake_apk_env
        return APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

    def test_axml_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\x03\x00\x08\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_binary_xml"

    def test_arsc_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\x02\x00\x0c\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_resource_table"

    def test_art_prof_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'pro\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_art_profile"

    def test_art_profm_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'prm\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_art_profile_metadata"

    def test_unknown_magic_returns_none(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\xff\xff\xff\xff' + b'\x00' * 12
        assert ext._identify_android_format(header) is None

    def test_short_header_returns_none(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._identify_android_format(b'\x03\x00') is None
        assert ext._identify_android_format(b'') is None

    def test_png_magic_not_matched(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\x89PNG\r\n\x1a\n' + b'\x00' * 8
        assert ext._identify_android_format(header) is None


# ============================================================================
# APKResourceExtractor — _is_suspicious_resource
# ============================================================================

class TestIsSuspiciousResource:
    """Unit tests for the layered suspicious resource classification."""

    def _make_extractor(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor
        apk_path, mock_apk, logger, exporters = fake_apk_env
        return APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

    # ── Layer 1: Allowlisted paths ──────────────────────────────────────

    def test_allowlisted_baseline_prof_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/dexopt/baseline.prof",
            magika_type="unknown", entropy=7.9,
            android_type=None,
        ) is False

    def test_allowlisted_baseline_profm_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/dexopt/baseline.profm",
            magika_type="unknown", entropy=7.9,
            android_type=None,
        ) is False

    # ── Layer 2: Android-specific formats → always benign ───────────────

    def test_axml_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/layout/activity_main.xml",
            magika_type="gzip", entropy=6.5,
            android_type="android_binary_xml",
        ) is False

    def test_arsc_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/values/resources.arsc",
            magika_type="unknown", entropy=7.2,
            android_type="android_resource_table",
        ) is False

    def test_art_profile_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/custom/baseline.prof",
            magika_type="unknown", entropy=7.8,
            android_type="android_art_profile",
        ) is False

    def test_art_profile_metadata_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/other/baseline.profm",
            magika_type="unknown", entropy=7.5,
            android_type="android_art_profile_metadata",
        ) is False

    # ── Layer 3: Image extension / Magika type mismatch ─────────────────

    def test_fake_png_extension_with_non_image_content_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/raw/payload.png",
            magika_type="zip", entropy=7.2,
            android_type=None,
        ) is True

    def test_fake_jpg_extension_with_unknown_high_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/data.jpg",
            magika_type="unknown", entropy=6.5,
            android_type=None,
        ) is True

    def test_image_extension_mismatch_low_entropy_not_suspicious(self, fake_apk_env):
        """Tiny/low-entropy files with image extensions shouldn't be flagged."""
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/drawable/tiny.png",
            magika_type="unknown", entropy=3.0,
            android_type=None,
        ) is False

    # ── Layer 4: Magika-confirmed images → benign ───────────────────────

    def test_confirmed_png_high_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/drawable/photo.png",
            magika_type="png", entropy=7.95,
            android_type=None,
        ) is False

    def test_confirmed_webp_high_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/drawable/image.webp",
            magika_type="webp", entropy=7.99,
            android_type=None,
        ) is False

    def test_confirmed_jpeg_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/photos/bg.jpg",
            magika_type="jpeg", entropy=7.9,
            android_type=None,
        ) is False

    # ── Layer 5: Known suspicious file types ────────────────────────────

    def test_elf_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/payload",
            magika_type="elf", entropy=5.0,
            android_type=None,
        ) is True

    def test_dex_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/classes.dex",
            magika_type="dex", entropy=5.5,
            android_type=None,
        ) is True

    def test_shell_script_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/run.sh",
            magika_type="shell", entropy=4.0,
            android_type=None,
        ) is True

    def test_zip_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/data.zip",
            magika_type="zip", entropy=7.5,
            android_type=None,
        ) is True

    def test_jar_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/plugin.jar",
            magika_type="jar", entropy=6.0,
            android_type=None,
        ) is True

    def test_lzma_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/blob.lzma",
            magika_type="lzma", entropy=7.9,
            android_type=None,
        ) is True

    # ── Layer 6: High-entropy unrecognized blobs ────────────────────────

    def test_unknown_type_high_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/xyzdata",
            magika_type="unknown", entropy=7.5,
            android_type=None,
        ) is True

    def test_empty_type_high_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/blob.dat",
            magika_type="empty", entropy=7.2,
            android_type=None,
        ) is True

    def test_unknown_type_low_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/config.dat",
            magika_type="unknown", entropy=4.5,
            android_type=None,
        ) is False

    # ── Layer 7: Extreme entropy on non-image recognized types ──────────

    def test_xml_extreme_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/raw/config.xml",
            magika_type="xml", entropy=7.9,
            android_type=None,
        ) is True

    def test_txt_extreme_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/readme.txt",
            magika_type="txt", entropy=7.86,
            android_type=None,
        ) is True

    def test_xml_normal_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/raw/config.xml",
            magika_type="xml", entropy=4.0,
            android_type=None,
        ) is False

    # ── Benign types that should NOT be flagged ─────────────────────────

    def test_html_not_in_suspicious_types(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/index.html",
            magika_type="html", entropy=5.0,
            android_type=None,
        ) is False

    def test_javascript_not_in_suspicious_types(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/app.js",
            magika_type="javascript", entropy=5.0,
            android_type=None,
        ) is False

    def test_sqlite_not_in_suspicious_types(self, fake_apk_env):
        """sqlite was intentionally excluded — too many legitimate uses."""
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/data.db",
            magika_type="sqlite", entropy=5.0,
            android_type=None,
        ) is False


# ============================================================================
# APKResourceExtractor — integration with extract()
# ============================================================================

class TestAPKResourceExtractorIntegration:
    """Integration tests: craft ZIP contents and verify end-to-end classification."""

    def test_extract_flags_elf_in_assets(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "assets/payload.bin": b"\x7fELF" + b"\x00" * 100,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        # Mock Magika to return "elf" for the payload — real Magika needs
        # a valid ELF structure, but we control classification in unit tests.
        mock_magika = MagicMock()
        mock_magika.identify_bytes.return_value = MagicMock(
            output=MagicMock(label="elf")
        )

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        with patch("magika.Magika", return_value=mock_magika):
            result = ext.extract()
        assert result is not None
        assert result["suspicious_file_count"] >= 1
        sus_paths = [s.path for s in result["suspicious_files"]]
        assert "assets/payload.bin" in sus_paths

    def test_extract_does_not_flag_normal_png(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "res/drawable/icon.png": b"\x89PNG\r\n\x1a\n" + b"\x00" * 50,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        result = ext.extract()
        assert result is not None
        sus_paths = [s.path for s in result["suspicious_files"]]
        assert "res/drawable/icon.png" not in sus_paths

    def test_extract_stores_android_type_override(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        # AXML magic — Magika would likely misclassify, but stored_type
        # should be "android_binary_xml"
        axml_data = b'\x03\x00\x08\x00' + b'\x00' * 50
        apk_path = _create_fake_apk(str(tmp_path), {
            "res/layout/main.xml": axml_data,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        result = ext.extract()
        assert result is not None
        axml_resources = [r for r in result["resources"]
                          if r.path == "res/layout/main.xml"]
        assert len(axml_resources) == 1
        assert axml_resources[0].filetype_magika == "android_binary_xml"
        assert axml_resources[0].is_suspicious is False

    def test_extract_skips_non_res_non_assets(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "lib/armeabi-v7a/libnative.so": b"\x7fELF" + b"\x00" * 50,
            "META-INF/MANIFEST.MF": b"Manifest-Version: 1.0\n",
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        result = ext.extract()
        if result:
            res_paths = [r.path for r in result["resources"]]
            assert "lib/armeabi-v7a/libnative.so" not in res_paths
            assert "META-INF/MANIFEST.MF" not in res_paths

    def test_prepare_export_includes_suspicious_flag(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "assets/evil.bin": b"\x7fELF" + b"\x00" * 100,
            "res/drawable/ok.png": b"\x89PNG\r\n\x1a\n" + b"\x00" * 50,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        # Map filenames to Magika labels so the ELF payload gets flagged
        def _magika_side_effect(data):
            if data[:4] == b"\x7fELF":
                return MagicMock(output=MagicMock(label="elf"))
            return MagicMock(output=MagicMock(label="png"))

        mock_magika = MagicMock()
        mock_magika.identify_bytes.side_effect = _magika_side_effect

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        with patch("magika.Magika", return_value=mock_magika):
            ext.extract()
        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is not None
        data, col_names, col_types = result
        assert "is_suspicious" in col_names
        sus_idx = col_names.index("is_suspicious")
        # At least one row should have is_suspicious=1
        sus_values = [row[sus_idx] for row in data]
        assert 1 in sus_values


# ============================================================================
# APKNativeLibExtractor
# ============================================================================

class TestAPKNativeLibExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_native_libs"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_native_libs"

    def test_extract_finds_native_libs(self, tmp_path):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor
        from redb.models.dataclasses import APKNativeLib

        # Create APK with a native lib inside
        apk_path = _create_fake_apk(str(tmp_path), {
            "lib/armeabi-v7a/libnative.so": b"\x7fELF" + b"\x00" * 100,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()
        exporters = [MagicMock()]

        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is not None
        assert isinstance(result, dict)
        assert "native_libs" in result
        assert len(result["native_libs"]) >= 1
        assert isinstance(result["native_libs"][0], APKNativeLib)
        assert result["native_libs"][0].abi == "armeabi-v7a"

    def test_extract_detects_packer_libs(self, tmp_path):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        # Create APK with a known packer lib
        apk_path = _create_fake_apk(str(tmp_path), {
            "lib/armeabi-v7a/libjiagu.so": b"\x7fELF" + b"\x00" * 50,
            "lib/armeabi-v7a/libnormal.so": b"\x7fELF" + b"\x00" * 50,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()
        exporters = [MagicMock()]

        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is not None
        packer_libs = [lib for lib in result["native_libs"] if lib.is_known_packer]
        assert len(packer_libs) >= 1  # libjiagu.so is a known packer

    def test_extract_no_native_libs(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # The fake APK has no lib/*.so files
        mock_apk.get_files.return_value = ["classes.dex", "AndroidManifest.xml"]
        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is None


# ============================================================================
# APKInconsistencyTestsExtractor
# ============================================================================

class TestAPKInconsistencyTestsExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_inconsistency_tests"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_inconsistency_tests"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor
        from redb.models.dataclasses import APKInconsistencyTests

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKInconsistencyTests)

    def test_extract_clean_apk_no_anomalies(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        # A clean APK should have mostly False values
        assert result.test_zip_bomb is not None  # Should be set (True or False)


# ============================================================================
# APK workers.py integration — module registry
# ============================================================================

class TestAPKModuleRegistry:

    def test_all_apk_modules_in_registry(self):
        from redb.workers import get_module_by_name

        apk_modules = [
            "APKFeaturesExtractor",
            "APKManifestExtractor",
            "APKPermissionsExtractor",
            "APKSignatureExtractor",
            "APKDexExtractor",
            "APKResourceExtractor",
            "APKNativeLibExtractor",
            "APKInconsistencyTestsExtractor",
        ]
        for name in apk_modules:
            module_class = get_module_by_name(name)
            assert module_class is not None, f"{name} not found in module registry"

    def test_apk_module_classes_correct(self):
        from redb.workers import get_module_by_name
        from redb.extractors.apk_extractors import (
            APKFeaturesExtractor,
            APKManifestExtractor,
            APKPermissionsExtractor,
            APKSignatureExtractor,
            APKDexExtractor,
            APKResourceExtractor,
            APKNativeLibExtractor,
            APKInconsistencyTestsExtractor,
        )

        assert get_module_by_name("APKFeaturesExtractor") is APKFeaturesExtractor
        assert get_module_by_name("APKManifestExtractor") is APKManifestExtractor
        assert get_module_by_name("APKPermissionsExtractor") is APKPermissionsExtractor
        assert get_module_by_name("APKSignatureExtractor") is APKSignatureExtractor
        assert get_module_by_name("APKDexExtractor") is APKDexExtractor
        assert get_module_by_name("APKResourceExtractor") is APKResourceExtractor
        assert get_module_by_name("APKNativeLibExtractor") is APKNativeLibExtractor
        assert get_module_by_name("APKInconsistencyTestsExtractor") is APKInconsistencyTestsExtractor


# ============================================================================
# APK filetype guard — workers.py dispatch
# ============================================================================

class TestAPKWorkerDispatch:

    def test_apk_excluded_from_die_guard(self):
        """APK filetype should be in the exclusion set alongside macho for DIE/BasicProperties/Hash."""
        import redb.workers as workers_mod
        import inspect

        source = inspect.getsource(workers_mod.process_binary_file)
        # The guards should exclude "apk" from DIE, BasicProperties, HashExtractor.
        # The exact tuple may grow as new text-based formats are added (e.g.
        # "javascript"), so we check that "apk" is present in a filetype
        # exclusion guard rather than matching the full tuple literally.
        assert 'filetype not in ("macho", "apk"' in source

    def test_apk_dispatch_branch_exists(self):
        """The APK dispatch branch should exist and registry should provide all APK extractors."""
        import inspect
        import redb.workers as workers_mod
        from redb.extractor_registry import get_filetype_modules

        # Verify the APK branch exists in process_binary_file
        source = inspect.getsource(workers_mod.process_binary_file)
        assert 'elif filetype == "apk"' in source

        # Verify all APK extractors are registered and loadable
        apk_modules = get_filetype_modules("apk")
        apk_names = {m.__name__ for m in apk_modules}
        for expected in [
            "APKFeaturesExtractor", "APKManifestExtractor",
            "APKPermissionsExtractor", "APKSignatureExtractor",
            "APKDexExtractor", "APKResourceExtractor",
            "APKNativeLibExtractor", "APKInconsistencyTestsExtractor",
        ]:
            assert expected in apk_names, f"{expected} not in APK registry"

    def test_apk_dispatch_runs_basic_and_hash(self):
        """The APK dispatch branch should run BasicPropertiesExtractor and HashExtractor."""
        import redb.workers as workers_mod
        import inspect

        source = inspect.getsource(workers_mod.process_binary_file)
        # Find the apk block
        apk_idx = source.index('elif filetype == "apk"')
        apk_block = source[apk_idx:apk_idx + 4000]
        assert "BasicPropertiesExtractor" in apk_block
        assert "HashExtractor" in apk_block


# ============================================================================
# APKExtractor base class
# ============================================================================

class TestAPKExtractorBase:

    def test_binary_property(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        # binary property should return the file content
        with open(apk_path, "rb") as f:
            expected = f.read()
        assert ext.binary == expected

    def test_is_valid_apk_with_apk(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext._is_valid_apk() is True

    def test_is_valid_apk_without_apk(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, _, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=None)
        ext.apk = None
        assert ext._is_valid_apk() is False

    def test_list_files(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        files = ext._list_files()
        assert len(files) == 5
        assert "classes.dex" in files

    def test_get_zip_file(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        zf = ext._get_zip_file()
        assert zf is not None
        zf.close()

    def test_sha256_computed_correctly(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        # Verify sha256 matches actual file content
        with open(apk_path, "rb") as f:
            expected_sha256 = hashlib.sha256(f.read()).hexdigest()
        assert ext.sha256 == expected_sha256