Edit SF and WM config from winscope.
Can now set the buffer sizes for these two traces, as well as set
tracing level and type for WM. Tested for multiple combinations of
config settings, as well as if settings are left as
placeholders/selected as the name of the config.
Bug: b/200159899
Test: Run a SF/WM trace with arbitrary config settings and check that all loads as normal.
Merged-In: I50ccc271bd2f90dba1d22c3e8c568490c4bf831f
Change-Id: I50ccc271bd2f90dba1d22c3e8c568490c4bf831f
(cherry picked from commit 9d3f674027)
This commit is contained in:
@@ -203,6 +203,52 @@ class SurfaceFlingerTraceConfig:
|
|||||||
def command(self) -> str:
|
def command(self) -> str:
|
||||||
return f'su root service call SurfaceFlinger 1033 i32 {self.flags}'
|
return f'su root service call SurfaceFlinger 1033 i32 {self.flags}'
|
||||||
|
|
||||||
|
class SurfaceFlingerTraceSelectedConfig:
|
||||||
|
"""Handles optional selected configuration for surfaceflinger traces.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
# defaults set for all configs
|
||||||
|
self.selectedConfigs = {
|
||||||
|
"sfbuffersize": "16000"
|
||||||
|
}
|
||||||
|
|
||||||
|
def add(self, configType, configValue) -> None:
|
||||||
|
self.selectedConfigs[configType] = configValue
|
||||||
|
|
||||||
|
def is_valid(self, configType) -> bool:
|
||||||
|
return configType in CONFIG_SF_SELECTION
|
||||||
|
|
||||||
|
def setBufferSize(self) -> str:
|
||||||
|
return f'su root service call SurfaceFlinger 1029 i32 {self.selectedConfigs["sfbuffersize"]}'
|
||||||
|
|
||||||
|
class WindowManagerTraceSelectedConfig:
|
||||||
|
"""Handles optional selected configuration for windowmanager traces.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
# defaults set for all configs
|
||||||
|
self.selectedConfigs = {
|
||||||
|
"wmbuffersize": "16000",
|
||||||
|
"tracinglevel": "all",
|
||||||
|
"tracingtype": "frame",
|
||||||
|
}
|
||||||
|
|
||||||
|
def add(self, configType, configValue) -> None:
|
||||||
|
self.selectedConfigs[configType] = configValue
|
||||||
|
|
||||||
|
def is_valid(self, configType) -> bool:
|
||||||
|
return configType in CONFIG_WM_SELECTION
|
||||||
|
|
||||||
|
def setBufferSize(self) -> str:
|
||||||
|
return f'su root cmd window tracing size {self.selectedConfigs["wmbuffersize"]}'
|
||||||
|
|
||||||
|
def setTracingLevel(self) -> str:
|
||||||
|
return f'su root cmd window tracing level {self.selectedConfigs["tracinglevel"]}'
|
||||||
|
|
||||||
|
def setTracingType(self) -> str:
|
||||||
|
return f'su root cmd window tracing {self.selectedConfigs["tracingtype"]}'
|
||||||
|
|
||||||
|
|
||||||
CONFIG_FLAG = {
|
CONFIG_FLAG = {
|
||||||
"composition": 1 << 2,
|
"composition": 1 << 2,
|
||||||
@@ -210,6 +256,17 @@ CONFIG_FLAG = {
|
|||||||
"hwc": 1 << 4
|
"hwc": 1 << 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#Keep up to date with options in DataAdb.vue
|
||||||
|
CONFIG_SF_SELECTION = [
|
||||||
|
"sfbuffersize",
|
||||||
|
]
|
||||||
|
|
||||||
|
#Keep up to date with options in DataAdb.vue
|
||||||
|
CONFIG_WM_SELECTION = [
|
||||||
|
"wmbuffersize",
|
||||||
|
"tracingtype",
|
||||||
|
"tracinglevel",
|
||||||
|
]
|
||||||
|
|
||||||
class DumpTarget:
|
class DumpTarget:
|
||||||
"""Defines a single parameter to trace.
|
"""Defines a single parameter to trace.
|
||||||
@@ -610,6 +667,18 @@ class EndTrace(DeviceRequestEndpoint):
|
|||||||
"utf-8"))
|
"utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def execute_command(server, device_id, shell, configType, configValue):
|
||||||
|
process = subprocess.Popen(shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
|
stdin=subprocess.PIPE, start_new_session=True)
|
||||||
|
log.debug(f"Changing trace config on device {device_id} {configType}:{configValue}")
|
||||||
|
out, err = process.communicate(configValue.encode('utf-8'))
|
||||||
|
if process.returncode != 0:
|
||||||
|
raise AdbError(
|
||||||
|
f"Error executing command:\n {configValue}\n\n### OUTPUT ###{out.decode('utf-8')}\n{err.decode('utf-8')}")
|
||||||
|
log.debug(f"Changing trace config finished on device {device_id}")
|
||||||
|
server.respond(HTTPStatus.OK, b'', "text/plain")
|
||||||
|
|
||||||
|
|
||||||
class ConfigTrace(DeviceRequestEndpoint):
|
class ConfigTrace(DeviceRequestEndpoint):
|
||||||
def process_with_device(self, server, path, device_id):
|
def process_with_device(self, server, path, device_id):
|
||||||
try:
|
try:
|
||||||
@@ -630,15 +699,50 @@ class ConfigTrace(DeviceRequestEndpoint):
|
|||||||
command = config.command()
|
command = config.command()
|
||||||
shell = ['adb', '-s', device_id, 'shell']
|
shell = ['adb', '-s', device_id, 'shell']
|
||||||
log.debug(f"Starting shell {' '.join(shell)}")
|
log.debug(f"Starting shell {' '.join(shell)}")
|
||||||
process = subprocess.Popen(shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
execute_command(server, device_id, shell, "sf buffer size", command)
|
||||||
stdin=subprocess.PIPE, start_new_session=True)
|
|
||||||
log.debug(f"Changing trace config on device {device_id} cmd:{command}")
|
|
||||||
out, err = process.communicate(command.encode('utf-8'))
|
def add_selected_request_to_config(self, server, device_id, config):
|
||||||
if process.returncode != 0:
|
try:
|
||||||
raise AdbError(
|
requested_configs = self.get_request(server)
|
||||||
f"Error executing command:\n {command}\n\n### OUTPUT ###{out.decode('utf-8')}\n{err.decode('utf-8')}")
|
for requested_config in requested_configs:
|
||||||
log.debug(f"Changing trace config finished on device {device_id}")
|
if config.is_valid(requested_config):
|
||||||
server.respond(HTTPStatus.OK, b'', "text/plain")
|
config.add(requested_config, requested_configs[requested_config])
|
||||||
|
else:
|
||||||
|
raise BadRequest(
|
||||||
|
f"Unsupported config {requested_config}\n")
|
||||||
|
except KeyError as err:
|
||||||
|
raise BadRequest("Unsupported trace target\n" + str(err))
|
||||||
|
if device_id in TRACE_THREADS:
|
||||||
|
BadRequest(f"Trace in progress for {device_id}")
|
||||||
|
if not check_root(device_id):
|
||||||
|
raise AdbError(
|
||||||
|
f"Unable to acquire root privileges on the device - check the output of 'adb -s {device_id} shell su root id'")
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
class SurfaceFlingerSelectedConfigTrace(DeviceRequestEndpoint):
|
||||||
|
def process_with_device(self, server, path, device_id):
|
||||||
|
config = SurfaceFlingerTraceSelectedConfig()
|
||||||
|
config = add_selected_request_to_config(self, server, device_id, config)
|
||||||
|
setBufferSize = config.setBufferSize()
|
||||||
|
shell = ['adb', '-s', device_id, 'shell']
|
||||||
|
log.debug(f"Starting shell {' '.join(shell)}")
|
||||||
|
execute_command(server, device_id, shell, "sf buffer size", setBufferSize)
|
||||||
|
|
||||||
|
|
||||||
|
class WindowManagerSelectedConfigTrace(DeviceRequestEndpoint):
|
||||||
|
def process_with_device(self, server, path, device_id):
|
||||||
|
config = WindowManagerTraceSelectedConfig()
|
||||||
|
config = add_selected_request_to_config(self, server, device_id, config)
|
||||||
|
setBufferSize = config.setBufferSize()
|
||||||
|
setTracingType = config.setTracingType()
|
||||||
|
setTracingLevel = config.setTracingLevel()
|
||||||
|
shell = ['adb', '-s', device_id, 'shell']
|
||||||
|
log.debug(f"Starting shell {' '.join(shell)}")
|
||||||
|
execute_command(server, device_id, shell, "wm buffer size", setBufferSize)
|
||||||
|
execute_command(server, device_id, shell, "tracing type", setTracingType)
|
||||||
|
execute_command(server, device_id, shell, "tracing level", setTracingLevel)
|
||||||
|
|
||||||
|
|
||||||
class StatusEndpoint(DeviceRequestEndpoint):
|
class StatusEndpoint(DeviceRequestEndpoint):
|
||||||
@@ -691,6 +795,10 @@ class ADBWinscopeProxy(BaseHTTPRequestHandler):
|
|||||||
self.router.register_endpoint(RequestType.POST, "dump", DumpEndpoint())
|
self.router.register_endpoint(RequestType.POST, "dump", DumpEndpoint())
|
||||||
self.router.register_endpoint(
|
self.router.register_endpoint(
|
||||||
RequestType.POST, "configtrace", ConfigTrace())
|
RequestType.POST, "configtrace", ConfigTrace())
|
||||||
|
self.router.register_endpoint(
|
||||||
|
RequestType.POST, "selectedsfconfigtrace", SurfaceFlingerSelectedConfigTrace())
|
||||||
|
self.router.register_endpoint(
|
||||||
|
RequestType.POST, "selectedwmconfigtrace", WindowManagerSelectedConfigTrace())
|
||||||
super().__init__(request, client_address, server)
|
super().__init__(request, client_address, server)
|
||||||
|
|
||||||
def respond(self, code: int, data: bytes, mime: str) -> None:
|
def respond(self, code: int, data: bytes, mime: str) -> None:
|
||||||
|
|||||||
@@ -86,10 +86,29 @@
|
|||||||
<div class="selection">
|
<div class="selection">
|
||||||
<md-checkbox class="md-primary" v-for="traceKey in Object.keys(TRACES)" :key="traceKey" v-model="adbStore[traceKey]">{{TRACES[traceKey].name}}</md-checkbox>
|
<md-checkbox class="md-primary" v-for="traceKey in Object.keys(TRACES)" :key="traceKey" v-model="adbStore[traceKey]">{{TRACES[traceKey].name}}</md-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="trace-config" v-for="traceKey in Object.keys(TRACE_CONFIG)" :key="traceKey">
|
<div class="trace-config">
|
||||||
<h4>{{TRACES[traceKey].name}} config</h4>
|
<h4>Surface Flinger config</h4>
|
||||||
<div class="selection">
|
<div class="selection">
|
||||||
<md-checkbox class="md-primary" v-for="config in TRACE_CONFIG[traceKey]" :key="config" v-model="adbStore[config]">{{config}}</md-checkbox>
|
<md-checkbox class="md-primary" v-for="config in TRACE_CONFIG['layers_trace']" :key="config" v-model="adbStore[config]">{{config}}</md-checkbox>
|
||||||
|
<div class="selection">
|
||||||
|
<md-field class="config-selection" v-for="selectConfig in Object.keys(SF_SELECTED_CONFIG)" :key="selectConfig">
|
||||||
|
<md-select v-model="SF_SELECTED_CONFIG_VALUES[selectConfig]" :placeholder="selectConfig">
|
||||||
|
<md-option value="">{{selectConfig}}</md-option>
|
||||||
|
<md-option v-for="option in SF_SELECTED_CONFIG[selectConfig]" :key="option" :value="option">{{ option }}</md-option>
|
||||||
|
</md-select>
|
||||||
|
</md-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="trace-config">
|
||||||
|
<h4>Window Manager config</h4>
|
||||||
|
<div class="selection">
|
||||||
|
<md-field class="config-selection" v-for="selectConfig in Object.keys(WM_SELECTED_CONFIG)" :key="selectConfig">
|
||||||
|
<md-select v-model="WM_SELECTED_CONFIG_VALUES[selectConfig]" :placeholder="selectConfig">
|
||||||
|
<md-option value="">{{selectConfig}}</md-option>
|
||||||
|
<md-option v-for="option in WM_SELECTED_CONFIG[selectConfig]" :key="option" :value="option">{{ option }}</md-option>
|
||||||
|
</md-select>
|
||||||
|
</md-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<md-button class="md-primary trace-btn" @click="startTrace">Start trace</md-button>
|
<md-button class="md-primary trace-btn" @click="startTrace">Start trace</md-button>
|
||||||
@@ -149,6 +168,8 @@ const PROXY_ENDPOINTS = {
|
|||||||
START_TRACE: '/start/',
|
START_TRACE: '/start/',
|
||||||
END_TRACE: '/end/',
|
END_TRACE: '/end/',
|
||||||
CONFIG_TRACE: '/configtrace/',
|
CONFIG_TRACE: '/configtrace/',
|
||||||
|
SELECTED_WM_CONFIG_TRACE: '/selectedwmconfigtrace/',
|
||||||
|
SELECTED_SF_CONFIG_TRACE: '/selectedsfconfigtrace/',
|
||||||
DUMP: '/dump/',
|
DUMP: '/dump/',
|
||||||
FETCH: '/fetch/',
|
FETCH: '/fetch/',
|
||||||
STATUS: '/status/',
|
STATUS: '/status/',
|
||||||
@@ -192,6 +213,33 @@ const TRACE_CONFIG = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SF_SELECTED_CONFIG = {
|
||||||
|
'sfbuffersize': [
|
||||||
|
'4000',
|
||||||
|
'8000',
|
||||||
|
'16000',
|
||||||
|
'32000',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const WM_SELECTED_CONFIG = {
|
||||||
|
'wmbuffersize': [
|
||||||
|
'4000',
|
||||||
|
'8000',
|
||||||
|
'16000',
|
||||||
|
'32000',
|
||||||
|
],
|
||||||
|
'tracingtype': [
|
||||||
|
'frame',
|
||||||
|
'transaction',
|
||||||
|
],
|
||||||
|
'tracinglevel': [
|
||||||
|
'all',
|
||||||
|
'trim',
|
||||||
|
'critical',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
const DUMPS = {
|
const DUMPS = {
|
||||||
'window_dump': {
|
'window_dump': {
|
||||||
name: 'Window Manager',
|
name: 'Window Manager',
|
||||||
@@ -228,6 +276,10 @@ export default {
|
|||||||
STATES,
|
STATES,
|
||||||
TRACES,
|
TRACES,
|
||||||
TRACE_CONFIG,
|
TRACE_CONFIG,
|
||||||
|
SF_SELECTED_CONFIG,
|
||||||
|
WM_SELECTED_CONFIG,
|
||||||
|
SF_SELECTED_CONFIG_VALUES: {},
|
||||||
|
WM_SELECTED_CONFIG_VALUES: {},
|
||||||
DUMPS,
|
DUMPS,
|
||||||
FILE_DECODERS,
|
FILE_DECODERS,
|
||||||
WINSCOPE_PROXY_VERSION,
|
WINSCOPE_PROXY_VERSION,
|
||||||
@@ -292,7 +344,7 @@ export default {
|
|||||||
this.keep_alive_worker = null;
|
this.keep_alive_worker = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.callProxy('GET', PROXY_ENDPOINTS.STATUS + this.deviceId() + '/', this, function(request, view) {
|
this.callProxy('GET', `${PROXY_ENDPOINTS.STATUS}${this.deviceId()}/`, this, function(request, view) {
|
||||||
if (request.responseText !== 'True') {
|
if (request.responseText !== 'True') {
|
||||||
view.endTrace();
|
view.endTrace();
|
||||||
} else if (view.keep_alive_worker === null) {
|
} else if (view.keep_alive_worker === null) {
|
||||||
@@ -303,16 +355,21 @@ export default {
|
|||||||
startTrace() {
|
startTrace() {
|
||||||
const requested = this.toTrace();
|
const requested = this.toTrace();
|
||||||
const requestedConfig = this.toTraceConfig();
|
const requestedConfig = this.toTraceConfig();
|
||||||
|
const requestedSelectedSfConfig = this.toSelectedSfTraceConfig();
|
||||||
|
const requestedSelectedWmConfig = this.toSelectedWmTraceConfig();
|
||||||
if (requested.length < 1) {
|
if (requested.length < 1) {
|
||||||
this.errorText = 'No targets selected';
|
this.errorText = 'No targets selected';
|
||||||
this.status = STATES.ERROR;
|
this.status = STATES.ERROR;
|
||||||
this.newEventOccurred("No targets selected");
|
this.newEventOccurred("No targets selected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newEventOccurred("Start Trace");
|
this.newEventOccurred("Start Trace");
|
||||||
this.callProxy('POST', PROXY_ENDPOINTS.CONFIG_TRACE + this.deviceId() + '/', this, null, null, requestedConfig);
|
this.callProxy('POST', `${PROXY_ENDPOINTS.CONFIG_TRACE}${this.deviceId()}/`, this, null, null, requestedConfig);
|
||||||
|
this.callProxy('POST', `${PROXY_ENDPOINTS.SELECTED_SF_CONFIG_TRACE}${this.deviceId()}/`, this, null, null, requestedSelectedSfConfig);
|
||||||
|
this.callProxy('POST', `${PROXY_ENDPOINTS.SELECTED_WM_CONFIG_TRACE}${this.deviceId()}/`, this, null, null, requestedSelectedWmConfig);
|
||||||
this.status = STATES.END_TRACE;
|
this.status = STATES.END_TRACE;
|
||||||
this.callProxy('POST', PROXY_ENDPOINTS.START_TRACE + this.deviceId() + '/', this, function(request, view) {
|
this.callProxy('POST', `${PROXY_ENDPOINTS.START_TRACE}${this.deviceId()}/`, this, function(request, view) {
|
||||||
view.keepAliveTrace();
|
view.keepAliveTrace();
|
||||||
}, null, requested);
|
}, null, requested);
|
||||||
},
|
},
|
||||||
@@ -326,19 +383,19 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.status = STATES.LOAD_DATA;
|
this.status = STATES.LOAD_DATA;
|
||||||
this.callProxy('POST', PROXY_ENDPOINTS.DUMP + this.deviceId() + '/', this, function(request, view) {
|
this.callProxy('POST', `${PROXY_ENDPOINTS.DUMP}${this.deviceId()}/`, this, function(request, view) {
|
||||||
view.loadFile(requested, 0);
|
view.loadFile(requested, 0);
|
||||||
}, null, requested);
|
}, null, requested);
|
||||||
},
|
},
|
||||||
endTrace() {
|
endTrace() {
|
||||||
this.status = STATES.LOAD_DATA;
|
this.status = STATES.LOAD_DATA;
|
||||||
this.callProxy('POST', PROXY_ENDPOINTS.END_TRACE + this.deviceId() + '/', this, function(request, view) {
|
this.callProxy('POST', `${PROXY_ENDPOINTS.END_TRACE}${this.deviceId()}/`, this, function(request, view) {
|
||||||
view.loadFile(view.toTrace(), 0);
|
view.loadFile(view.toTrace(), 0);
|
||||||
});
|
});
|
||||||
this.newEventOccurred("Ended Trace");
|
this.newEventOccurred("Ended Trace");
|
||||||
},
|
},
|
||||||
loadFile(files, idx) {
|
loadFile(files, idx) {
|
||||||
this.callProxy('GET', PROXY_ENDPOINTS.FETCH + this.deviceId() + '/' + files[idx] + '/', this, function(request, view) {
|
this.callProxy('GET', `${PROXY_ENDPOINTS.FETCH}${this.deviceId()}/${files[idx]}/`, this, function(request, view) {
|
||||||
try {
|
try {
|
||||||
const enc = new TextDecoder('utf-8');
|
const enc = new TextDecoder('utf-8');
|
||||||
const resp = enc.decode(request.response);
|
const resp = enc.decode(request.response);
|
||||||
@@ -380,6 +437,24 @@ export default {
|
|||||||
.flatMap((file) => TRACE_CONFIG[file])
|
.flatMap((file) => TRACE_CONFIG[file])
|
||||||
.filter((config) => this.adbStore[config]);
|
.filter((config) => this.adbStore[config]);
|
||||||
},
|
},
|
||||||
|
toSelectedSfTraceConfig() {
|
||||||
|
const requestedSelectedConfig = {};
|
||||||
|
for (const config in this.SF_SELECTED_CONFIG_VALUES) {
|
||||||
|
if (this.SF_SELECTED_CONFIG_VALUES[config] !== "") {
|
||||||
|
requestedSelectedConfig[config] = this.SF_SELECTED_CONFIG_VALUES[config];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestedSelectedConfig;
|
||||||
|
},
|
||||||
|
toSelectedWmTraceConfig() {
|
||||||
|
const requestedSelectedConfig = {};
|
||||||
|
for (const config in this.WM_SELECTED_CONFIG_VALUES) {
|
||||||
|
if (this.WM_SELECTED_CONFIG_VALUES[config] !== "") {
|
||||||
|
requestedSelectedConfig[config] = this.WM_SELECTED_CONFIG_VALUES[config];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestedSelectedConfig;
|
||||||
|
},
|
||||||
toDump() {
|
toDump() {
|
||||||
return Object.keys(DUMPS)
|
return Object.keys(DUMPS)
|
||||||
.filter((dumpKey) => this.adbStore[dumpKey]);
|
.filter((dumpKey) => this.adbStore[dumpKey]);
|
||||||
@@ -459,6 +534,12 @@ export default {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.config-selection {
|
||||||
|
width: 150px;
|
||||||
|
display: inline-flex;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
.device-choice {
|
.device-choice {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user