Skip to content

Commit c1998f3

Browse files
authored
androidtv 12 & 13 (#340)
* add support for androidtv 12 & 13 * reformated code by black formater * reformatted code by black again * fixed missing CMD_CURRENT_APP_MEDIA_SESSION_STATE12 * tried to fix the tests errors * fix missing CMD_VOLUME_SET_COMMAND11 * fixed errors * Stmts Miss * fix
1 parent 4df518d commit c1998f3

File tree

6 files changed

+542
-90
lines changed

6 files changed

+542
-90
lines changed

androidtv/basetv/basetv.py

Lines changed: 104 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,14 @@ class BaseTV(object): # pylint: disable=too-few-public-methods
6969
DEVICE_ENUM = constants.DeviceEnum.BASETV
7070

7171
def __init__(
72-
self, adb, host, port=5555, adbkey="", adb_server_ip="", adb_server_port=5037, state_detection_rules=None
72+
self,
73+
adb,
74+
host,
75+
port=5555,
76+
adbkey="",
77+
adb_server_ip="",
78+
adb_server_port=5037,
79+
state_detection_rules=None,
7380
):
7481
self._adb = adb
7582
self.host = host
@@ -131,6 +138,14 @@ def _cmd_audio_state(self):
131138
# Is this an Android 11 device?
132139
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
133140
return constants.CMD_AUDIO_STATE11
141+
142+
# Is this an Android 12 device?
143+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
144+
return constants.CMD_AUDIO_STATE11
145+
146+
# Is this an Android 13 device?
147+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
148+
return constants.CMD_AUDIO_STATE11
134149
return constants.CMD_AUDIO_STATE
135150

136151
def _cmd_current_app(self):
@@ -157,6 +172,14 @@ def _cmd_current_app(self):
157172
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
158173
return constants.CMD_CURRENT_APP11
159174

175+
# Is this an Android 12 device?
176+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
177+
return constants.CMD_CURRENT_APP12
178+
179+
# Is this an Android 13 device?
180+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
181+
return constants.CMD_CURRENT_APP13
182+
160183
return constants.CMD_CURRENT_APP
161184

162185
def _cmd_current_app_media_session_state(self):
@@ -183,6 +206,14 @@ def _cmd_current_app_media_session_state(self):
183206
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
184207
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE11
185208

209+
# Is this an Android 12 device?
210+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
211+
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE12
212+
213+
# Is this an Android 13 device?
214+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
215+
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE13
216+
186217
return constants.CMD_CURRENT_APP_MEDIA_SESSION_STATE
187218

188219
def _cmd_hdmi_input(self):
@@ -201,8 +232,39 @@ def _cmd_hdmi_input(self):
201232
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
202233
return constants.CMD_HDMI_INPUT11
203234

235+
# Is this an Android 12 device?
236+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
237+
return constants.CMD_HDMI_INPUT11
238+
239+
# Is this an Android 13 device?
240+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
241+
return constants.CMD_HDMI_INPUT11
242+
204243
return constants.CMD_HDMI_INPUT
205244

245+
def _cmd_volume_set(self):
246+
"""Get the command used to set volume for this device.
247+
248+
Returns
249+
-------
250+
str
251+
The device-specific ADB shell command used to set volume
252+
253+
"""
254+
# Is this an Android 11 device?
255+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
256+
return constants.CMD_VOLUME_SET_COMMAND11
257+
258+
# Is this an Android 12 device?
259+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
260+
return constants.CMD_VOLUME_SET_COMMAND11
261+
262+
# Is this an Android 13 device?
263+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
264+
return constants.CMD_VOLUME_SET_COMMAND11
265+
266+
return constants.CMD_VOLUME_SET_COMMAND
267+
206268
def _cmd_launch_app(self, app):
207269
"""Get the command to launch the specified app for this device.
208270
@@ -235,6 +297,14 @@ def _cmd_launch_app(self, app):
235297
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "11":
236298
return constants.CMD_LAUNCH_APP11.format(app)
237299

300+
# Is this an Android 12 device?
301+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "12":
302+
return constants.CMD_LAUNCH_APP12.format(app)
303+
304+
# Is this an Android 13 device?
305+
if self.DEVICE_ENUM == constants.DeviceEnum.ANDROIDTV and self.device_properties.get("sw_version", "") == "13":
306+
return constants.CMD_LAUNCH_APP13.format(app)
307+
238308
return constants.CMD_LAUNCH_APP.format(app)
239309

240310
def _cmd_running_apps(self):
@@ -339,7 +409,12 @@ def _parse_device_properties(self, properties):
339409
``'serialno'``, ``'manufacturer'``, ``'model'``, and ``'sw_version'``
340410
341411
"""
342-
_LOGGER.debug("%s:%d `get_device_properties` response: %s", self.host, self.port, properties)
412+
_LOGGER.debug(
413+
"%s:%d `get_device_properties` response: %s",
414+
self.host,
415+
self.port,
416+
properties,
417+
)
343418

344419
if not properties:
345420
self.device_properties = {}
@@ -353,7 +428,12 @@ def _parse_device_properties(self, properties):
353428
manufacturer, model, serialno, version = lines
354429

355430
if not serialno.strip():
356-
_LOGGER.warning("Could not obtain serialno for %s:%d, got: '%s'", self.host, self.port, serialno)
431+
_LOGGER.warning(
432+
"Could not obtain serialno for %s:%d, got: '%s'",
433+
self.host,
434+
self.port,
435+
serialno,
436+
)
357437
serialno = None
358438

359439
self.device_properties = {
@@ -393,7 +473,11 @@ def _parse_mac_address(mac_response):
393473
# #
394474
# ======================================================================= #
395475
def _custom_state_detection(
396-
self, current_app=None, media_session_state=None, wake_lock_size=None, audio_state=None
476+
self,
477+
current_app=None,
478+
media_session_state=None,
479+
wake_lock_size=None,
480+
audio_state=None,
397481
):
398482
"""Use the rules in ``self._state_detection_rules`` to determine the state.
399483
@@ -670,7 +754,11 @@ def _parse_stream_music(stream_music_raw):
670754
if not stream_music_raw:
671755
return None
672756

673-
matches = re.findall(constants.STREAM_MUSIC_REGEX_PATTERN, stream_music_raw, re.DOTALL | re.MULTILINE)
757+
matches = re.findall(
758+
constants.STREAM_MUSIC_REGEX_PATTERN,
759+
stream_music_raw,
760+
re.DOTALL | re.MULTILINE,
761+
)
674762
if matches:
675763
return matches[0]
676764

@@ -747,15 +835,21 @@ def _volume(self, stream_music, audio_output_device):
747835
return None
748836

749837
if not self.max_volume:
750-
max_volume_matches = re.findall(constants.MAX_VOLUME_REGEX_PATTERN, stream_music, re.DOTALL | re.MULTILINE)
838+
max_volume_matches = re.findall(
839+
constants.MAX_VOLUME_REGEX_PATTERN,
840+
stream_music,
841+
re.DOTALL | re.MULTILINE,
842+
)
751843
if max_volume_matches:
752844
self.max_volume = float(max_volume_matches[0])
753845

754846
if not audio_output_device:
755847
return None
756848

757849
volume_matches = re.findall(
758-
audio_output_device + constants.VOLUME_REGEX_PATTERN, stream_music, re.DOTALL | re.MULTILINE
850+
audio_output_device + constants.VOLUME_REGEX_PATTERN,
851+
stream_music,
852+
re.DOTALL | re.MULTILINE,
759853
)
760854
if volume_matches:
761855
return int(volume_matches[0])
@@ -899,7 +993,9 @@ def state_detection_rules_validator(rules, exc=KeyError):
899993
if not isinstance(value, constants.VALID_PROPERTIES_TYPES[prop]):
900994
raise exc(
901995
"Conditional value for property '{0}' must be of type {1}, not {2}".format(
902-
prop, constants.VALID_PROPERTIES_TYPES[prop].__name__, type(value).__name__
996+
prop,
997+
constants.VALID_PROPERTIES_TYPES[prop].__name__,
998+
type(value).__name__,
903999
)
9041000
)
9051001

androidtv/basetv/basetv_async.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ async def set_volume_level(self, volume_level):
830830

831831
new_volume = int(min(max(round(self.max_volume * volume_level), 0.0), self.max_volume))
832832

833-
await self._adb.shell("media volume --show --stream 3 --set {}".format(new_volume))
833+
await self._adb.shell(self._cmd_volume_set().format(new_volume))
834834

835835
# return the new volume level
836836
return new_volume / self.max_volume

androidtv/constants.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ class DeviceEnum(IntEnum):
8989

9090
#: Parse current application for an Android 11 device
9191
CMD_PARSE_CURRENT_APP11 = "CURRENT_APP=${CURRENT_APP%%/*} && CURRENT_APP=${CURRENT_APP##* }"
92-
9392
#: Assign focused application identifier to ``CURRENT_APP`` variable
9493
CMD_DEFINE_CURRENT_APP_VARIABLE = (
9594
"CURRENT_APP=$(dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp') && " + CMD_PARSE_CURRENT_APP
@@ -99,13 +98,30 @@ class DeviceEnum(IntEnum):
9998
"CURRENT_APP=$(dumpsys window windows | grep -E -m 1 'mInputMethod(Input)?Target') && " + CMD_PARSE_CURRENT_APP11
10099
)
101100

101+
#: Assign focused application identifier to ``CURRENT_APP`` variable for an Android 12 device
102+
CMD_DEFINE_CURRENT_APP_VARIABLE12 = (
103+
"CURRENT_APP=$(dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp|mObscuringWindow') && "
104+
+ CMD_PARSE_CURRENT_APP11
105+
)
106+
107+
#: Assign focused application identifier to ``CURRENT_APP`` variable for an Android 13 device
108+
CMD_DEFINE_CURRENT_APP_VARIABLE13 = (
109+
"CURRENT_APP=$(dumpsys window windows | grep -E -m 1 'imeLayeringTarget|imeInputTarget|imeControlTarget') && "
110+
+ CMD_PARSE_CURRENT_APP11
111+
)
102112

103113
#: Output identifier for current/focused application
104114
CMD_CURRENT_APP = CMD_DEFINE_CURRENT_APP_VARIABLE + " && echo $CURRENT_APP"
105115

106116
#: Output identifier for current/focused application for an Android 11 device
107117
CMD_CURRENT_APP11 = CMD_DEFINE_CURRENT_APP_VARIABLE11 + " && echo $CURRENT_APP"
108118

119+
#: Output identifier for current/focused application for an Android 12 device
120+
CMD_CURRENT_APP12 = CMD_DEFINE_CURRENT_APP_VARIABLE12 + " && echo $CURRENT_APP"
121+
122+
#: Output identifier for current/focused application for an Android 13 device
123+
CMD_CURRENT_APP13 = CMD_DEFINE_CURRENT_APP_VARIABLE13 + " && echo $CURRENT_APP"
124+
109125
#: Assign focused application identifier to ``CURRENT_APP`` variable (for a Google TV device)
110126
CMD_DEFINE_CURRENT_APP_VARIABLE_GOOGLE_TV = (
111127
"CURRENT_APP=$(dumpsys activity a . | grep mResumedActivity) && " + CMD_PARSE_CURRENT_APP
@@ -114,6 +130,12 @@ class DeviceEnum(IntEnum):
114130
#: Output identifier for current/focused application (for a Google TV device)
115131
CMD_CURRENT_APP_GOOGLE_TV = CMD_DEFINE_CURRENT_APP_VARIABLE_GOOGLE_TV + " && echo $CURRENT_APP"
116132

133+
#: set volume
134+
CMD_VOLUME_SET_COMMAND = "media volume --show --stream 3 --set {}"
135+
136+
#: set volume for an Android 11 & 12 & 13 device
137+
CMD_VOLUME_SET_COMMAND11 = "cmd media_session volume --show --stream 3 --set {}"
138+
117139
#: Get the HDMI input
118140
CMD_HDMI_INPUT = (
119141
"dumpsys activity starter | grep -E -o '(ExternalTv|HDMI)InputService/HW[0-9]' -m 1 | grep -o 'HW[0-9]'"
@@ -145,6 +167,16 @@ class DeviceEnum(IntEnum):
145167
CMD_DEFINE_CURRENT_APP_VARIABLE11.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION
146168
)
147169

170+
#: Launch an app if it is not already the current app on an Android 12 device
171+
CMD_LAUNCH_APP12 = (
172+
CMD_DEFINE_CURRENT_APP_VARIABLE12.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION
173+
)
174+
175+
#: Launch an app if it is not already the current app on an Android 11 device
176+
CMD_LAUNCH_APP13 = (
177+
CMD_DEFINE_CURRENT_APP_VARIABLE13.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION
178+
)
179+
148180
#: Launch an app on a Fire TV device
149181
CMD_LAUNCH_APP_FIRETV = (
150182
CMD_DEFINE_CURRENT_APP_VARIABLE.replace("{", "{{").replace("}", "}}") + " && " + CMD_LAUNCH_APP_CONDITION_FIRETV
@@ -164,6 +196,12 @@ class DeviceEnum(IntEnum):
164196
#: Determine the current app and get the state from ``dumpsys media_session`` for an Android 11 device
165197
CMD_CURRENT_APP_MEDIA_SESSION_STATE11 = CMD_CURRENT_APP11 + " && " + CMD_MEDIA_SESSION_STATE
166198

199+
#: Determine the current app and get the state from ``dumpsys media_session`` for an Android 12 device
200+
CMD_CURRENT_APP_MEDIA_SESSION_STATE12 = CMD_CURRENT_APP12 + " && " + CMD_MEDIA_SESSION_STATE
201+
202+
#: Determine the current app and get the state from ``dumpsys media_session`` for an Android 13 device
203+
CMD_CURRENT_APP_MEDIA_SESSION_STATE13 = CMD_CURRENT_APP13 + " && " + CMD_MEDIA_SESSION_STATE
204+
167205
#: Determine the current app and get the state from ``dumpsys media_session`` for a Google TV device
168206
CMD_CURRENT_APP_MEDIA_SESSION_STATE_GOOGLE_TV = CMD_CURRENT_APP_GOOGLE_TV + " && " + CMD_MEDIA_SESSION_STATE
169207

@@ -381,7 +419,11 @@ class DeviceEnum(IntEnum):
381419
VALID_PROPERTIES = VALID_STATE_PROPERTIES + ("wake_lock_size",)
382420

383421
#: The required type for each entry in :py:const:`VALID_PROPERTIES` (used by :func:`~androidtv.basetv.state_detection_rules_validator`)
384-
VALID_PROPERTIES_TYPES = {"audio_state": str, "media_session_state": int, "wake_lock_size": int}
422+
VALID_PROPERTIES_TYPES = {
423+
"audio_state": str,
424+
"media_session_state": int,
425+
"wake_lock_size": int,
426+
}
385427

386428
# https://developer.android.com/reference/android/media/session/PlaybackState.html
387429
#: States for the :attr:`~androidtv.basetv.basetv.BaseTV.media_session_state` property
@@ -483,6 +525,7 @@ class DeviceEnum(IntEnum):
483525
APP_TWITCH_FIRETV = "tv.twitch.android.viewer"
484526
APP_VEVO = "com.vevo.tv"
485527
APP_VH1 = "com.mtvn.vh1android"
528+
APP_VIKI = "com.viki.android"
486529
APP_VIMEO = "com.vimeo.android.videoapp"
487530
APP_VLC = "org.videolan.vlc"
488531
APP_VOYO = "com.phonegap.voyo"
@@ -590,6 +633,7 @@ class DeviceEnum(IntEnum):
590633
APP_TWITCH_FIRETV: "Twitch (FireTV)",
591634
APP_VEVO: "Vevo",
592635
APP_VH1: "VH1",
636+
APP_VIKI: "Rakuten Viki",
593637
APP_VIMEO: "Vimeo",
594638
APP_VLC: "VLC",
595639
APP_VOYO: "VOYO",

tests/generate_test_constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
"CMD_SUCCESS1_FAILURE0",
1313
"CMD_PARSE_CURRENT_APP",
1414
"CMD_PARSE_CURRENT_APP11",
15+
"CMD_PARSE_CURRENT_APP12",
16+
"CMD_PARSE_CURRENT_APP13",
1517
"CMD_DEFINE_CURRENT_APP_VARIABLE",
1618
"CMD_DEFINE_CURRENT_APP_VARIABLE11",
19+
"CMD_DEFINE_CURRENT_APP_VARIABLE12",
20+
"CMD_DEFINE_CURRENT_APP_VARIABLE13",
1721
"CMD_DEFINE_CURRENT_APP_VARIABLE_GOOGLE_TV",
1822
"CMD_LAUNCH_APP_CONDITION",
1923
"CMD_LAUNCH_APP_CONDITION_FIRETV",

0 commit comments

Comments
 (0)