예제 #1
0
    def reboot(self, wait_cpu_low=True, usage=20, duration=10, timeout=120):
        '''重启手机
        
        :param wait_cpu_low:   是否等待CPU使用率降低
        :type wait_cpu_low:    bool
        :param usage:          cpu使用率阈值
        :type  usage:          int
        :param duration:       持续时间(秒)
        :type  duration:       int
        :param timeout:        超时时间,超市时间到后,无论当前CPU使用率是多少,都会返回
        :type  timeout:        int
        '''
        pattern = re.compile(r'^.+:\d+$')
        try:
            ret = self.run_driver_cmd('reboot', True, retry_count=1, timeout=30)
            if ret == 'false': return
        except RuntimeError as e:
            logger.warn('reboot: %r' % e)
            if pattern.match(self.device_id):
                try:
                    self.adb.reboot(60)
                except RuntimeError:
                    logger.warn('reboot: %s' % e)
                    # 虚拟机会出现明明重启成功却一直不返回的情况
            else:
                self.adb.reboot(0)  # 不能使用reboot shell命令,有些手机需要root权限才能执行

        time.sleep(10)  # 防止设备尚未关闭,一般重启不可能在10秒内完成
        self.adb.wait_for_boot_complete()
        self._adb = None  # 重启后部分属性可能发生变化,需要重新实例化

        if wait_cpu_low == True:
            self.wait_for_cpu_usage_low(usage, duration, timeout)
예제 #2
0
 def _run_server(self, server_name):
     '''运行系统测试桩
     '''
     if not self.adb.is_rooted():
         try:
             self.adb.start_service('%s/.service.HelperService' % server_name, {'serviceName': server_name})
         except RuntimeError:
             logger.warn('start helper server failed')
             self.adb.start_activity('%s/.activity.StartServiceActivity' % server_name, extra={'serviceName': 'HelperService'}, wait=False)
             time.sleep(1)
         return self._server_opend()
     
     timeout = 10
     time0 = time.time()
     while time.time() - time0 < timeout:
         try:
             ret = self.run_driver_cmd('runServer', server_name, root=self.adb.is_rooted(), retry_count=1, timeout=10)
             logger.debug('Run server %s' % ret)
             if 'service run success' in ret:
                 # wait for parent process exit
                 time.sleep(0.5)
             elif 'service is running' in ret:
                 pass
             elif 'java.lang.UnsatisfiedLinkError' in ret:
                 raise RuntimeError('启动系统测试桩进程失败:\n%s' % ret)
         except TimeoutError as e:
             logger.warn('Run server timeout: %s' % e)
         
         if self._server_opend(): return True
         time.sleep(1)
     return False
예제 #3
0
    def refresh_media_store(self, file_path=""):
        """刷新图库,显示新拷贝到手机的图片
        """
        from qt4a.androiddriver.adb import TimeoutError

        command = ""
        if not file_path:
            if (hasattr(self, "_last_refresh_all")
                    and time.time() - self._last_refresh_all < 2 * 60):
                logger.warn("[DeviceDriver] 120S内不允许全盘重复刷新")
                return
            sdcard_path = self.get_external_sdcard_path()
            command = (
                "am broadcast -a android.intent.action.MEDIA_MOUNTED --ez read-only false -d file://%s"
                % sdcard_path)
            self._last_refresh_all = time.time()
        else:
            if file_path.startswith("/sdcard/"):
                file_path = self.get_external_sdcard_path() + file_path[7:]
            command = (
                "am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://%s"
                % file_path)
        try:
            self.adb.run_shell_cmd(command, self.adb.is_rooted())
        except TimeoutError:
            logger.exception("refresh_media_store failed")
            return False
        # self.adb.run_shell_cmd('am broadcast -a android.intent.action.BOOT_COMPLETED')
        if file_path and self.adb.get_sdk_version() >= 16:
            return self._wait_for_media_available(file_path)
예제 #4
0
    def pull(self, device_id, src_file, dst_file):
        '''adb pull
        '''
        time0 = time.time()
        self._transport(device_id)
        self._send_command('sync:')
        mode, fsize, ftime = self._sync_read_mode(src_file)
        if mode == 0:
            self._sock.close()
            self._sock = None
            raise AdbError('remote object %r does not exist' % src_file)

        src_file = utf8_encode(src_file)
        data = b'RECV' + struct.pack(b'I', len(src_file)) + src_file
        self._sock.send(data)
        f = open(dst_file, 'wb')
        data_size = 0
        last_data = b''
        while True:
            result = self._sock.recv(8)
            if len(result) != 8:
                logger.warn('返回数据错误:%r' % result)

            last_data += result
            if len(last_data) < 8:
                continue
            else:
                result = last_data[:8]
                last_data = last_data[8:]

            psize = struct.unpack(b'I', result[4:])[0]  # 每个分包大小

            if result[:4] == b'DONE': break
            elif result[:4] == b'FAIL':
                raise AdbError(self._sock.recv(psize))
            elif result[:4] != b'DATA':
                raise AdbError('pull_file error')

            result = self._recv(psize - len(last_data))
            result = last_data + result
            if len(result) >= psize:
                last_data = result[psize:]
                result = result[:psize]
            else:
                raise ValueError('数据长度不一致,期望值:%d 实际值:%d' %
                                 (psize, len(result)))
            f.write(result)
            data_size += len(result)

        f.close()
        self._sock.send(b'QUIT' + struct.pack(b'I', 0))
        time_cost = time.time() - time0
        self._sock.close()
        self._sock = None
        if data_size > 0:
            return '%d KB/s (%d bytes in %fs)' % (int(
                data_size / 1000 / time_cost) if time_cost > 0 else 65535,
                                                  data_size, time_cost)
        else:
            return ''
예제 #5
0
    def click(self, control, x, y, sleep_time=0):
        if x < 0 or y < 0:
            raise RuntimeError("坐标错误:(%d, %d)" % (x, y))

        try:
            if not control:
                result = self.send_command(EnumCommand.CmdClick,
                                           X=x,
                                           Y=y,
                                           SleepTime=int(sleep_time * 1000))
            else:
                result = self.send_command(
                    EnumCommand.CmdClick,
                    Control=control,
                    X=x,
                    Y=y,
                    SleepTime=int(sleep_time * 1000),
                )
            # print (result['Result'])
            return result["Result"]
        except AndroidSpyError as e:
            if str(e).find("java.lang.SecurityException") >= 0:
                # 有时操作过快会出现该问题
                return False
            elif "ErrControlNotShown" in str(e):
                return False
            elif str(e) == "控件已失效":
                # 认为点击成功了
                pic_name = "%s.png" % int(time.time())
                logger.warn("%s %s" % (e, pic_name))
                self._device_driver.take_screen_shot(pic_name)
                return True
            else:
                raise e
예제 #6
0
    def send(self, data):
        if not self._connect:
            if not self.connect(): return None
        try:
            self._sock.send(data.encode('utf8'))
        except socket.error as e:
            logger.info('发送%r错误: %s' % (data, e))
            self._sock.close()
            self._connect = False
            return None

        expect_len = self.recv(8)
        if not expect_len: return None

        expect_len = int(expect_len, 16) + 1
        recv_buff = ''
        while len(recv_buff) < expect_len:
            buff = self.recv(expect_len - len(recv_buff))
            if not buff:
                logger.warn('Socket closed when recv rsp for %r' % data)

            while True:
                try:
                    recv_buff += buff.decode('utf8')
                    break
                except UnicodeDecodeError:
                    buff += self.recv(1)

        return recv_buff
예제 #7
0
    def wait_for_recv_message(self, timeout=120, interval=0.5):
        '''等待接收消息完成
        '''
        from tuia.exceptions import ControlNotFoundError
        time0 = time.time()
        recving = self.Controls['左上角微信']
        try:
            recving.wait_for_exist(20, 0.5)
        except ControlNotFoundError:
            logger.warn('wait for loading timeout')

        while time.time() - time0 < timeout:
            if not recving.exist() or not recving.visible:
                time.sleep(2)
                continue
            if '(' not in self.Controls['左上角微信'].text:
                time.sleep(1)
                continue
            break
        old_text = self.Controls['左上角微信'].text
        time0 = time.time()
        while time.time() - time0 < 5:
            time.sleep(2)
            new_text = self.Controls['左上角微信'].text
            if new_text != old_text:
                old_text = new_text
                time.sleep(3)
            else:
                break
예제 #8
0
 def _start(self, clear_state=True, kill_process=True, start_extra_params={}):
     '''启动Android微信
     '''
     
     if kill_process == True:
         self.device.kill_process(self.package_name)  # 杀死已有进程
         
     if clear_state == True:
         # 清登录态,不清数据
         logger.warn('Clearing user state')
         self.run_shell_cmd('rm /data/data/%s/shared_prefs/%s*.xml' % (self.package_name, self.package_name))
         self.run_shell_cmd('rm /data/data/%s/MicroMsg/*.cfg' % (self.package_name))
         self.run_shell_cmd('rm /data/data/%s/shared_prefs/system_config_prefs.xml' % (self.package_name))
         
     # try:
     #     # 目前还不支持xwalk内核,先强制不使用该内核
     #     self.run_shell_cmd('rm -r /data/data/%s/app_xwalkconfig' % (self.package_name))
     #     self.run_shell_cmd('touch /data/data/%s/app_xwalkconfig' % (self.package_name))
     #     self.run_shell_cmd('chmod 777 /data/data/%s/app_xwalkconfig' % (self.package_name))
     #     self.run_shell_cmd('rm -r /data/data/%s/app_xwalk_*' % (self.package_name))
     # except:
     #     logger.exception('Disable xwalk failed')
         
     try:
         self.device.start_activity(self.startup_activity, extra=start_extra_params) 
     except TimeoutError:
         logger.exception('Start Android Wechat Failed')
         self.device.clear_data(self.package_name)
         self.device.start_activity(self.startup_activity, extra=start_extra_params)
예제 #9
0
 def get_current_activity(self):
     '''获取当前窗口
     '''
     timeout = 10
     time0 = time.time()
     result = None
     while time.time() - time0 < timeout:
         if not self.adb.is_rooted():
             result = self._get_current_window()
         else:
             try:
                 result = self._send_command('GetCurrentWindow')
             except SocketError as e:
                 raise e
             except RuntimeError as e:
                 logger.warn('GetCurrentWindow error: %s' % e)
         if not result or result == 'null':
             # 一般是设备黑屏之类
             time.sleep(0.5)
             continue
         return result
     
     if not self.adb.is_rooted(): return None
     
     logger.warn('GetCurrentWindow failed')
     return self._send_command('GetCurrentActivity')
예제 #10
0
 def get_imei(self):
     '''获取设备imei号
     '''
     try:
         return self.adb.get_device_imei()
     except RuntimeError as e:
         logger.warn('Read device imei by dumpsys failed: %s' % e)
         return self._device_driver.get_device_imei()
예제 #11
0
 def close_activity(self, activity):
     '''关闭Activity
     '''
     try:
         return self._close_activity(activity)
     except ProcessExitError:
         logger.warn('close_activity error: process %s not exist' % self._process_name)
         return -3  # 进程退出
예제 #12
0
 def clear_camera_default_app(self):
     '''清除默认相机应用
     '''
     from qt4a.androiddriver.util import logger
     if self.is_rooted():
         return self._device_driver.clear_default_app('android.media.action.IMAGE_CAPTURE')
     else:
         logger.warn('clear_camera_default_app need root')
예제 #13
0
 def get_system_boot_time(self):
     '''获取系统启动时间,单位为秒
     '''
     for _ in range(3):
         ret = self.run_driver_cmd('getSystemBootTime', root=self.adb.is_rooted())
         if ret and ret.isdigit(): return int(ret / 1000)
         logger.warn('getSystemBootTime return %r' % ret)
         time.sleep(2)
     return 0
예제 #14
0
 def close_activity(self, activity):
     """关闭Activity
     """
     try:
         return self._close_activity(activity)
     except ProcessExitError:
         logger.warn("close_activity error: process %s not exist" %
                     self._process_name)
         return -3  # 进程退出
예제 #15
0
파일: androidapp.py 프로젝트: wolf937/QT4A
 def _get_view_id(self, str_id):
     '''从控件字符串ID获取整型ID
     '''
     if not str_id: raise RuntimeError('控件ID不能为空')
     try:
         return self.device._get_view_id(self.package_name, str_id)
     except RuntimeError, e:
         logger.warn(str(e))
         return None
예제 #16
0
 def take_screen_shot(self, path, quality=90):
     '''截屏
     '''
     result = self.adb.run_shell_cmd('%s/screenshot capture -q %s' % (qt4a_path, quality), binary_output=True)
     # 为避免pull文件耗时,直接写到stdout
     if len(result) < 256:
         logger.warn('Take screenshot failed: %s' % result)
         return False
     with open(path, 'wb') as fp:
         fp.write(result)
     return True
예제 #17
0
 def kill_process(self, package_name):
     '''杀死进程
     '''
     try:
         self.run_driver_cmd('killProcess', package_name, root=self.adb.is_rooted())
     except RuntimeError as e:
         logger.warn('killProcess error: %r' % e)
     if not self.adb.is_rooted(): return
     for _ in range(3):
         ret = self.adb.kill_process(package_name)
         if ret == None: return True
         elif ret == False: return False
     return False
예제 #18
0
 def recv_data(data_len):
     data = ''
     while len(data) < data_len:
         try:
             buff = sock.recv(data_len - len(data))
             if not buff:
                 logger.warn('screenshot socket closed')
                 return
             data += buff
         except socket.error as e:
             logger.warn('recv screenshot data error: %s' % e)
             return
     return data
예제 #19
0
 def connect(self):
     self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     # socket.setdefaulttimeout(120)
     for i in range(3):
         try:
             self._sock.connect((self._addr, self._port))
             self._sock.settimeout(self._timeout)
             self._connect = True
             return True
         except Exception as e:
             logger.warn('connect (%s, %s) error: %s' %
                         (self._addr, self._port, e))
             if i == 2: return False  # 连接失败
             time.sleep(1)
예제 #20
0
 def _wait_for_event(self, thread_id, timeout):
     '''等待事件
     '''
     if self._get_lock(thread_id).is_set(): return
     time0 = time.time()
     ret = self._get_lock(thread_id).wait(timeout)
     if ret:
         cost_time = time.time() - time0
         logger.debug('thread %s wait %s S' % (thread_id, cost_time))
     else:
         # 超时
         logger.warn('thread %s wait for sync event timeout' % thread_id)
         self.resume_thread(thread_id)  # 防止出错后一直等待
     return ret
예제 #21
0
 def create_socket(self):
     '''创建socket对象
     '''
     self._service_name = 'xweb_devtools_remote_%d' % self._pid
     try:
         sock = self._device.adb.create_tunnel(self._service_name,
                                               'localabstract')
         if sock:
             return sock
     except:
         logger.warn('create socket tunnel %s failed' % self._service_name)
     self._driver.call_static_method(
         'org.xwalk.core.internal.XWalkPreferencesInternal', 'setValue',
         self.hashcode, '', 'remote-debugging', True)
     return self.create_socket()
예제 #22
0
 def clear_data(self, package_name):
     '''清理应用数据
     
     :param package_name: 包名
     :type package_name:  string
     '''
     if not self.adb.get_package_path(package_name): return True
     cmdline = 'pm clear %s' % package_name
     if self.adb.is_rooted():
         return 'Success' in self.run_shell_cmd(cmdline, True)
     else:
         result = self.run_shell_cmd(cmdline)
         if 'Success' in result:
             return True
         logger.warn('clear %s data failed: %s' % (package_name, result))
         return 'Success' in self.run_as(package_name, cmdline)
예제 #23
0
 def _take_screen_shot(self, path, _format='png', quality=90):
     """
     使用android系统命令截图
     # todo:使用android的java接口替换该方案
     """
     # result = self.adb.run_shell_cmd(
     #     "sh %s/SpyHelper.sh takeScreenshot %s %s %s" % (qt4a_path, path, _format, quality), self.adb.is_rooted())
     # if 'true' in result:
     #     return True
     # logger.warn("Take screenshot by SpyHelper.sh failed: %s" % result)
     try:
         result = self.adb.run_shell_cmd("screencap -p", binary_output=True)
         return result
     except Exception as e:
         logger.warn("Take screenshot failed: %s" % traceback.format_exc(e))
         return False
예제 #24
0
 def take_screen_shot(self, path, quality=90):
     """截屏
     """
     if self.adb.get_sdk_version() >= 29:
         result = self._take_screen_shot(path)
     else:
         result = self.adb.run_shell_cmd("%s/screenshot capture -q %s" %
                                         (qt4a_path, quality),
                                         binary_output=True)
     # 为避免pull文件耗时,直接写到stdout
     if len(result) < 256:
         logger.warn("Take screenshot failed: %s" % result)
         return False
     with open(path, "wb") as fp:
         fp.write(result)
     return True
예제 #25
0
 def create_tunnel(self, device_id, remote_addr):
     """创建与手机中服务端的连接通道
     """
     self._transport(device_id)
     self._sock.settimeout(2)
     try:
         self._send_command(remote_addr)
     except AdbError as e:
         if "closed" == e.args[0]:
             return ""
         raise
     except socket.timeout as e:
         logger.warn("create_tunnel timeout")
         return ""
     sock = self._sock
     self._sock = None
     return sock
예제 #26
0
 def create_tunnel(self, device_id, remote_addr):
     '''创建与手机中服务端的连接通道
     '''
     self._transport(device_id)
     self._sock.settimeout(2)
     try:
         self._send_command(remote_addr)
     except AdbError as e:
         if 'closed' == e.args[0]:
             return ''
         raise
     except socket.timeout as e:
         logger.warn('create_tunnel timeout')
         return ''
     sock = self._sock
     self._sock = None
     return sock
예제 #27
0
    def _run_server(self, server_name):
        """运行系统测试桩
        """
        if not self.adb.is_rooted():
            try:
                self.adb.start_service(
                    "%s/.service.HelperService" % server_name,
                    {"serviceName": server_name},
                )
            except RuntimeError:
                logger.warn("start helper server failed")
                self.adb.start_activity(
                    "%s/.activity.StartServiceActivity" % server_name,
                    extra={"serviceName": "HelperService"},
                    wait=False,
                )
                time.sleep(1)
            return self._server_opend()

        timeout = 10
        time0 = time.time()
        while time.time() - time0 < timeout:
            try:
                ret = self.run_driver_cmd(
                    "runServer",
                    server_name,
                    root=self.adb.is_rooted(),
                    retry_count=1,
                    timeout=10,
                )
                logger.debug("Run server %s" % ret)
                if "service run success" in ret:
                    # wait for parent process exit
                    time.sleep(0.5)
                elif "service is running" in ret:
                    pass
                elif "java.lang.UnsatisfiedLinkError" in ret:
                    raise RuntimeError("启动系统测试桩进程失败:\n%s" % ret)
            except TimeoutError as e:
                logger.warn("Run server timeout: %s" % e)

            if self._server_opend():
                return True
            time.sleep(1)
        return False
예제 #28
0
    def send(self, data):
        if not self._connect:
            if not self.connect(): return None
        try:
            self._sock.send(data.encode('utf8'))
        except socket.error as e:
            logger.info('发送%r错误: %s' % (data, e))
            self._sock.close()
            self._connect = False
            return None

        expect_len = self.recv(8)
        if not expect_len: return None

        expect_len = int(expect_len, 16) + 1
        recv_buff = ''
        max_utf8_length = 6

        while len(recv_buff) < expect_len:
            buff = self.recv(expect_len - len(recv_buff))

            if not buff:
                logger.warn('Socket closed when recv rsp for %r' % data)

            while True:
                try:
                    recv_buff += buff.decode('utf8')
                    break
                except UnicodeDecodeError:
                    if len(buff) > max_utf8_length:
                        for i in range(max_utf8_length):
                            this_buff = buff[:i - max_utf8_length]
                            try:
                                recv_buff += this_buff.decode('utf8')
                            except UnicodeDecodeError:
                                pass
                            else:
                                buff = buff[i - max_utf8_length:]
                                break
                        else:
                            raise RuntimeError('Invalid utf-8 bytes: %r' %
                                               buff)
                    buff += self.recv(1)

        return recv_buff
예제 #29
0
파일: device.py 프로젝트: Tencent/QT4A
    def push_file(self, src_path, dst_path):
        '''向手机中拷贝文件
        
        :param src_path: PC上的源路径
        :type src_path:  string
        :param dst_path: 手机上的目标路径
        :type dst_path:  string
        '''

        if not os.path.exists(src_path):
            raise RuntimeError('File: %s not exist' % src_path)
        file_size = os.path.getsize(src_path)
        is_zip = False
        if file_size >= 5 * 1024 * 1024:
            is_zip = True
            zip_file_path = src_path + '.zip'
            zip_file = zipfile.ZipFile(zip_file_path, 'w',
                                       zipfile.ZIP_DEFLATED)
            if dst_path[-1] == '/':
                # filename not specified
                filename = os.path.split(src_path)[-1]
            else:
                filename = dst_path.split('/')[-1]
            zip_file.write(src_path, filename)
            zip_file.close()
            src_path = zip_file_path
            dst_path += '.zip'
        ret = self.adb.push_file(src_path, dst_path)
        if is_zip:
            os.remove(src_path)
            if not self._device_driver.unzip_file(
                    dst_path, dst_path[:dst_path.rfind('/')]):
                logger.warn('unzip file %s failed' % dst_path)
                ret = self.adb.push_file(src_path[:-4], dst_path[:-4])
            elif dst_path.startswith('/data/'):
                self.adb.chmod(dst_path[:-4], '744')
            self.delete_file(dst_path)
            dst_path = dst_path[:-4]
        try:
            self.run_shell_cmd('touch "%s"' % dst_path)  # 修改文件修改时间
        except:
            logger.exception('touch file %s error' % dst_path)
        return ret
예제 #30
0
 def lock_keyguard(self):
     '''锁屏
     '''
     if self.is_keyguard_locked(): return True  # 已经是锁屏状态
     if self.adb.is_rooted():
         self.set_screen_lock_enable(True)
     if self.adb.get_sdk_version() >= 16:
         # 发送电源键
         self.send_key(KeyCode.KEYCODE_POWER)
         return True
     
     self._last_activity_before_lock = self._get_current_activity(True)  # 保存锁屏前的Activity
     logger.debug('锁屏前Activity为:%r' % self._last_activity_before_lock)
     ret = self._lock_keyguard()
     if not ret: 
         logger.warn('lock keyguard failed')
         self.wake_screen(False)
         time.sleep(1)
         self.wake_screen(True)
         return self.is_keyguard_locked()
     return True