- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
1180 lines
44 KiB
Python
1180 lines
44 KiB
Python
"""
|
|
Android Telephony MBMS 组件 — MbmsDownloadManager, MbmsStreamingManager, DownloadRequest, StreamingService 等
|
|
方法签名完全对齐 Android SDK (android.telephony.mbms 包)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import time
|
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsErrors
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsErrors(Stub):
|
|
"""MbmsErrors — MBMS 错误代码基类"""
|
|
|
|
SUCCESS = 0
|
|
ERROR_NO_UNIQUE_MIDDLEWARE = 1
|
|
ERROR_MIDDLEWARE_NOT_BOUND = 2
|
|
ERROR_MIDDLEWARE_LOST = 3
|
|
ERROR_MIDDLEWARE_NOT_YET_READY = 4
|
|
ERROR_OUT_OF_MEMORY = 5
|
|
ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE = 6
|
|
ERROR_MIDDLEWARE_PERMANENTLY_UNAVAILABLE = 7
|
|
ERROR_MIDDLEWARE_UNABLE_TO_CREATE_SESSION = 8
|
|
ERROR_MIDDLEWARE_UNABLE_TO_CREATE_DATA_SESSION = 9
|
|
ERROR_MIDDLEWARE_UNABLE_TO_CREATE_DOWNLOAD = 10
|
|
ERROR_MIDDLEWARE_UNABLE_TO_CREATE_STREAMING = 11
|
|
ERROR_MIDDLEWARE_INTERNAL_ERROR = 12
|
|
ERROR_MIDDLEWARE_NOT_SUPPORTED = 13
|
|
ERROR_MIDDLEWARE_INVALID_INPUT = 14
|
|
ERROR_MIDDLEWARE_INVALID_SERVICE_ID = 15
|
|
ERROR_MIDDLEWARE_INVALID_FILE_PATH = 16
|
|
ERROR_MIDDLEWARE_DUPLICATE_SERVICE = 17
|
|
ERROR_MIDDLEWARE_SERVICE_NOT_FOUND = 18
|
|
ERROR_MIDDLEWARE_SERVICE_ALREADY_RUNNING = 19
|
|
ERROR_MIDDLEWARE_SERVICE_NOT_RUNNING = 20
|
|
ERROR_MIDDLEWARE_INVALID_SAI = 21
|
|
ERROR_MIDDLEWARE_INVALID_CELL_ID = 22
|
|
ERROR_MIDDLEWARE_UNABLE_TO_FETCH_PREFIX = 23
|
|
ERROR_MIDDLEWARE_TEMP_FILE_EXPIRED = 24
|
|
ERROR_MIDDLEWARE_FILE_ALREADY_COMPLETE = 25
|
|
ERROR_MIDDLEWARE_FILE_ALREADY_IN_PROGRESS = 26
|
|
ERROR_MIDDLEWARE_STALE_SERVICE_ANNOUNCEMENT = 27
|
|
ERROR_MIDDLEWARE_MISSING_FILE_INFO = 28
|
|
ERROR_MIDDLEWARE_NO_EXPIRATION = 29
|
|
ERROR_MIDDLEWARE_UNKNOWN_FILE_INFO = 30
|
|
ERROR_MIDDLEWARE_UNKNOWN_SIGNAL = 31
|
|
ERROR_MIDDLEWARE_INSUFFICIENT_STORAGE = 32
|
|
ERROR_MIDDLEWARE_INSUFFICIENT_MEMORY = 33
|
|
ERROR_MIDDLEWARE_UNABLE_TO_CLOSE_FILE = 34
|
|
ERROR_MIDDLEWARE_UNABLE_TO_OPEN_FILE = 35
|
|
ERROR_MIDDLEWARE_IO_ERROR = 36
|
|
ERROR_MIDDLEWARE_CONCURRENT_SERVICE_LIMIT = 37
|
|
ERROR_MIDDLEWARE_INVALID_DOWNLOAD_ID = 38
|
|
|
|
class InitializationErrors(Stub):
|
|
"""MbmsErrors.InitializationErrors — 初始化错误"""
|
|
ERROR_DUPLICATE_INITIALIZE = 101
|
|
ERROR_APP_PERMISSIONS_NOT_GRANTED = 102
|
|
ERROR_UNABLE_TO_INITIALIZE = 103
|
|
ERROR_INTERNAL = 104
|
|
ERROR_MIDDLEWARE_NOT_BOUND = 105
|
|
|
|
class DownloadErrors(Stub):
|
|
"""MbmsErrors.DownloadErrors — 下载错误"""
|
|
ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT = 201
|
|
ERROR_UNKNOWN_DOWNLOAD_REQUEST = 202
|
|
ERROR_DOWNLOAD_NOT_FOUND = 203
|
|
ERROR_DOWNLOAD_ALREADY_EXISTS = 204
|
|
ERROR_DOWNLOAD_INACTIVE = 205
|
|
ERROR_FILE_UNAVAILABLE = 206
|
|
ERROR_SERVICE_ID_NOT_DOWNLOAD = 207
|
|
ERROR_MALFORMED_FILE_URI = 208
|
|
ERROR_STALE_FILE_INFO = 209
|
|
ERROR_TEMP_FILE_ROOT_NOT_SET = 210
|
|
ERROR_UNKNOWN_FILE_INFO = 211
|
|
ERROR_NO_DOWNLOAD_FOR_FILE = 212
|
|
|
|
class StreamingErrors(Stub):
|
|
"""MbmsErrors.StreamingErrors — 流错误"""
|
|
ERROR_STREAMING_NOT_ALLOWED = 301
|
|
ERROR_STREAMING_SERVICE_NOT_STARTED = 302
|
|
ERROR_STREAMING_SERVICE_ALREADY_STARTED = 303
|
|
ERROR_STREAMING_SERVICE_NOT_VISIBLE = 304
|
|
ERROR_STREAMING_MALFORMED_SERVICE_ANNOUNCEMENT = 305
|
|
ERROR_STREAMING_DUPLICATE_SERVICE_ANNOUNCEMENT = 306
|
|
ERROR_STREAMING_SERVICE_ANNOUNCEMENT_EXPIRED = 307
|
|
ERROR_STREAMING_RADIO_RESOURCE_REJECTED = 308
|
|
ERROR_STREAMING_RADIO_RESOURCE_NOT_AVAILABLE = 309
|
|
ERROR_STREAMING_INVALID_SAI_LIST = 310
|
|
ERROR_STREAMING_UNABLE_TO_UPDATE_SUBFLOW = 311
|
|
|
|
class NameTypeErrors(Stub):
|
|
"""MbmsErrors.NameTypeErrors — 名称类型错误"""
|
|
ERROR_NAME_SYSTEM_ERROR = 401
|
|
ERROR_NAME_INVALID_FORMAT = 402
|
|
ERROR_NAME_UNSUPPORTED_CHARACTER_ENCODING = 403
|
|
ERROR_NAME_CONTAINS_INVALID_CHARACTERS = 404
|
|
|
|
class GeneralErrors(Stub):
|
|
"""MbmsErrors.GeneralErrors — 通用错误"""
|
|
ERROR_MIDDLEWARE_NOT_BOUND = 501
|
|
ERROR_OUT_OF_MEMORY = 502
|
|
ERROR_MIDDLEWARE_LOST = 503
|
|
ERROR_MIDDLEWARE_NOT_YET_READY = 504
|
|
ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE = 505
|
|
ERROR_MIDDLEWARE_UNABLE_TO_CREATE_SESSION = 506
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DownloadRequest
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DownloadRequest(Stub):
|
|
"""DownloadRequest — MBMS 下载请求"""
|
|
|
|
# 下载请求常量
|
|
DOWNLOAD_RESULT_SUCCESS = 0
|
|
DOWNLOAD_RESULT_ERROR = 1
|
|
DOWNLOAD_RESULT_ERROR_MEDIA_NOT_FOUND = 2
|
|
DOWNLOAD_RESULT_ERROR_MEDIA_UNAVAILABLE = 3
|
|
DOWNLOAD_RESULT_ERROR_MEDIA_FAILED = 4
|
|
DOWNLOAD_RESULT_ERROR_SERVICE_UNAVAILABLE = 5
|
|
DOWNLOAD_RESULT_ERROR_INSUFFICIENT_STORAGE = 6
|
|
DOWNLOAD_RESULT_ERROR_IO_ERROR = 7
|
|
DOWNLOAD_RESULT_ERROR_FILE_NOT_FOUND = 8
|
|
DOWNLOAD_RESULT_ERROR_OUT_OF_MEMORY = 9
|
|
DOWNLOAD_RESULT_ERROR_RADIO_OFF = 10
|
|
DOWNLOAD_RESULT_ERROR_INTERRUPTED = 11
|
|
DOWNLOAD_RESULT_ERROR_TIMEOUT = 12
|
|
DOWNLOAD_RESULT_ERROR_CANCELLED = 13
|
|
DOWNLOAD_RESULT_ERROR_DOWNLOAD_NOT_STARTED = 14
|
|
|
|
# 下载状态
|
|
DOWNLOAD_STATUS_INACTIVE = 0
|
|
DOWNLOAD_STATUS_ACTIVE = 1
|
|
DOWNLOAD_STATUS_PENDING = 2
|
|
DOWNLOAD_STATUS_PAUSED = 3
|
|
DOWNLOAD_STATUS_COMPLETED = 4
|
|
DOWNLOAD_STATUS_CANCELED = 5
|
|
DOWNLOAD_STATUS_FAILED = 6
|
|
|
|
def __init__(self, service_id: str = "", file_uri: str = "",
|
|
source: Any = None, destination: Any = None,
|
|
app_intent: Any = None):
|
|
super().__init__()
|
|
self._service_id = service_id
|
|
self._file_uri = file_uri
|
|
self._source = source
|
|
self._destination = destination
|
|
self._app_intent = app_intent
|
|
self._subscription_id: int = 0
|
|
self._sai: List[int] = []
|
|
self._app_name: str = ""
|
|
self._app_version: str = ""
|
|
self._storage_type: int = 0
|
|
self._hash: str = ""
|
|
self._request_id: int = 0
|
|
|
|
def getServiceId(self) -> str:
|
|
return self._service_id
|
|
|
|
def getFileUri(self) -> str:
|
|
return self._file_uri
|
|
|
|
def getSource(self) -> Any:
|
|
return self._source
|
|
|
|
def getDestination(self) -> Any:
|
|
return self._destination
|
|
|
|
def getIntent(self) -> Any:
|
|
return self._app_intent
|
|
|
|
def getSubscriptionId(self) -> int:
|
|
return self._subscription_id
|
|
|
|
def setSubscriptionId(self, sub_id: int):
|
|
self._subscription_id = sub_id
|
|
|
|
def getSai(self) -> List[int]:
|
|
return list(self._sai)
|
|
|
|
def setSai(self, sai: List[int]):
|
|
self._sai = list(sai)
|
|
|
|
def getAppName(self) -> str:
|
|
return self._app_name
|
|
|
|
def setAppName(self, name: str):
|
|
self._app_name = name
|
|
|
|
def getAppVersion(self) -> str:
|
|
return self._app_version
|
|
|
|
def setAppVersion(self, version: str):
|
|
self._app_version = version
|
|
|
|
def getStorageType(self) -> int:
|
|
return self._storage_type
|
|
|
|
def setStorageType(self, storage_type: int):
|
|
self._storage_type = storage_type
|
|
|
|
def getHash(self) -> str:
|
|
return self._hash
|
|
|
|
def getRequestId(self) -> int:
|
|
return self._request_id
|
|
|
|
def setRequestId(self, request_id: int):
|
|
self._request_id = request_id
|
|
|
|
def toString(self) -> str:
|
|
return f"DownloadRequest(serviceId={self._service_id}, fileUri={self._file_uri})"
|
|
|
|
class Builder(Stub):
|
|
"""DownloadRequest.Builder — 下载请求构建器"""
|
|
|
|
def __init__(self, service_id: str, file_uri: str):
|
|
super().__init__()
|
|
self._service_id = service_id
|
|
self._file_uri = file_uri
|
|
self._source: Any = None
|
|
self._destination: Any = None
|
|
self._app_intent: Any = None
|
|
self._subscription_id: int = 0
|
|
self._sai: List[int] = []
|
|
self._app_name: str = ""
|
|
self._app_version: str = ""
|
|
self._storage_type: int = 0
|
|
|
|
def setServiceId(self, service_id: str) -> DownloadRequest.Builder:
|
|
self._service_id = service_id
|
|
return self
|
|
|
|
def setFileUri(self, file_uri: str) -> DownloadRequest.Builder:
|
|
self._file_uri = file_uri
|
|
return self
|
|
|
|
def setSource(self, source: Any) -> DownloadRequest.Builder:
|
|
self._source = source
|
|
return self
|
|
|
|
def setDestination(self, destination: Any) -> DownloadRequest.Builder:
|
|
self._destination = destination
|
|
return self
|
|
|
|
def setIntent(self, intent: Any) -> DownloadRequest.Builder:
|
|
self._app_intent = intent
|
|
return self
|
|
|
|
def setSubscriptionId(self, sub_id: int) -> DownloadRequest.Builder:
|
|
self._subscription_id = sub_id
|
|
return self
|
|
|
|
def setSai(self, sai: List[int]) -> DownloadRequest.Builder:
|
|
self._sai = list(sai)
|
|
return self
|
|
|
|
def setAppName(self, name: str) -> DownloadRequest.Builder:
|
|
self._app_name = name
|
|
return self
|
|
|
|
def setAppVersion(self, version: str) -> DownloadRequest.Builder:
|
|
self._app_version = version
|
|
return self
|
|
|
|
def setStorageType(self, storage_type: int) -> DownloadRequest.Builder:
|
|
self._storage_type = storage_type
|
|
return self
|
|
|
|
def build(self) -> DownloadRequest:
|
|
req = DownloadRequest(self._service_id, self._file_uri,
|
|
self._source, self._destination,
|
|
self._app_intent)
|
|
req.setSubscriptionId(self._subscription_id)
|
|
req.setSai(self._sai)
|
|
req.setAppName(self._app_name)
|
|
req.setAppVersion(self._app_version)
|
|
req.setStorageType(self._storage_type)
|
|
return req
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FileInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FileInfo(Stub):
|
|
"""FileInfo — MBMS 文件信息"""
|
|
|
|
def __init__(self, uri: str = "", mime_type: str = "",
|
|
file_size: int = 0, name: str = ""):
|
|
super().__init__()
|
|
self._uri = uri
|
|
self._mime_type = mime_type
|
|
self._file_size = file_size
|
|
self._name = name
|
|
|
|
def getUri(self) -> str:
|
|
return self._uri
|
|
|
|
def getMimeType(self) -> str:
|
|
return self._mime_type
|
|
|
|
def getFileSize(self) -> int:
|
|
return self._file_size
|
|
|
|
def getName(self) -> str:
|
|
return self._name
|
|
|
|
def toString(self) -> str:
|
|
return f"FileInfo(uri={self._uri}, mimeType={self._mime_type}, size={self._file_size})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DownloadStatusListener
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DownloadStatusListener(Stub):
|
|
"""DownloadStatusListener — MBMS 下载状态监听器"""
|
|
|
|
def onStatusChanged(self, request: DownloadRequest, info: FileInfo, status: int):
|
|
"""下载状态改变回调"""
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FileServiceInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FileServiceInfo(Stub):
|
|
"""FileServiceInfo — MBMS 文件服务信息"""
|
|
|
|
def __init__(self, service_id: str = "", service_class: str = "",
|
|
service_announcement: Any = None):
|
|
super().__init__()
|
|
self._service_id = service_id
|
|
self._service_class = service_class
|
|
self._service_announcement = service_announcement
|
|
self._sais: List[int] = []
|
|
self._cells: List[int] = []
|
|
self._files: List[FileInfo] = []
|
|
|
|
def getServiceId(self) -> str:
|
|
return self._service_id
|
|
|
|
def getServiceClass(self) -> str:
|
|
return self._service_class
|
|
|
|
def getServiceAnnouncement(self) -> Any:
|
|
return self._service_announcement
|
|
|
|
def getSai(self) -> List[int]:
|
|
return list(self._sais)
|
|
|
|
def getCells(self) -> List[int]:
|
|
return list(self._cells)
|
|
|
|
def getFiles(self) -> List[FileInfo]:
|
|
return list(self._files)
|
|
|
|
def toString(self) -> str:
|
|
return f"FileServiceInfo(serviceId={self._service_id}, class={self._service_class})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# StreamingService
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class StreamingService(Stub):
|
|
"""StreamingService — MBMS 流媒体服务"""
|
|
|
|
# 流媒体服务状态
|
|
STATE_STOPPED = 0
|
|
STATE_STARTED = 1
|
|
STATE_STALLED = 2
|
|
STATE_PENDING = 3
|
|
STATE_ERROR = 4
|
|
|
|
# 流媒体服务广播标志
|
|
BROADCAST_METHOD_UNICAST = 0
|
|
BROADCAST_METHOD_MULTICAST = 1
|
|
BROADCAST_METHOD_BROADCAST = 2
|
|
|
|
# 流媒体服务信息
|
|
STREAMING_SERVICE_STATE_STOPPED = 0
|
|
STREAMING_SERVICE_STATE_STARTED = 1
|
|
STREAMING_SERVICE_STATE_STALLED = 2
|
|
STREAMING_SERVICE_STATE_PENDING = 3
|
|
STREAMING_SERVICE_STATE_ERROR = 4
|
|
|
|
REASON_NONE = 0
|
|
REASON_BY_USER_REQUEST = 1
|
|
REASON_BY_MIDDLEWARE = 2
|
|
REASON_BY_RADIO_RESOURCE = 3
|
|
REASON_BY_OUT_OF_MEMORY = 4
|
|
REASON_BY_SIGNAL_LOST = 5
|
|
REASON_BY_TEMPORARILY_UNAVAILABLE = 6
|
|
REASON_BY_PERMANENTLY_UNAVAILABLE = 7
|
|
REASON_BY_SERVICE_SHUTDOWN = 8
|
|
REASON_BY_SERVICE_NOT_VISIBLE = 9
|
|
REASON_BY_RADIO_NOT_AVAILABLE = 10
|
|
|
|
def __init__(self, service_id: str = "", service_class: str = ""):
|
|
super().__init__()
|
|
self._service_id = service_id
|
|
self._service_class = service_class
|
|
self._state = StreamingService.STATE_STOPPED
|
|
self._broadcast_method = StreamingService.BROADCAST_METHOD_MULTICAST
|
|
self._callback: Optional[StreamingServiceCallback] = None
|
|
self._audio_description: Any = None
|
|
self._video_description: Any = None
|
|
self._subtitle_descriptions: List[Any] = []
|
|
self._estimated_bitrate: int = 0
|
|
|
|
def getServiceId(self) -> str:
|
|
return self._service_id
|
|
|
|
def getServiceClass(self) -> str:
|
|
return self._service_class
|
|
|
|
def getState(self) -> int:
|
|
return self._state
|
|
|
|
def setState(self, state: int):
|
|
self._state = state
|
|
|
|
def getBroadcastMethod(self) -> int:
|
|
return self._broadcast_method
|
|
|
|
def setBroadcastMethod(self, method: int):
|
|
self._broadcast_method = method
|
|
|
|
def getAudioDescription(self) -> Any:
|
|
return self._audio_description
|
|
|
|
def setAudioDescription(self, desc: Any):
|
|
self._audio_description = desc
|
|
|
|
def getVideoDescription(self) -> Any:
|
|
return self._video_description
|
|
|
|
def setVideoDescription(self, desc: Any):
|
|
self._video_description = desc
|
|
|
|
def getSubtitleDescriptions(self) -> List[Any]:
|
|
return list(self._subtitle_descriptions)
|
|
|
|
def setSubtitleDescriptions(self, descs: List[Any]):
|
|
self._subtitle_descriptions = list(descs)
|
|
|
|
def getEstimatedBitrate(self) -> int:
|
|
return self._estimated_bitrate
|
|
|
|
def setEstimatedBitrate(self, bitrate: int):
|
|
self._estimated_bitrate = bitrate
|
|
|
|
def setCallback(self, callback: StreamingServiceCallback):
|
|
self._callback = callback
|
|
|
|
def getCallback(self) -> Optional[StreamingServiceCallback]:
|
|
return self._callback
|
|
|
|
def start(self):
|
|
"""启动流媒体服务"""
|
|
self._state = StreamingService.STATE_STARTED
|
|
if self._callback:
|
|
self._callback.onStreamStateUpdated(self._state,
|
|
StreamingService.REASON_BY_USER_REQUEST)
|
|
|
|
def stop(self):
|
|
"""停止流媒体服务"""
|
|
self._state = StreamingService.STATE_STOPPED
|
|
if self._callback:
|
|
self._callback.onStreamStateUpdated(self._state,
|
|
StreamingService.REASON_BY_USER_REQUEST)
|
|
|
|
def close(self):
|
|
"""关闭流媒体服务"""
|
|
self._state = StreamingService.STATE_STOPPED
|
|
self._callback = None
|
|
|
|
def toString(self) -> str:
|
|
return f"StreamingService(serviceId={self._service_id}, state={self._state})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# StreamingServiceCallback
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class StreamingServiceCallback(Stub):
|
|
"""StreamingServiceCallback — MBMS 流媒体服务回调"""
|
|
|
|
SIGNAL_STRENGTH_UNKNOWN = 0
|
|
SIGNAL_STRENGTH_POOR = 1
|
|
SIGNAL_STRENGTH_MODERATE = 2
|
|
SIGNAL_STRENGTH_GOOD = 3
|
|
SIGNAL_STRENGTH_GREAT = 4
|
|
|
|
def onStreamStateUpdated(self, state: int, reason: int):
|
|
"""流状态更新回调"""
|
|
pass
|
|
|
|
def onMediaDescriptionUpdated(self):
|
|
"""媒体描述更新回调"""
|
|
pass
|
|
|
|
def onBroadcastSignalStrengthUpdated(self, signal_strength: int):
|
|
"""广播信号强度更新回调"""
|
|
pass
|
|
|
|
def onStreamMethodUpdated(self, broadcast_method: int):
|
|
"""流方法更新回调"""
|
|
pass
|
|
|
|
def onError(self, error_code: int, message: str = ""):
|
|
"""错误回调"""
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DownloadProgressListener
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DownloadProgressListener(Stub):
|
|
"""DownloadProgressListener — MBMS 下载进度监听器"""
|
|
|
|
def onProgressUpdated(self, request: DownloadRequest, info: FileInfo,
|
|
current_bytes: int, total_bytes: int, current_files: int,
|
|
total_files: int):
|
|
"""下载进度更新回调"""
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DownloadRequestListener
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DownloadRequestListener(Stub):
|
|
"""DownloadRequestListener — MBMS 下载请求监听器"""
|
|
|
|
def onProgressUpdated(self, request: DownloadRequest, info: FileInfo,
|
|
current_bytes: int, total_bytes: int, current_files: int,
|
|
total_files: int):
|
|
pass
|
|
|
|
def onDownloadStateChanged(self, request: DownloadRequest, state: int):
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsDownloadSession (pre-API 30)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsDownloadSession(Stub):
|
|
"""MbmsDownloadSession — MBMS 下载会话 (旧版 API)"""
|
|
|
|
EXTRA_MBMS_DOWNLOAD_RESULT = "android.telephony.mbms.extra.MBMS_DOWNLOAD_RESULT"
|
|
EXTRA_MBMS_DOWNLOAD_REQUEST = "android.telephony.mbms.extra.MBMS_DOWNLOAD_REQUEST"
|
|
EXTRA_MBMS_FILE_INFO = "android.telephony.mbms.extra.MBMS_FILE_INFO"
|
|
EXTRA_MBMS_COMPLETED_FILES = "android.telephony.mbms.extra.MBMS_COMPLETED_FILES"
|
|
|
|
RESULT_SUCCESSFUL_DOWNLOAD = 0
|
|
RESULT_EXPIRED_CHARGES = 1
|
|
RESULT_FILE_UNAVAILABLE = 2
|
|
RESULT_IO_ERROR = 3
|
|
RESULT_OUT_OF_STORAGE = 4
|
|
RESULT_SERVICE_NOT_DOWNLOAD = 5
|
|
RESULT_DOWNLOAD_NOT_STARTED = 6
|
|
RESULT_FILE_NOT_FOUND = 7
|
|
RESULT_FILE_IN_PROGRESS = 8
|
|
RESULT_FILE_ALREADY_DOWNLOADED = 9
|
|
RESULT_MALFORMED_URI = 10
|
|
RESULT_CANCELLED = 11
|
|
RESULT_INTERRUPTED = 12
|
|
RESULT_TIMEOUT = 13
|
|
RESULT_SERVICE_UNAVAILABLE = 14
|
|
RESULT_MEDIA_NOT_FOUND = 15
|
|
RESULT_MEDIA_FAILED = 16
|
|
RESULT_ERROR_RADIO_OFF = 17
|
|
RESULT_ERROR_OUT_OF_MEMORY = 18
|
|
|
|
_instance_map: Dict[int, MbmsDownloadSession] = {}
|
|
|
|
def __init__(self, context: Any = None, subscription_id: int = 0,
|
|
callback: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._subscription_id = subscription_id
|
|
self._callback = callback
|
|
self._middleware_bound = False
|
|
self._download_requests: Dict[int, DownloadRequest] = {}
|
|
self._file_services: Dict[str, FileServiceInfo] = {}
|
|
self._temp_root: str = ""
|
|
|
|
@staticmethod
|
|
def create(context: Any, callback: Any,
|
|
subscription_id: int = 0) -> MbmsDownloadSession:
|
|
session = MbmsDownloadSession(context, subscription_id, callback)
|
|
MbmsDownloadSession._instance_map[subscription_id] = session
|
|
return session
|
|
|
|
def requestUpdate(self, file_service_list: List[FileServiceInfo]):
|
|
"""请求更新文件服务列表"""
|
|
pass
|
|
|
|
def download(self, request: DownloadRequest):
|
|
"""开始下载"""
|
|
request_id = int(time.time() * 1000)
|
|
request.setRequestId(request_id)
|
|
self._download_requests[request_id] = request
|
|
|
|
def cancelDownload(self, download_request: DownloadRequest):
|
|
"""取消下载"""
|
|
rid = download_request.getRequestId()
|
|
if rid in self._download_requests:
|
|
del self._download_requests[rid]
|
|
|
|
def getCurrentPendingDownloadRequests(self) -> List[DownloadRequest]:
|
|
"""获取当前待处理的下载请求"""
|
|
return list(self._download_requests.values())
|
|
|
|
def getTempFileRoot(self) -> str:
|
|
"""获取临时文件根目录"""
|
|
return self._temp_root
|
|
|
|
def setTempFileRoot(self, temp_root: str, storage_type: int):
|
|
"""设置临时文件根目录"""
|
|
self._temp_root = temp_root
|
|
|
|
def getMiddlewareVersion(self) -> int:
|
|
"""获取中间件版本"""
|
|
return 0
|
|
|
|
def getSubscriptionId(self) -> int:
|
|
return self._subscription_id
|
|
|
|
def close(self):
|
|
"""关闭会话"""
|
|
self._download_requests.clear()
|
|
self._file_services.clear()
|
|
|
|
@staticmethod
|
|
def getDownloadStatus(context: Any, subscription_id: int,
|
|
download_request: DownloadRequest) -> int:
|
|
return DownloadRequest.DOWNLOAD_STATUS_INACTIVE
|
|
|
|
def getFileServices(self) -> Dict[str, FileServiceInfo]:
|
|
return dict(self._file_services)
|
|
|
|
def getName(self) -> str:
|
|
return "MbmsDownloadSession"
|
|
|
|
def toString(self) -> str:
|
|
return f"MbmsDownloadSession(subId={self._subscription_id})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsStreamingSession (pre-API 30)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsStreamingSession(Stub):
|
|
"""MbmsStreamingSession — MBMS 流媒体会话 (旧版 API)"""
|
|
|
|
EXTRA_MBMS_STREAMING_SERVICE = "android.telephony.mbms.extra.MBMS_STREAMING_SERVICE"
|
|
EXTRA_MBMS_STREAMING_SERVICE_INFO = "android.telephony.mbms.extra.MBMS_STREAMING_SERVICE_INFO"
|
|
|
|
_instance_map: Dict[int, MbmsStreamingSession] = {}
|
|
|
|
def __init__(self, context: Any = None, subscription_id: int = 0,
|
|
callback: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._subscription_id = subscription_id
|
|
self._callback = callback
|
|
self._middleware_bound = False
|
|
self._streaming_services: Dict[str, StreamingService] = {}
|
|
|
|
@staticmethod
|
|
def create(context: Any, callback: Any,
|
|
subscription_id: int = 0) -> MbmsStreamingSession:
|
|
session = MbmsStreamingSession(context, subscription_id, callback)
|
|
MbmsStreamingSession._instance_map[subscription_id] = session
|
|
return session
|
|
|
|
def startStreaming(self, service_info: FileServiceInfo,
|
|
callback: StreamingServiceCallback) -> StreamingService:
|
|
"""开始流媒体"""
|
|
service = StreamingService(service_info.getServiceId(),
|
|
service_info.getServiceClass())
|
|
service.setCallback(callback)
|
|
self._streaming_services[service_info.getServiceId()] = service
|
|
return service
|
|
|
|
def stopStreaming(self, streaming_service: StreamingService):
|
|
"""停止流媒体"""
|
|
sid = streaming_service.getServiceId()
|
|
if sid in self._streaming_services:
|
|
streaming_service.stop()
|
|
del self._streaming_services[sid]
|
|
|
|
def requestUpdate(self, file_service_list: List[FileServiceInfo]):
|
|
"""请求更新服务列表"""
|
|
pass
|
|
|
|
def getCurrentStreamingServices(self) -> List[StreamingService]:
|
|
"""获取当前流媒体服务"""
|
|
return list(self._streaming_services.values())
|
|
|
|
def getMiddlewareVersion(self) -> int:
|
|
return 0
|
|
|
|
def getSubscriptionId(self) -> int:
|
|
return self._subscription_id
|
|
|
|
def close(self):
|
|
"""关闭会话"""
|
|
for service in self._streaming_services.values():
|
|
service.close()
|
|
self._streaming_services.clear()
|
|
|
|
def getName(self) -> str:
|
|
return "MbmsStreamingSession"
|
|
|
|
def toString(self) -> str:
|
|
return f"MbmsStreamingSession(subId={self._subscription_id})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsDownloadManager (API 30+)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsDownloadManager(Stub):
|
|
"""MbmsDownloadManager — MBMS 下载管理器 (API 30+)"""
|
|
|
|
EXTRA_MBMS_DOWNLOAD_RESULT = "android.telephony.mbms.extra.MBMS_DOWNLOAD_RESULT"
|
|
EXTRA_MBMS_DOWNLOAD_REQUEST = "android.telephony.mbms.extra.MBMS_DOWNLOAD_REQUEST"
|
|
EXTRA_MBMS_FILE_INFO = "android.telephony.mbms.extra.MBMS_FILE_INFO"
|
|
EXTRA_MBMS_COMPLETED_FILES = "android.telephony.mbms.extra.MBMS_COMPLETED_FILES"
|
|
|
|
# 下载结果码
|
|
DOWNLOAD_RESULT_SUCCESS = 0
|
|
DOWNLOAD_RESULT_ERROR = 1
|
|
DOWNLOAD_RESULT_ERROR_MEDIA_NOT_FOUND = 2
|
|
DOWNLOAD_RESULT_ERROR_MEDIA_UNAVAILABLE = 3
|
|
DOWNLOAD_RESULT_ERROR_MEDIA_FAILED = 4
|
|
DOWNLOAD_RESULT_ERROR_SERVICE_UNAVAILABLE = 5
|
|
DOWNLOAD_RESULT_ERROR_INSUFFICIENT_STORAGE = 6
|
|
DOWNLOAD_RESULT_ERROR_IO_ERROR = 7
|
|
DOWNLOAD_RESULT_ERROR_FILE_NOT_FOUND = 8
|
|
DOWNLOAD_RESULT_ERROR_OUT_OF_MEMORY = 9
|
|
DOWNLOAD_RESULT_ERROR_RADIO_OFF = 10
|
|
DOWNLOAD_RESULT_ERROR_INTERRUPTED = 11
|
|
DOWNLOAD_RESULT_ERROR_TIMEOUT = 12
|
|
DOWNLOAD_RESULT_ERROR_CANCELLED = 13
|
|
DOWNLOAD_RESULT_ERROR_DOWNLOAD_NOT_STARTED = 14
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._download_requests: Dict[int, DownloadRequest] = {}
|
|
self._file_services: Dict[str, FileServiceInfo] = {}
|
|
self._listeners: List[DownloadStatusListener] = []
|
|
self._progress_listeners: List[DownloadProgressListener] = []
|
|
|
|
@staticmethod
|
|
def getService(context: Any, sub_id: int = 0) -> Optional[MbmsDownloadManager]:
|
|
return MbmsDownloadManager(context)
|
|
|
|
def addDownloadRequest(self, download_request: DownloadRequest):
|
|
"""添加下载请求"""
|
|
request_id = len(self._download_requests) + 1
|
|
download_request.setRequestId(request_id)
|
|
self._download_requests[request_id] = download_request
|
|
|
|
def removeDownloadRequest(self, download_request: DownloadRequest):
|
|
"""移除下载请求"""
|
|
rid = download_request.getRequestId()
|
|
self._download_requests.pop(rid, None)
|
|
|
|
def getCurrentDownloadRequests(self) -> List[DownloadRequest]:
|
|
"""获取当前所有下载请求"""
|
|
return list(self._download_requests.values())
|
|
|
|
def getPendingDownloadRequests(self) -> List[DownloadRequest]:
|
|
"""获取待处理的下载请求"""
|
|
return [r for r in self._download_requests.values()
|
|
if r.getHash() == ""]
|
|
|
|
def getCompletedDownloadRequests(self) -> List[DownloadRequest]:
|
|
"""获取已完成的下载请求"""
|
|
return [r for r in self._download_requests.values()
|
|
if r.getHash() != ""]
|
|
|
|
def addStatusListener(self, listener: DownloadStatusListener):
|
|
"""添加状态监听器"""
|
|
if listener not in self._listeners:
|
|
self._listeners.append(listener)
|
|
|
|
def removeStatusListener(self, listener: DownloadStatusListener):
|
|
"""移除状态监听器"""
|
|
self._listeners = [l for l in self._listeners if l is not listener]
|
|
|
|
def addProgressListener(self, listener: DownloadProgressListener):
|
|
"""添加进度监听器"""
|
|
if listener not in self._progress_listeners:
|
|
self._progress_listeners.append(listener)
|
|
|
|
def removeProgressListener(self, listener: DownloadProgressListener):
|
|
"""移除进度监听器"""
|
|
self._progress_listeners = [l for l in self._progress_listeners
|
|
if l is not listener]
|
|
|
|
def getMaxDownloadRequests(self) -> int:
|
|
"""获取最大下载请求数"""
|
|
return 100
|
|
|
|
def getFileServices(self) -> Dict[str, FileServiceInfo]:
|
|
return dict(self._file_services)
|
|
|
|
def setTempFileRoot(self, temp_root: str, storage_type: int):
|
|
"""设置临时文件根目录"""
|
|
pass
|
|
|
|
def getTempFileRoot(self) -> str:
|
|
return ""
|
|
|
|
def getMiddlewareVersion(self) -> int:
|
|
return 0
|
|
|
|
def close(self):
|
|
"""关闭下载管理器"""
|
|
self._download_requests.clear()
|
|
self._listeners.clear()
|
|
self._progress_listeners.clear()
|
|
|
|
def toString(self) -> str:
|
|
return f"MbmsDownloadManager(requests={len(self._download_requests)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsStreamingManager (API 30+)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsStreamingManager(Stub):
|
|
"""MbmsStreamingManager — MBMS 流媒体管理器 (API 30+)"""
|
|
|
|
EXTRA_MBMS_STREAMING_SERVICE_INFO = "android.telephony.mbms.extra.MBMS_STREAMING_SERVICE_INFO"
|
|
|
|
STREAMING_SERVICE_STATE_STOPPED = 0
|
|
STREAMING_SERVICE_STATE_STARTED = 1
|
|
STREAMING_SERVICE_STATE_STALLED = 2
|
|
STREAMING_SERVICE_STATE_PENDING = 3
|
|
STREAMING_SERVICE_STATE_ERROR = 4
|
|
|
|
BROADCAST_METHOD_UNICAST = 0
|
|
BROADCAST_METHOD_MULTICAST = 1
|
|
BROADCAST_METHOD_BROADCAST = 2
|
|
|
|
REASON_BY_USER_REQUEST = 1
|
|
REASON_BY_MIDDLEWARE = 2
|
|
REASON_BY_RADIO_RESOURCE = 3
|
|
REASON_BY_OUT_OF_MEMORY = 4
|
|
REASON_BY_SIGNAL_LOST = 5
|
|
REASON_BY_TEMPORARILY_UNAVAILABLE = 6
|
|
REASON_BY_PERMANENTLY_UNAVAILABLE = 7
|
|
REASON_BY_SERVICE_SHUTDOWN = 8
|
|
REASON_BY_SERVICE_NOT_VISIBLE = 9
|
|
REASON_BY_RADIO_NOT_AVAILABLE = 10
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._streaming_services: Dict[str, StreamingService] = {}
|
|
self._service_info_map: Dict[str, FileServiceInfo] = {}
|
|
|
|
@staticmethod
|
|
def getService(context: Any, sub_id: int = 0) -> Optional[MbmsStreamingManager]:
|
|
return MbmsStreamingManager(context)
|
|
|
|
def startStreaming(self, service_info: FileServiceInfo,
|
|
callback: StreamingServiceCallback) -> StreamingService:
|
|
"""启动流媒体服务"""
|
|
service = StreamingService(service_info.getServiceId(),
|
|
service_info.getServiceClass())
|
|
service.setCallback(callback)
|
|
self._streaming_services[service_info.getServiceId()] = service
|
|
self._service_info_map[service_info.getServiceId()] = service_info
|
|
return service
|
|
|
|
def stopStreaming(self, streaming_service: StreamingService):
|
|
"""停止流媒体服务"""
|
|
sid = streaming_service.getServiceId()
|
|
if sid in self._streaming_services:
|
|
streaming_service.stop()
|
|
del self._streaming_services[sid]
|
|
|
|
def getCurrentStreamingServices(self) -> List[StreamingService]:
|
|
return list(self._streaming_services.values())
|
|
|
|
def getServiceInfoForStreamingService(self, service: StreamingService) -> Optional[FileServiceInfo]:
|
|
return self._service_info_map.get(service.getServiceId())
|
|
|
|
def getMaxStreamingServices(self) -> int:
|
|
return 10
|
|
|
|
def getMiddlewareVersion(self) -> int:
|
|
return 0
|
|
|
|
def close(self):
|
|
"""关闭流媒体管理器"""
|
|
for service in self._streaming_services.values():
|
|
service.close()
|
|
self._streaming_services.clear()
|
|
self._service_info_map.clear()
|
|
|
|
def toString(self) -> str:
|
|
return f"MbmsStreamingManager(services={len(self._streaming_services)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsUtils
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsUtils(Stub):
|
|
"""MbmsUtils — MBMS 工具类"""
|
|
|
|
@staticmethod
|
|
def getCellBroadcastServiceInfo(context: Any,
|
|
service_id: str,
|
|
subscription_id: int) -> Optional[FileServiceInfo]:
|
|
"""获取小区广播服务信息"""
|
|
return None
|
|
|
|
@staticmethod
|
|
def isFileService(service_announcement: Any) -> bool:
|
|
"""判断是否为文件服务"""
|
|
return True
|
|
|
|
@staticmethod
|
|
def isStreamingService(service_announcement: Any) -> bool:
|
|
"""判断是否为流媒体服务"""
|
|
return True
|
|
|
|
@staticmethod
|
|
def getServiceClassFromServiceAnnouncement(service_announcement: Any) -> Optional[str]:
|
|
"""从服务公告中获取服务类"""
|
|
return None
|
|
|
|
@staticmethod
|
|
def getServiceIdFromServiceAnnouncement(service_announcement: Any) -> Optional[str]:
|
|
"""从服务公告中获取服务 ID"""
|
|
return None
|
|
|
|
@staticmethod
|
|
def getFileInfoFromFileService(service_info: FileServiceInfo) -> List[FileInfo]:
|
|
"""从文件服务信息中获取文件信息列表"""
|
|
return service_info.getFiles()
|
|
|
|
@staticmethod
|
|
def createDownloadRequest(service_id: str, file_uri: str,
|
|
source: Any, destination: Any) -> DownloadRequest:
|
|
"""创建下载请求"""
|
|
return DownloadRequest(service_id, file_uri, source, destination)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsGroupCallService
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsGroupCallService(Stub):
|
|
"""MbmsGroupCallService — MBMS 组呼服务"""
|
|
|
|
REASON_BY_USER_REQUEST = 1
|
|
REASON_BY_MIDDLEWARE = 2
|
|
REASON_BY_RADIO_RESOURCE = 3
|
|
REASON_BY_OUT_OF_MEMORY = 4
|
|
REASON_BY_SIGNAL_LOST = 5
|
|
REASON_BY_TEMPORARILY_UNAVAILABLE = 6
|
|
REASON_BY_PERMANENTLY_UNAVAILABLE = 7
|
|
REASON_BY_SERVICE_SHUTDOWN = 8
|
|
REASON_BY_SERVICE_NOT_VISIBLE = 9
|
|
REASON_BY_RADIO_NOT_AVAILABLE = 10
|
|
|
|
STATE_STOPPED = 0
|
|
STATE_STARTED = 1
|
|
STATE_STALLED = 2
|
|
STATE_PENDING = 3
|
|
STATE_ERROR = 4
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._group_calls: Dict[str, Any] = {}
|
|
|
|
@staticmethod
|
|
def getService(context: Any, sub_id: int = 0) -> Optional[MbmsGroupCallService]:
|
|
return MbmsGroupCallService(context)
|
|
|
|
def startGroupCall(self, service_id: str, sai_list: List[int],
|
|
frequency: int, tmgi: Any, callback: Any):
|
|
"""启动组呼"""
|
|
pass
|
|
|
|
def stopGroupCall(self, service_id: str):
|
|
"""停止组呼"""
|
|
self._group_calls.pop(service_id, None)
|
|
|
|
def getCurrentGroupCalls(self) -> List[Any]:
|
|
return list(self._group_calls.values())
|
|
|
|
def close(self):
|
|
self._group_calls.clear()
|
|
|
|
def toString(self) -> str:
|
|
return f"MbmsGroupCallService(calls={len(self._group_calls)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsDownloadSessionCallback
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsDownloadSessionCallback(Stub):
|
|
"""MbmsDownloadSessionCallback — MBMS 下载会话回调"""
|
|
|
|
def onError(self, error_code: int, message: str = ""):
|
|
pass
|
|
|
|
def onFileServicesUpdated(self, services: List[FileServiceInfo]):
|
|
pass
|
|
|
|
def onMiddlewareReady(self):
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsStreamingSessionCallback
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsStreamingSessionCallback(Stub):
|
|
"""MbmsStreamingSessionCallback — MBMS 流媒体会话回调"""
|
|
|
|
def onError(self, error_code: int, message: str = ""):
|
|
pass
|
|
|
|
def onStreamingServicesUpdated(self, services: List[FileServiceInfo]):
|
|
pass
|
|
|
|
def onMiddlewareReady(self):
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ServiceAnnouncement
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ServiceAnnouncement(Stub):
|
|
"""ServiceAnnouncement — MBMS 服务公告"""
|
|
|
|
def __init__(self, service_id: str = "", service_class: str = "",
|
|
announcement_data: bytes = b""):
|
|
super().__init__()
|
|
self._service_id = service_id
|
|
self._service_class = service_class
|
|
self._announcement_data = announcement_data
|
|
self._sais: List[int] = []
|
|
self._cells: List[int] = []
|
|
self._expiry_time: int = 0
|
|
|
|
def getServiceId(self) -> str:
|
|
return self._service_id
|
|
|
|
def getServiceClass(self) -> str:
|
|
return self._service_class
|
|
|
|
def getAnnouncementData(self) -> bytes:
|
|
return self._announcement_data
|
|
|
|
def getSais(self) -> List[int]:
|
|
return list(self._sais)
|
|
|
|
def setSais(self, sais: List[int]):
|
|
self._sais = list(sais)
|
|
|
|
def getCells(self) -> List[int]:
|
|
return list(self._cells)
|
|
|
|
def setCells(self, cells: List[int]):
|
|
self._cells = list(cells)
|
|
|
|
def getExpiryTime(self) -> int:
|
|
return self._expiry_time
|
|
|
|
def setExpiryTime(self, expiry: int):
|
|
self._expiry_time = expiry
|
|
|
|
def toString(self) -> str:
|
|
return f"ServiceAnnouncement(serviceId={self._service_id})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# InternalDownloadSession (helper)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class InternalDownloadSession(Stub):
|
|
"""InternalDownloadSession — 内部下载会话辅助类"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._session_id: int = 0
|
|
self._active: bool = False
|
|
self._downloads: Dict[int, DownloadRequest] = {}
|
|
|
|
def getSessionId(self) -> int:
|
|
return self._session_id
|
|
|
|
def setSessionId(self, session_id: int):
|
|
self._session_id = session_id
|
|
|
|
def isActive(self) -> bool:
|
|
return self._active
|
|
|
|
def setActive(self, active: bool):
|
|
self._active = active
|
|
|
|
def addDownload(self, request: DownloadRequest):
|
|
self._downloads[request.getRequestId()] = request
|
|
|
|
def removeDownload(self, request_id: int):
|
|
self._downloads.pop(request_id, None)
|
|
|
|
def getDownloads(self) -> List[DownloadRequest]:
|
|
return list(self._downloads.values())
|
|
|
|
def clear(self):
|
|
self._downloads.clear()
|
|
self._active = False
|
|
|
|
def toString(self) -> str:
|
|
return f"InternalDownloadSession(id={self._session_id}, active={self._active})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MbmsResourceUtils
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MbmsResourceUtils(Stub):
|
|
"""MbmsResourceUtils — MBMS 资源工具"""
|
|
|
|
@staticmethod
|
|
def getServiceIdList(services: List[FileServiceInfo]) -> List[str]:
|
|
return [s.getServiceId() for s in services]
|
|
|
|
@staticmethod
|
|
def getServiceNameList(services: List[FileServiceInfo]) -> List[str]:
|
|
return [s.getServiceClass() for s in services]
|
|
|
|
@staticmethod
|
|
def findServiceById(services: List[FileServiceInfo],
|
|
service_id: str) -> Optional[FileServiceInfo]:
|
|
for s in services:
|
|
if s.getServiceId() == service_id:
|
|
return s
|
|
return None
|
|
|
|
@staticmethod
|
|
def mergeServiceLists(a: List[FileServiceInfo],
|
|
b: List[FileServiceInfo]) -> List[FileServiceInfo]:
|
|
merged = {s.getServiceId(): s for s in a}
|
|
for s in b:
|
|
merged[s.getServiceId()] = s
|
|
return list(merged.values()) |