From 83fdc7fbe006fcc6e87fd8ce9a0d5c701cd160ca Mon Sep 17 00:00:00 2001 From: Kean Mariotti Date: Fri, 30 Dec 2022 10:15:54 +0000 Subject: [PATCH 1/2] Fix eslint errors Test: npm run lint:check Bug: b/263471740 Change-Id: I8289c8b22d5af5e85fd94ccebf1d82abb0a062c2 --- tools/winscope-ng/karma.conf.js | 2 +- .../src/common/trace/flickerlib/ObjectFormatter.ts | 5 +++-- tools/winscope-ng/src/common/trace/flickerlib/common.js | 5 +++-- .../winscope-ng/src/common/trace/flickerlib/layers/Layer.ts | 2 +- .../src/common/trace/flickerlib/layers/Transform.ts | 2 +- .../src/common/trace/flickerlib/windows/WindowContainer.ts | 2 +- .../common/trace/flickerlib/windows/WindowManagerState.ts | 4 ++-- .../src/common/trace/flickerlib/windows/WindowState.ts | 2 +- tools/winscope-ng/src/common/trace/timestamp.ts | 2 -- tools/winscope-ng/src/parsers/parser.ts | 2 +- tools/winscope-ng/src/test/remote_tool_mock/app.component.ts | 2 +- tools/winscope-ng/src/trace_collection/proxy_client.ts | 2 +- tools/winscope-ng/webpack.config.unit.spec.js | 4 ++-- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tools/winscope-ng/karma.conf.js b/tools/winscope-ng/karma.conf.js index 37b1d39a2..559235f79 100644 --- a/tools/winscope-ng/karma.conf.js +++ b/tools/winscope-ng/karma.conf.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -let webpackConfig = require("./webpack.config.common"); +const webpackConfig = require("./webpack.config.common"); delete webpackConfig.entry; delete webpackConfig.output; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts b/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts index 1ac19e66b..3cf05501e 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts @@ -42,7 +42,7 @@ export default class ObjectFormatter { private static FLICKER_INTDEF_MAP = readIntdefMap(); static cloneObject(entry: any): any { - let obj: any = {} + const obj: any = {} const properties = ObjectFormatter.getProperties(entry); properties.forEach(prop => obj[prop] = entry[prop]); return obj; @@ -81,7 +81,8 @@ export default class ObjectFormatter { props.push(prop); } }); - } while (obj = Object.getPrototypeOf(obj)); + obj = Object.getPrototypeOf(obj); + } while (obj); return props; } diff --git a/tools/winscope-ng/src/common/trace/flickerlib/common.js b/tools/winscope-ng/src/common/trace/flickerlib/common.js index f3cfbcf58..f7f6f768d 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/common.js +++ b/tools/winscope-ng/src/common/trace/flickerlib/common.js @@ -99,6 +99,7 @@ const Region = require('flicker').com.android.server.wm.traces.common.region.Reg // Service const TaggingEngine = require('flicker').com.android.server.wm.traces.common.service.TaggingEngine; +const EMPTY_SIZE = Size.Companion.EMPTY; const EMPTY_BUFFER = ActiveBuffer.Companion.EMPTY; const EMPTY_COLOR3 = Color3.Companion.EMPTY; const EMPTY_COLOR = Color.Companion.EMPTY; @@ -113,14 +114,14 @@ const EMPTY_TRANSFORM = new Transform(0, EMPTY_MATRIX33); function toSize(proto) { if (proto == null) { - return EMPTY_BOUNDS; + return EMPTY_SIZE; } const width = proto.width ?? proto.w ?? 0; const height = proto.height ?? proto.h ?? 0; if (width || height) { return new Size(width, height); } - return EMPTY_BOUNDS; + return EMPTY_SIZE; } function toActiveBuffer(proto) { diff --git a/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts b/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts index bfc3da839..c9c41e0ea 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts @@ -41,7 +41,7 @@ Layer.fromProto = function (proto: any, excludesCompositionState = false): Layer let crop: Rect if (proto.crop) { crop = toRect(proto.crop) - }; + } const properties = new LayerProperties( visibleRegion, diff --git a/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts b/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts index 6bce384f1..654667d0a 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts @@ -65,7 +65,7 @@ function getDefaultTransform(type: number, x: number, y: number): Matrix33 { } export function isFlagSet(type: number, bits: number): Boolean { - var type = type || 0; + type = type || 0; return (type & bits) === bits; } diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts index f69df79d1..8c4e34a2d 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts @@ -105,7 +105,7 @@ function createConfiguration(proto: any): Configuration { if (proto == null) { return null; } - var windowConfiguration = null; + let windowConfiguration = null; if (proto != null && proto.windowConfiguration != null) { windowConfiguration = createWindowConfiguration(proto.windowConfiguration); diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts index 9dc407e5b..d2fe02b8d 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts @@ -34,10 +34,10 @@ WindowManagerState.fromProto = function ( realToElapsedTimeOffsetNs: bigint|undefined = undefined, useElapsedTime = false, ): WindowManagerState { - var inputMethodWIndowAppToken = ""; + const inputMethodWIndowAppToken = ""; if (proto.inputMethodWindow != null) { proto.inputMethodWindow.hashCode.toString(16) - }; + } let parseOrder = 0; const nextSeq = () => ++parseOrder; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts index 7ebd96056..8c626d586 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts @@ -109,7 +109,7 @@ function getWindowType(proto: any, identifierName: string): number { } function getName(identifierName: string): string { - var name = identifierName; + let name = identifierName; if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) { name = identifierName.substring(WindowState.STARTING_WINDOW_PREFIX.length); diff --git a/tools/winscope-ng/src/common/trace/timestamp.ts b/tools/winscope-ng/src/common/trace/timestamp.ts index eb405978c..69cde16ee 100644 --- a/tools/winscope-ng/src/common/trace/timestamp.ts +++ b/tools/winscope-ng/src/common/trace/timestamp.ts @@ -32,10 +32,8 @@ export class Timestamp { throw new Error("realToElapsedTimeOffsetNs can't be undefined to use real timestamp"); } return new Timestamp(TimestampType.REAL, elapsedTimestamp + realToElapsedTimeOffsetNs); - break; case TimestampType.ELAPSED: return new Timestamp(TimestampType.ELAPSED, elapsedTimestamp); - break; default: throw new Error("Unhandled timestamp type"); } diff --git a/tools/winscope-ng/src/parsers/parser.ts b/tools/winscope-ng/src/parsers/parser.ts index 297c04fbb..aa1852617 100644 --- a/tools/winscope-ng/src/parsers/parser.ts +++ b/tools/winscope-ng/src/parsers/parser.ts @@ -68,7 +68,7 @@ abstract class Parser { } for (const fieldName in protoObj.$type.fields) { - if (protoObj.$type.fields.hasOwnProperty(fieldName)) { + if (Object.prototype.hasOwnProperty.call(protoObj.$type.fields, fieldName)) { const fieldProperties = protoObj.$type.fields[fieldName]; const field = protoObj[fieldName]; diff --git a/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts b/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts index dc3ac7e5c..f7e72514c 100644 --- a/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts +++ b/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts @@ -60,7 +60,7 @@ export class AppComponent { static readonly TARGET = "http://localhost:8080"; static readonly TIMESTAMP_IN_BUGREPORT_MESSAGE = 1670509911000000000n; - private winscope: WindowProxy|null = null; + private winscope: Window|null = null; private isWinscopeUp = false; private onMessagePongReceived = FunctionUtils.DO_NOTHING; diff --git a/tools/winscope-ng/src/trace_collection/proxy_client.ts b/tools/winscope-ng/src/trace_collection/proxy_client.ts index b1f4efc68..2079c00ef 100644 --- a/tools/winscope-ng/src/trace_collection/proxy_client.ts +++ b/tools/winscope-ng/src/trace_collection/proxy_client.ts @@ -53,7 +53,7 @@ class ProxyRequest { method: string, path: string, onSuccess: ((request: XMLHttpRequest) => void|Promise) | undefined, - type?: XMLHttpRequestResponseType, + type?: XMLHttpRequest['responseType'], jsonRequest: any = null ): Promise { return new Promise((resolve) => { diff --git a/tools/winscope-ng/webpack.config.unit.spec.js b/tools/winscope-ng/webpack.config.unit.spec.js index 8269b2d21..c38ef0182 100644 --- a/tools/winscope-ng/webpack.config.unit.spec.js +++ b/tools/winscope-ng/webpack.config.unit.spec.js @@ -16,7 +16,7 @@ const path = require('path'); const glob = require('glob'); -let config = require('./webpack.config.common'); +const config = require('./webpack.config.common'); config["mode"] = "development"; @@ -25,7 +25,7 @@ const allTestFiles = [ ...glob.sync('./src/**/*.spec.ts') ] const unitTestFiles = allTestFiles - .filter(file => !file.match(".*component\.spec\.(js|ts)$")) + .filter(file => !file.match(".*component\\.spec\\.(js|ts)$")) .filter(file => !file.match(".*e2e.*")) config["entry"] = { tests: unitTestFiles, From 73be9787b6e476180af24f55d55e79f157f76511 Mon Sep 17 00:00:00 2001 From: Kean Mariotti Date: Fri, 30 Dec 2022 11:12:27 +0000 Subject: [PATCH 2/2] The great formatting Unleash prettier on the entire codebase Fix: b/263471740 Test: npm run format:check && npm run lint:check Change-Id: Ida110947bec9c9a9b385c64e126ccf6d7ad6652b --- tools/winscope-ng/karma.conf.js | 21 +- tools/winscope-ng/protractor.config.js | 16 +- .../abt_chrome_extension_protocol.ts | 36 +- .../abt_chrome_extension_protocol_stub.ts | 20 +- .../src/abt_chrome_extension/messages.ts | 10 +- tools/winscope-ng/src/app/app.module.ts | 128 ++-- tools/winscope-ng/src/app/colors.ts | 12 +- .../components/adb_proxy.component.spec.ts | 56 +- .../src/app/components/adb_proxy.component.ts | 67 +- .../src/app/components/app.component.spec.ts | 102 +-- .../src/app/components/app.component.ts | 221 ++++--- .../src/app/components/app_component_stub.ts | 4 +- .../bottomnav/bottom_drawer.component.ts | 180 +++--- .../app/components/canvas/canvas_drawer.ts | 22 +- .../components/canvas/canvas_mouse_handler.ts | 53 +- .../canvas/draggable_canvas_object.ts | 40 +- .../collect_traces.component.spec.ts | 232 +++---- .../components/collect_traces.component.ts | 257 +++++--- .../app/components/load_progress.component.ts | 25 +- .../parser_error_snack_bar_component.ts | 63 +- .../timeline/expanded_timeline.component.ts | 164 ++--- .../components/timeline/mini_canvas_drawer.ts | 116 ++-- .../timeline/mini_timeline.component.ts | 73 ++- .../timeline/single_timeline.component.ts | 92 ++- .../timeline/timeline.component.spec.ts | 243 +++++--- .../components/timeline/timeline.component.ts | 581 ++++++++++-------- .../timeline/timeline_component_stub.ts | 6 +- .../src/app/components/timeline/utils.ts | 8 +- .../components/trace_config.component.spec.ts | 123 ++-- .../app/components/trace_config.component.ts | 51 +- .../components/trace_view.component.spec.ts | 75 +-- .../app/components/trace_view.component.ts | 79 +-- .../upload_traces.component.spec.ts | 20 +- .../app/components/upload_traces.component.ts | 112 ++-- .../upload_traces_component_stub.ts | 2 +- .../app/components/web_adb.component.spec.ts | 20 +- .../src/app/components/web_adb.component.ts | 25 +- tools/winscope-ng/src/app/mediator.spec.ts | 91 +-- tools/winscope-ng/src/app/mediator.ts | 85 +-- .../winscope-ng/src/app/timeline_data.spec.ts | 116 ++-- tools/winscope-ng/src/app/timeline_data.ts | 114 ++-- tools/winscope-ng/src/app/trace_data.spec.ts | 75 +-- tools/winscope-ng/src/app/trace_data.ts | 53 +- tools/winscope-ng/src/app/trace_icons.ts | 30 +- tools/winscope-ng/src/app/trace_info.ts | 102 +-- .../trace/flickerlib/ObjectFormatter.ts | 536 ++++++++-------- .../src/common/trace/flickerlib/common.js | 122 ++-- .../common/trace/flickerlib/layers/Layer.ts | 157 ++--- .../flickerlib/layers/LayerTraceEntry.ts | 122 ++-- .../trace/flickerlib/layers/Transform.ts | 86 ++- .../src/common/trace/flickerlib/mixin.ts | 58 +- .../trace/flickerlib/windows/Activity.ts | 60 +- .../trace/flickerlib/windows/DisplayArea.ts | 48 +- .../flickerlib/windows/DisplayContent.ts | 124 ++-- .../common/trace/flickerlib/windows/Task.ts | 80 +-- .../trace/flickerlib/windows/TaskFragment.ts | 58 +- .../flickerlib/windows/WindowContainer.ts | 196 +++--- .../flickerlib/windows/WindowManagerState.ts | 188 +++--- .../trace/flickerlib/windows/WindowState.ts | 200 +++--- .../trace/flickerlib/windows/WindowToken.ts | 48 +- .../winscope-ng/src/common/trace/protolog.ts | 142 +++-- .../src/common/trace/screen_recording.ts | 4 +- .../common/trace/screen_recording_utils.ts | 4 +- .../src/common/trace/timestamp.spec.ts | 14 +- .../winscope-ng/src/common/trace/timestamp.ts | 28 +- tools/winscope-ng/src/common/trace/trace.ts | 8 +- .../src/common/trace/trace_tree_node.ts | 4 +- .../src/common/trace/transactions.ts | 9 +- .../src/common/utils/array_utils.spec.ts | 99 ++- .../src/common/utils/array_utils.ts | 21 +- .../src/common/utils/file_utils.ts | 35 +- .../src/common/utils/global_config.ts | 4 +- .../utils/persistent_store_proxy.spec.ts | 134 ++-- .../common/utils/persistent_store_proxy.ts | 39 +- .../src/common/utils/time_utils.spec.ts | 276 +++++---- .../src/common/utils/time_utils.ts | 108 ++-- .../src/common/utils/tree_utils.ts | 21 +- .../src/cross_tool/cross_tool_protocol.ts | 88 +-- .../cross_tool/cross_tool_protocol_stub.ts | 17 +- tools/winscope-ng/src/cross_tool/messages.ts | 17 +- .../src/cross_tool/origin_allow_list.spec.ts | 46 +- .../src/cross_tool/origin_allow_list.ts | 22 +- .../interfaces/remote_bugreport_receiver.ts | 2 +- .../interfaces/remote_timestamp_receiver.ts | 2 +- .../src/interfaces/remote_timestamp_sender.ts | 2 +- .../interfaces/timestamp_change_listener.ts | 4 +- .../src/interfaces/trace_data_listener.ts | 2 +- tools/winscope-ng/src/main.component.spec.ts | 26 +- tools/winscope-ng/src/main.dev.ts | 13 +- tools/winscope-ng/src/main.prod.ts | 11 +- tools/winscope-ng/src/parsers/parser.ts | 35 +- .../src/parsers/parser_accessibility.spec.ts | 52 +- .../src/parsers/parser_accessibility.ts | 27 +- .../src/parsers/parser_common.spec.ts | 108 ++-- .../winscope-ng/src/parsers/parser_factory.ts | 73 ++- .../parser_input_method_clients.spec.ts | 59 +- .../parsers/parser_input_method_clients.ts | 73 ++- ...arser_input_method_manager_service.spec.ts | 60 +- .../parser_input_method_manager_service.ts | 71 ++- .../parser_input_method_service.spec.ts | 62 +- .../parsers/parser_input_method_service.ts | 73 ++- .../src/parsers/parser_protolog.spec.ts | 56 +- .../src/parsers/parser_protolog.ts | 50 +- .../parsers/parser_screen_recording.spec.ts | 42 +- .../src/parsers/parser_screen_recording.ts | 81 ++- .../parser_screen_recording_legacy.spec.ts | 32 +- .../parsers/parser_screen_recording_legacy.ts | 47 +- .../parsers/parser_surface_flinger.spec.ts | 79 ++- .../src/parsers/parser_surface_flinger.ts | 38 +- .../parser_surface_flinger_dump.spec.ts | 46 +- .../src/parsers/parser_transactions.spec.ts | 82 ++- .../src/parsers/parser_transactions.ts | 54 +- .../src/parsers/parser_window_manager.spec.ts | 55 +- .../src/parsers/parser_window_manager.ts | 35 +- .../parser_window_manager_dump.spec.ts | 30 +- .../src/parsers/parser_window_manager_dump.ts | 20 +- tools/winscope-ng/src/parsers/proto_types.js | 54 +- tools/winscope-ng/src/polyfills.ts | 3 +- tools/winscope-ng/src/test/common/blob.ts | 8 +- tools/winscope-ng/src/test/common/file.ts | 4 +- tools/winscope-ng/src/test/common/utils.ts | 12 +- .../src/test/e2e/cross_tool_protocol.spec.ts | 91 +-- .../src/test/e2e/upload_traces.spec.ts | 42 +- tools/winscope-ng/src/test/e2e/utils.ts | 14 +- .../e2e/viewer_input_method_clients.spec.ts | 23 +- ...iewer_input_method_manager_service.spec.ts | 25 +- .../e2e/viewer_input_method_service.spec.ts | 23 +- .../src/test/e2e/viewer_protolog.spec.ts | 29 +- .../test/e2e/viewer_screen_recording.spec.ts | 37 +- .../test/e2e/viewer_surface_flinger.spec.ts | 23 +- .../src/test/e2e/viewer_transactions.spec.ts | 29 +- .../test/e2e/viewer_window_manager.spec.ts | 23 +- .../winscope-ng/src/test/e2e/winscope.spec.ts | 19 +- .../test/remote_tool_mock/app.component.ts | 147 +++-- .../src/test/remote_tool_mock/app.module.ts | 22 +- .../src/test/remote_tool_mock/main.ts | 9 +- .../src/test/remote_tool_mock/polyfills.ts | 3 +- .../test/remote_tool_mock/webpack.config.js | 48 +- .../src/test/unit/hierarchy_tree_builder.ts | 10 +- .../src/test/unit/layer_builder.ts | 12 +- .../src/test/unit/mock_storage.spec.ts | 12 +- .../winscope-ng/src/test/unit/mock_storage.ts | 7 +- tools/winscope-ng/src/test/unit/utils.ts | 57 +- .../src/trace_collection/connection.ts | 60 +- .../src/trace_collection/proxy_client.ts | 183 +++--- .../src/trace_collection/proxy_connection.ts | 66 +- .../trace_collection_utils.ts | 235 ++++--- .../src/trace_collection/tracing_config.ts | 62 +- tools/winscope-ng/src/viewers/common/chip.ts | 34 +- .../common/ime_additional_properties.ts | 4 +- .../src/viewers/common/ime_ui_data.ts | 10 +- .../src/viewers/common/ime_utils.spec.ts | 101 ++- .../src/viewers/common/ime_utils.ts | 79 +-- .../viewers/common/presenter_input_method.ts | 122 ++-- .../presenter_input_method_test_utils.ts | 116 ++-- .../common/properties_tree_generator.spec.ts | 138 ++--- .../common/properties_tree_generator.ts | 44 +- .../src/viewers/common/rectangle.ts | 8 +- .../src/viewers/common/table_properties.ts | 2 +- .../src/viewers/common/tree_generator.spec.ts | 239 ++++--- .../src/viewers/common/tree_generator.ts | 95 +-- .../viewers/common/tree_transformer.spec.ts | 144 ++--- .../src/viewers/common/tree_transformer.ts | 154 +++-- .../src/viewers/common/ui_tree_utils.ts | 31 +- .../src/viewers/common/user_options.ts | 10 +- .../src/viewers/common/viewer_events.ts | 16 +- .../src/viewers/common/viewer_input_method.ts | 44 +- .../coordinates_table.component.spec.ts | 14 +- .../components/coordinates_table.component.ts | 15 +- .../components/hierarchy.component.spec.ts | 69 +-- .../viewers/components/hierarchy.component.ts | 100 ++- ...me_additional_properties.component.spec.ts | 20 +- .../ime_additional_properties.component.ts | 262 ++++---- .../components/properties.component.spec.ts | 56 +- .../components/properties.component.ts | 82 ++- .../properties_table.component.spec.ts | 14 +- .../components/properties_table.component.ts | 13 +- .../property_groups.component.spec.ts | 40 +- .../components/property_groups.component.ts | 105 ++-- .../src/viewers/components/rects/canvas.ts | 139 +++-- .../src/viewers/components/rects/mapper3d.ts | 86 +-- .../components/rects/rects.component.spec.ts | 80 ++- .../components/rects/rects.component.ts | 157 +++-- .../src/viewers/components/rects/types3d.ts | 13 +- .../viewers/components/styles/node.styles.ts | 2 +- .../styles/tree_node_data_view.styles.ts | 2 +- .../transform_matrix.component.spec.ts | 21 +- .../components/transform_matrix.component.ts | 61 +- .../viewers/components/tree.component.spec.ts | 53 +- .../src/viewers/components/tree.component.ts | 121 ++-- .../components/tree_node.component.spec.ts | 45 +- .../viewers/components/tree_node.component.ts | 52 +- .../tree_node_data_view.component.spec.ts | 21 +- .../tree_node_data_view.component.ts | 49 +- ...ode_properties_data_view.component.spec.ts | 17 +- ...ree_node_properties_data_view.component.ts | 25 +- .../viewer_input_method.component.spec.ts | 44 +- .../viewer_input_method.component.ts | 74 ++- tools/winscope-ng/src/viewers/viewer.ts | 7 +- .../winscope-ng/src/viewers/viewer_factory.ts | 20 +- .../presenter_input_method_clients.spec.ts | 19 +- .../presenter_input_method_clients.ts | 18 +- .../viewer_input_method_clients.ts | 12 +- ...enter_input_method_manager_service.spec.ts | 21 +- .../presenter_input_method_manager_service.ts | 32 +- .../viewer_input_method_manager_service.ts | 20 +- .../presenter_input_method_service.spec.ts | 20 +- .../presenter_input_method_service.ts | 15 +- .../viewer_input_method_service.ts | 15 +- .../src/viewers/viewer_protolog/events.ts | 8 +- .../viewers/viewer_protolog/presenter.spec.ts | 66 +- .../src/viewers/viewer_protolog/presenter.ts | 59 +- .../src/viewers/viewer_protolog/ui_data.ts | 6 +- .../viewer_protolog.component.spec.ts | 40 +- .../viewer_protolog.component.ts | 73 ++- .../viewer_protolog/viewer_protolog.ts | 14 +- .../viewer_screen_recording.component.spec.ts | 42 +- .../viewer_screen_recording.component.ts | 39 +- .../viewer_screen_recording.ts | 12 +- tools/winscope-ng/src/viewers/viewer_stub.ts | 4 +- .../viewer_surface_flinger/presenter.spec.ts | 132 ++-- .../viewer_surface_flinger/presenter.ts | 161 ++--- .../viewers/viewer_surface_flinger/ui_data.ts | 10 +- .../viewer_surface_flinger.component.spec.ts | 46 +- .../viewer_surface_flinger.component.ts | 31 +- .../viewer_surface_flinger.ts | 42 +- .../src/viewers/viewer_transactions/events.ts | 14 +- .../viewer_transactions/presenter.spec.ts | 193 +++--- .../viewers/viewer_transactions/presenter.ts | 283 +++++---- .../viewers/viewer_transactions/ui_data.ts | 32 +- .../viewer_transactions.component.spec.ts | 96 ++- .../viewer_transactions.component.ts | 106 ++-- .../viewer_transactions.ts | 14 +- .../viewer_window_manager/presenter.spec.ts | 144 +++-- .../viewer_window_manager/presenter.ts | 159 ++--- .../viewers/viewer_window_manager/ui_data.ts | 8 +- .../viewer_window_manager.component.spec.ts | 46 +- .../viewer_window_manager.component.ts | 70 +-- .../viewer_window_manager.ts | 44 +- tools/winscope-ng/webpack.config.common.js | 37 +- tools/winscope-ng/webpack.config.dev.js | 29 +- tools/winscope-ng/webpack.config.prod.js | 20 +- tools/winscope-ng/webpack.config.unit.spec.js | 25 +- 243 files changed, 8238 insertions(+), 7447 deletions(-) diff --git a/tools/winscope-ng/karma.conf.js b/tools/winscope-ng/karma.conf.js index 559235f79..58b6e0af2 100644 --- a/tools/winscope-ng/karma.conf.js +++ b/tools/winscope-ng/karma.conf.js @@ -13,25 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const webpackConfig = require("./webpack.config.common"); +const webpackConfig = require('./webpack.config.common'); delete webpackConfig.entry; delete webpackConfig.output; module.exports = (config) => { config.set({ - frameworks: ["jasmine", "webpack"], - plugins: [ - "karma-webpack", - "karma-chrome-launcher", - "karma-jasmine", - "karma-sourcemap-loader", - ], - files: [{ pattern: "src/main.component.spec.ts", watched: false }], + frameworks: ['jasmine', 'webpack'], + plugins: ['karma-webpack', 'karma-chrome-launcher', 'karma-jasmine', 'karma-sourcemap-loader'], + files: [{pattern: 'src/main.component.spec.ts', watched: false}], preprocessors: { - 'src/main.component.spec.ts': ['webpack', 'sourcemap'] + 'src/main.component.spec.ts': ['webpack', 'sourcemap'], }, singleRun: true, - browsers: ["ChromeHeadless"], - webpack: webpackConfig + browsers: ['ChromeHeadless'], + webpack: webpackConfig, }); -} +}; diff --git a/tools/winscope-ng/protractor.config.js b/tools/winscope-ng/protractor.config.js index bbbe9e78d..f1df7fb79 100644 --- a/tools/winscope-ng/protractor.config.js +++ b/tools/winscope-ng/protractor.config.js @@ -21,16 +21,16 @@ // and change the hardcoded version here exports.config = { - specs: ["dist/e2e.spec/e2e/*.spec.js"], + specs: ['dist/e2e.spec/e2e/*.spec.js'], directConnect: true, capabilities: { - browserName: "chrome", + browserName: 'chrome', chromeOptions: { - args: ["--headless", "--disable-gpu", "--window-size=1280x1024"] - } + args: ['--headless', '--disable-gpu', '--window-size=1280x1024'], + }, }, - chromeDriver: "./node_modules/webdriver-manager/selenium/chromedriver_108.0.5359.71", + chromeDriver: './node_modules/webdriver-manager/selenium/chromedriver_108.0.5359.71', allScriptsTimeout: 10000, getPageTimeout: 10000, @@ -39,11 +39,11 @@ exports.config = { defaultTimeoutInterval: 10000, }, - onPrepare: function() { + onPrepare: function () { // allow specifying the file protocol within browser.get(...) browser.ignoreSynchronization = true; browser.waitForAngular(); browser.sleep(500); - browser.resetUrl = "file:///"; - } + browser.resetUrl = 'file:///'; + }, }; diff --git a/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol.ts b/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol.ts index a8dad35f2..ece590016 100644 --- a/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol.ts +++ b/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol.ts @@ -14,21 +14,18 @@ * limitations under the License. */ -import { - MessageType, - OpenBuganizerResponse, - OpenRequest, - WebCommandMessage} from "./messages"; -import {FunctionUtils} from "common/utils/function_utils"; +import {FunctionUtils} from 'common/utils/function_utils'; import { BuganizerAttachmentsDownloadEmitter, + OnBuganizerAttachmentsDownloaded, OnBuganizerAttachmentsDownloadStart, - OnBuganizerAttachmentsDownloaded -} from "interfaces/buganizer_attachments_download_emitter"; +} from 'interfaces/buganizer_attachments_download_emitter'; +import {MessageType, OpenBuganizerResponse, OpenRequest, WebCommandMessage} from './messages'; export class AbtChromeExtensionProtocol implements BuganizerAttachmentsDownloadEmitter { - static readonly ABT_EXTENSION_ID = "mbbaofdfoekifkfpgehgffcpagbbjkmj"; - private onAttachmentsDownloadStart: OnBuganizerAttachmentsDownloadStart = FunctionUtils.DO_NOTHING; + static readonly ABT_EXTENSION_ID = 'mbbaofdfoekifkfpgehgffcpagbbjkmj'; + private onAttachmentsDownloadStart: OnBuganizerAttachmentsDownloadStart = + FunctionUtils.DO_NOTHING; private onttachmentsDownloaded: OnBuganizerAttachmentsDownloaded = FunctionUtils.DO_NOTHING_ASYNC; setOnBuganizerAttachmentsDownloadStart(callback: OnBuganizerAttachmentsDownloadStart) { @@ -41,14 +38,14 @@ export class AbtChromeExtensionProtocol implements BuganizerAttachmentsDownloadE run() { const urlParams = new URLSearchParams(window.location.search); - if (urlParams.get("source") !== "openFromExtension" || !chrome) { + if (urlParams.get('source') !== 'openFromExtension' || !chrome) { return; } this.onAttachmentsDownloadStart(); const openRequestMessage: OpenRequest = { - action: MessageType.OPEN_REQUEST + action: MessageType.OPEN_REQUEST, }; chrome.runtime.sendMessage( @@ -62,20 +59,18 @@ export class AbtChromeExtensionProtocol implements BuganizerAttachmentsDownloadE if (this.isOpenBuganizerResponseMessage(message)) { await this.onOpenBuganizerResponseMessageReceived(message); } else { - console.warn("ABT chrome extension protocol received unexpected message:", message); + console.warn('ABT chrome extension protocol received unexpected message:', message); } } private async onOpenBuganizerResponseMessageReceived(message: OpenBuganizerResponse) { - console.log( - "ABT chrome extension protocol received OpenBuganizerResponse message:", message - ); + console.log('ABT chrome extension protocol received OpenBuganizerResponse message:', message); if (message.attachments.length === 0) { - console.warn("ABT chrome extension protocol received no attachments"); + console.warn('ABT chrome extension protocol received no attachments'); } - const filesBlobPromises = message.attachments.map(async attachment => { + const filesBlobPromises = message.attachments.map(async (attachment) => { const fileQueryResponse = await fetch(attachment.objectUrl); const blob = await fileQueryResponse.blob(); @@ -91,8 +86,9 @@ export class AbtChromeExtensionProtocol implements BuganizerAttachmentsDownloadE await this.onttachmentsDownloaded(files); } - private isOpenBuganizerResponseMessage(message: WebCommandMessage): - message is OpenBuganizerResponse { + private isOpenBuganizerResponseMessage( + message: WebCommandMessage + ): message is OpenBuganizerResponse { return message.action === MessageType.OPEN_BUGANIZER_RESPONSE; } } diff --git a/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol_stub.ts b/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol_stub.ts index 9c4b23f61..795ecc829 100644 --- a/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol_stub.ts +++ b/tools/winscope-ng/src/abt_chrome_extension/abt_chrome_extension_protocol_stub.ts @@ -14,19 +14,21 @@ * limitations under the License. */ -import {FunctionUtils} from "common/utils/function_utils"; +import {FunctionUtils} from 'common/utils/function_utils'; import { BuganizerAttachmentsDownloadEmitter, + OnBuganizerAttachmentsDownloaded, OnBuganizerAttachmentsDownloadStart, - OnBuganizerAttachmentsDownloaded -} from "interfaces/buganizer_attachments_download_emitter"; -import {Runnable} from "interfaces/runnable"; +} from 'interfaces/buganizer_attachments_download_emitter'; +import {Runnable} from 'interfaces/runnable'; -export class AbtChromeExtensionProtocolStub implements - BuganizerAttachmentsDownloadEmitter, - Runnable { - onBuganizerAttachmentsDownloadStart: OnBuganizerAttachmentsDownloadStart = FunctionUtils.DO_NOTHING; - onBuganizerAttachmentsDownloaded: OnBuganizerAttachmentsDownloaded = FunctionUtils.DO_NOTHING_ASYNC; +export class AbtChromeExtensionProtocolStub + implements BuganizerAttachmentsDownloadEmitter, Runnable +{ + onBuganizerAttachmentsDownloadStart: OnBuganizerAttachmentsDownloadStart = + FunctionUtils.DO_NOTHING; + onBuganizerAttachmentsDownloaded: OnBuganizerAttachmentsDownloaded = + FunctionUtils.DO_NOTHING_ASYNC; setOnBuganizerAttachmentsDownloadStart(callback: OnBuganizerAttachmentsDownloadStart) { this.onBuganizerAttachmentsDownloadStart = callback; diff --git a/tools/winscope-ng/src/abt_chrome_extension/messages.ts b/tools/winscope-ng/src/abt_chrome_extension/messages.ts index d6ad07da8..fec7e1777 100644 --- a/tools/winscope-ng/src/abt_chrome_extension/messages.ts +++ b/tools/winscope-ng/src/abt_chrome_extension/messages.ts @@ -52,10 +52,10 @@ export declare interface OpenBuganizerResponse extends WebCommandMessage { issueId: string; /** issue title */ - issueTitle: string|undefined; + issueTitle: string | undefined; /** issue access level */ - issueAccessLevel: IssueAccessLimit|undefined; + issueAccessLevel: IssueAccessLimit | undefined; /** Attachment list. */ attachments: AttachmentMetadata[]; @@ -96,9 +96,9 @@ export interface BugReportMetadata { * http://go/buganizer/concepts/access-control#accesslimit */ export const enum IssueAccessLimit { - INTERNAL = "", - VISIBLE_TO_PARTNERS = "Visible to Partners", - VISIBLE_TO_PUBLIC = "Visible to Public", + INTERNAL = '', + VISIBLE_TO_PARTNERS = 'Visible to Partners', + VISIBLE_TO_PUBLIC = 'Visible to Public', } /** diff --git a/tools/winscope-ng/src/app/app.module.ts b/tools/winscope-ng/src/app/app.module.ts index b224598cf..71e16194a 100644 --- a/tools/winscope-ng/src/app/app.module.ts +++ b/tools/winscope-ng/src/app/app.module.ts @@ -14,66 +14,68 @@ * limitations under the License. */ -import { NgModule } from "@angular/core"; -import { BrowserModule } from "@angular/platform-browser"; -import { DragDropModule } from "@angular/cdk/drag-drop"; -import { ScrollingModule } from "@angular/cdk/scrolling"; -import { CommonModule } from "@angular/common"; -import { MatCardModule } from "@angular/material/card"; -import { MatButtonModule } from "@angular/material/button"; -import { MatGridListModule } from "@angular/material/grid-list"; -import { MatListModule } from "@angular/material/list"; -import { MatProgressSpinnerModule } from "@angular/material/progress-spinner"; -import { MatProgressBarModule } from "@angular/material/progress-bar"; -import { FormsModule, ReactiveFormsModule } from "@angular/forms"; -import { MatCheckboxModule } from "@angular/material/checkbox"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatIconModule } from "@angular/material/icon"; -import { MatInputModule } from "@angular/material/input"; -import { MatSelectModule } from "@angular/material/select"; -import { MatRadioModule } from "@angular/material/radio"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { HttpClientModule } from "@angular/common/http"; -import { MatSliderModule } from "@angular/material/slider"; -import { MatTooltipModule } from "@angular/material/tooltip"; -import { MatToolbarModule } from "@angular/material/toolbar"; -import { MatTabsModule } from "@angular/material/tabs"; -import { MatSnackBarModule } from "@angular/material/snack-bar"; - -import { AdbProxyComponent } from "./components/adb_proxy.component"; -import { AppComponent } from "./components/app.component"; -import { CollectTracesComponent } from "./components/collect_traces.component"; -import { LoadProgressComponent } from "./components/load_progress.component"; -import { ParserErrorSnackBarComponent } from "./components/parser_error_snack_bar_component"; -import { TraceConfigComponent } from "./components/trace_config.component"; -import { TraceViewComponent } from "./components/trace_view.component"; -import { UploadTracesComponent } from "./components/upload_traces.component"; -import { WebAdbComponent } from "./components/web_adb.component"; - -import { CoordinatesTableComponent } from "viewers/components/coordinates_table.component"; -import { HierarchyComponent } from "viewers/components/hierarchy.component"; -import { ImeAdditionalPropertiesComponent } from "viewers/components/ime_additional_properties.component"; -import { PropertiesComponent } from "viewers/components/properties.component"; -import { PropertiesTableComponent } from "viewers/components/properties_table.component"; -import { PropertyGroupsComponent } from "viewers/components/property_groups.component"; -import { RectsComponent } from "viewers/components/rects/rects.component"; -import { TransformMatrixComponent } from "viewers/components/transform_matrix.component"; -import { TreeComponent } from "viewers/components/tree.component"; -import { TreeNodeComponent } from "viewers/components/tree_node.component"; -import { TreeNodeDataViewComponent } from "viewers/components/tree_node_data_view.component"; -import { TreeNodePropertiesDataViewComponent } from "viewers/components/tree_node_properties_data_view.component"; -import { ViewerInputMethodComponent } from "viewers/components/viewer_input_method.component"; -import { ViewerProtologComponent} from "viewers/viewer_protolog/viewer_protolog.component"; -import { ViewerScreenRecordingComponent } from "viewers/viewer_screen_recording/viewer_screen_recording.component"; -import { ViewerSurfaceFlingerComponent } from "viewers/viewer_surface_flinger/viewer_surface_flinger.component"; -import { ViewerTransactionsComponent } from "viewers/viewer_transactions/viewer_transactions.component"; -import { ViewerWindowManagerComponent } from "viewers/viewer_window_manager/viewer_window_manager.component"; -import { TimelineComponent } from "./components/timeline/timeline.component"; -import { MiniTimelineComponent } from "./components/timeline/mini_timeline.component"; -import { ExpandedTimelineComponent } from "./components/timeline/expanded_timeline.component"; -import { SingleTimelineComponent } from "./components/timeline/single_timeline.component"; -import { MatDrawerContent, MatDrawer, MatDrawerContainer } from "./components/bottomnav/bottom_drawer.component"; +import {DragDropModule} from '@angular/cdk/drag-drop'; +import {ScrollingModule} from '@angular/cdk/scrolling'; +import {CommonModule} from '@angular/common'; +import {HttpClientModule} from '@angular/common/http'; +import {NgModule} from '@angular/core'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {MatButtonModule} from '@angular/material/button'; +import {MatCardModule} from '@angular/material/card'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatGridListModule} from '@angular/material/grid-list'; +import {MatIconModule} from '@angular/material/icon'; +import {MatInputModule} from '@angular/material/input'; +import {MatListModule} from '@angular/material/list'; +import {MatProgressBarModule} from '@angular/material/progress-bar'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; +import {MatRadioModule} from '@angular/material/radio'; +import {MatSelectModule} from '@angular/material/select'; +import {MatSliderModule} from '@angular/material/slider'; +import {MatSnackBarModule} from '@angular/material/snack-bar'; +import {MatTabsModule} from '@angular/material/tabs'; +import {MatToolbarModule} from '@angular/material/toolbar'; +import {MatTooltipModule} from '@angular/material/tooltip'; +import {BrowserModule} from '@angular/platform-browser'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {CoordinatesTableComponent} from 'viewers/components/coordinates_table.component'; +import {HierarchyComponent} from 'viewers/components/hierarchy.component'; +import {ImeAdditionalPropertiesComponent} from 'viewers/components/ime_additional_properties.component'; +import {PropertiesComponent} from 'viewers/components/properties.component'; +import {PropertiesTableComponent} from 'viewers/components/properties_table.component'; +import {PropertyGroupsComponent} from 'viewers/components/property_groups.component'; +import {RectsComponent} from 'viewers/components/rects/rects.component'; +import {TransformMatrixComponent} from 'viewers/components/transform_matrix.component'; +import {TreeComponent} from 'viewers/components/tree.component'; +import {TreeNodeComponent} from 'viewers/components/tree_node.component'; +import {TreeNodeDataViewComponent} from 'viewers/components/tree_node_data_view.component'; +import {TreeNodePropertiesDataViewComponent} from 'viewers/components/tree_node_properties_data_view.component'; +import {ViewerInputMethodComponent} from 'viewers/components/viewer_input_method.component'; +import {ViewerProtologComponent} from 'viewers/viewer_protolog/viewer_protolog.component'; +import {ViewerScreenRecordingComponent} from 'viewers/viewer_screen_recording/viewer_screen_recording.component'; +import {ViewerSurfaceFlingerComponent} from 'viewers/viewer_surface_flinger/viewer_surface_flinger.component'; +import {ViewerTransactionsComponent} from 'viewers/viewer_transactions/viewer_transactions.component'; +import {ViewerWindowManagerComponent} from 'viewers/viewer_window_manager/viewer_window_manager.component'; +import {AdbProxyComponent} from './components/adb_proxy.component'; +import {AppComponent} from './components/app.component'; +import { + MatDrawer, + MatDrawerContainer, + MatDrawerContent, +} from './components/bottomnav/bottom_drawer.component'; +import {CollectTracesComponent} from './components/collect_traces.component'; +import {LoadProgressComponent} from './components/load_progress.component'; +import {ParserErrorSnackBarComponent} from './components/parser_error_snack_bar_component'; +import {ExpandedTimelineComponent} from './components/timeline/expanded_timeline.component'; +import {MiniTimelineComponent} from './components/timeline/mini_timeline.component'; +import {SingleTimelineComponent} from './components/timeline/single_timeline.component'; +import {TimelineComponent} from './components/timeline/timeline.component'; +import {TraceConfigComponent} from './components/trace_config.component'; +import {TraceViewComponent} from './components/trace_view.component'; +import {UploadTracesComponent} from './components/upload_traces.component'; +import {WebAdbComponent} from './components/web_adb.component'; @NgModule({ declarations: [ @@ -110,7 +112,7 @@ import { MatDrawerContent, MatDrawer, MatDrawerContainer } from "./components/bo MatDrawer, MatDrawerContent, MatDrawerContainer, - LoadProgressComponent + LoadProgressComponent, ], imports: [ BrowserModule, @@ -141,6 +143,6 @@ import { MatDrawerContent, MatDrawer, MatDrawerContainer } from "./components/bo DragDropModule, ReactiveFormsModule, ], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) -export class AppModule { } +export class AppModule {} diff --git a/tools/winscope-ng/src/app/colors.ts b/tools/winscope-ng/src/app/colors.ts index 25283ca3c..09fb923f8 100644 --- a/tools/winscope-ng/src/app/colors.ts +++ b/tools/winscope-ng/src/app/colors.ts @@ -15,10 +15,10 @@ */ export enum Color { - SELECTOR_COLOR = "#8AB4F8", - SELECTION_BACKGROUND = "#E8F0FE", - ACTIVE_POINTER = "#1967D2", - GUIDE_BAR = "#3C4043", - GUIDE_BAR_LIGHT = "#9AA0A6", + SELECTOR_COLOR = '#8AB4F8', + SELECTION_BACKGROUND = '#E8F0FE', + ACTIVE_POINTER = '#1967D2', + GUIDE_BAR = '#3C4043', + GUIDE_BAR_LIGHT = '#9AA0A6', ACTIVE_BORDER = ACTIVE_POINTER, -} \ No newline at end of file +} diff --git a/tools/winscope-ng/src/app/components/adb_proxy.component.spec.ts b/tools/winscope-ng/src/app/components/adb_proxy.component.spec.ts index 3bae481d9..9ea449c76 100644 --- a/tools/winscope-ng/src/app/components/adb_proxy.component.spec.ts +++ b/tools/winscope-ng/src/app/components/adb_proxy.component.spec.ts @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CommonModule } from "@angular/common"; -import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { AdbProxyComponent } from "./adb_proxy.component"; -import { proxyClient, ProxyState } from "trace_collection/proxy_client"; -import { MatIconModule } from "@angular/material/icon"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatInputModule } from "@angular/material/input"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { MatButtonModule } from "@angular/material/button"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; +import {CommonModule} from '@angular/common'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatButtonModule} from '@angular/material/button'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatIconModule} from '@angular/material/icon'; +import {MatInputModule} from '@angular/material/input'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {proxyClient, ProxyState} from 'trace_collection/proxy_client'; +import {AdbProxyComponent} from './adb_proxy.component'; -describe("AdbProxyComponent", () => { +describe('AdbProxyComponent', () => { let fixture: ComponentFixture; let component: AdbProxyComponent; let htmlElement: HTMLElement; @@ -37,10 +37,10 @@ describe("AdbProxyComponent", () => { MatFormFieldModule, MatInputModule, BrowserAnimationsModule, - MatButtonModule + MatButtonModule, ], declarations: [AdbProxyComponent], - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(AdbProxyComponent); component = fixture.componentInstance; @@ -48,37 +48,41 @@ describe("AdbProxyComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("check correct icon and message displays if no proxy", () => { + it('check correct icon and message displays if no proxy', () => { component.proxy.setState(ProxyState.NO_PROXY); fixture.detectChanges(); - expect(htmlElement.querySelector(".further-adb-info-text")?.innerHTML).toContain("Launch the Winscope ADB Connect proxy"); + expect(htmlElement.querySelector('.further-adb-info-text')?.innerHTML).toContain( + 'Launch the Winscope ADB Connect proxy' + ); }); - it("check correct icon and message displays if invalid proxy", () => { + it('check correct icon and message displays if invalid proxy', () => { component.proxy.setState(ProxyState.INVALID_VERSION); fixture.detectChanges(); - expect(htmlElement.querySelector(".adb-info")?.innerHTML).toBe("Your local proxy version is incompatible with Winscope."); - expect(htmlElement.querySelector(".adb-icon")?.innerHTML).toBe("update"); + expect(htmlElement.querySelector('.adb-info')?.innerHTML).toBe( + 'Your local proxy version is incompatible with Winscope.' + ); + expect(htmlElement.querySelector('.adb-icon')?.innerHTML).toBe('update'); }); - it("check correct icon and message displays if unauthorised proxy", () => { + it('check correct icon and message displays if unauthorised proxy', () => { component.proxy.setState(ProxyState.UNAUTH); fixture.detectChanges(); - expect(htmlElement.querySelector(".adb-info")?.innerHTML).toBe("Proxy authorisation required."); - expect(htmlElement.querySelector(".adb-icon")?.innerHTML).toBe("lock"); + expect(htmlElement.querySelector('.adb-info')?.innerHTML).toBe('Proxy authorisation required.'); + expect(htmlElement.querySelector('.adb-icon')?.innerHTML).toBe('lock'); }); - it("check retry button acts as expected", async () => { + it('check retry button acts as expected', async () => { component.proxy.setState(ProxyState.NO_PROXY); fixture.detectChanges(); - spyOn(component, "restart").and.callThrough(); - const button: HTMLButtonElement | null = htmlElement.querySelector(".retry"); + spyOn(component, 'restart').and.callThrough(); + const button: HTMLButtonElement | null = htmlElement.querySelector('.retry'); expect(button).toBeInstanceOf(HTMLButtonElement); - button?.dispatchEvent(new Event("click")); + button?.dispatchEvent(new Event('click')); await fixture.whenStable(); expect(component.restart).toHaveBeenCalled(); }); diff --git a/tools/winscope-ng/src/app/components/adb_proxy.component.ts b/tools/winscope-ng/src/app/components/adb_proxy.component.ts index b8d2d8bfe..a6997b5cf 100644 --- a/tools/winscope-ng/src/app/components/adb_proxy.component.ts +++ b/tools/winscope-ng/src/app/components/adb_proxy.component.ts @@ -13,24 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input, Output, EventEmitter } from "@angular/core"; -import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_client"; +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {proxyClient, ProxyClient, ProxyState} from 'trace_collection/proxy_client'; @Component({ - selector: "adb-proxy", + selector: 'adb-proxy', template: `
-

Launch the Winscope ADB Connect proxy to capture traces directly from your browser.

+

+ Launch the Winscope ADB Connect proxy to capture traces directly from your browser. +

Python 3.5+ and ADB are required.

-

Run: python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py

+

+ Run: + + python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py + +

Or get it from the AOSP repository.

- - + +
@@ -41,13 +52,22 @@ import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_cli Your local proxy version is incompatible with Winscope.

Please update the proxy to version {{ proxyVersion }}.

-

Run: python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py

+

+ Run: + + python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py + +

Or get it from the AOSP repository.

- - + +
@@ -59,13 +79,17 @@ import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_cli

Enter Winscope proxy token:

- + -

The proxy token is printed to console on proxy launch, copy and paste it above.

+

+ The proxy token is printed to console on proxy launch, copy and paste it above. +

- +
@@ -95,23 +119,24 @@ import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_cli .adb-info { margin-left: 5px; } - ` - ] + `, + ], }) export class AdbProxyComponent { @Input() - proxy: ProxyClient = proxyClient; + proxy: ProxyClient = proxyClient; @Output() - proxyChange = new EventEmitter(); + proxyChange = new EventEmitter(); @Output() - addKey = new EventEmitter(); + addKey = new EventEmitter(); states = ProxyState; - proxyKeyItem = ""; + proxyKeyItem = ''; readonly proxyVersion = this.proxy.VERSION; - readonly downloadProxyUrl: string = "https://android.googlesource.com/platform/development/+/master/tools/winscope/adb_proxy/winscope_proxy.py"; + readonly downloadProxyUrl: string = + 'https://android.googlesource.com/platform/development/+/master/tools/winscope/adb_proxy/winscope_proxy.py'; public restart() { this.addKey.emit(this.proxyKeyItem); @@ -120,6 +145,6 @@ export class AdbProxyComponent { } public downloadFromAosp() { - window.open(this.downloadProxyUrl, "_blank")?.focus(); + window.open(this.downloadProxyUrl, '_blank')?.focus(); } } diff --git a/tools/winscope-ng/src/app/components/app.component.spec.ts b/tools/winscope-ng/src/app/components/app.component.spec.ts index 9d4323f16..ad594db14 100644 --- a/tools/winscope-ng/src/app/components/app.component.spec.ts +++ b/tools/winscope-ng/src/app/components/app.component.spec.ts @@ -13,43 +13,41 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ChangeDetectionStrategy } from "@angular/core"; -import {ComponentFixture, TestBed, ComponentFixtureAutoDetect} from "@angular/core/testing"; -import { CommonModule } from "@angular/common"; -import { FormsModule, ReactiveFormsModule } from "@angular/forms"; -import { MatCardModule } from "@angular/material/card"; -import { MatButtonModule } from "@angular/material/button"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatIconModule } from "@angular/material/icon"; -import { MatSelectModule } from "@angular/material/select"; -import { MatSliderModule } from "@angular/material/slider"; -import { MatSnackBarModule } from "@angular/material/snack-bar"; -import { MatToolbarModule } from "@angular/material/toolbar"; -import { MatTooltipModule } from "@angular/material/tooltip"; +import {CommonModule} from '@angular/common'; +import {ChangeDetectionStrategy} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {MatButtonModule} from '@angular/material/button'; +import {MatCardModule} from '@angular/material/card'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatIconModule} from '@angular/material/icon'; +import {MatSelectModule} from '@angular/material/select'; +import {MatSliderModule} from '@angular/material/slider'; +import {MatSnackBarModule} from '@angular/material/snack-bar'; +import {MatToolbarModule} from '@angular/material/toolbar'; +import {MatTooltipModule} from '@angular/material/tooltip'; -import { AppComponent } from "./app.component"; -import { MatDrawer, MatDrawerContainer, MatDrawerContent } from "./bottomnav/bottom_drawer.component"; -import { CollectTracesComponent } from "./collect_traces.component"; -import { UploadTracesComponent } from "./upload_traces.component"; -import { AdbProxyComponent } from "./adb_proxy.component"; -import { WebAdbComponent } from "./web_adb.component"; -import { TraceConfigComponent } from "./trace_config.component"; -import { ViewerSurfaceFlingerComponent } from "viewers/viewer_surface_flinger/viewer_surface_flinger.component"; -import { TimelineComponent } from "./timeline/timeline.component"; -import { MiniTimelineComponent } from "./timeline/mini_timeline.component"; -import { TraceViewComponent } from "./trace_view.component"; +import {ViewerSurfaceFlingerComponent} from 'viewers/viewer_surface_flinger/viewer_surface_flinger.component'; +import {AdbProxyComponent} from './adb_proxy.component'; +import {AppComponent} from './app.component'; +import {MatDrawer, MatDrawerContainer, MatDrawerContent} from './bottomnav/bottom_drawer.component'; +import {CollectTracesComponent} from './collect_traces.component'; +import {MiniTimelineComponent} from './timeline/mini_timeline.component'; +import {TimelineComponent} from './timeline/timeline.component'; +import {TraceConfigComponent} from './trace_config.component'; +import {TraceViewComponent} from './trace_view.component'; +import {UploadTracesComponent} from './upload_traces.component'; +import {WebAdbComponent} from './web_adb.component'; -describe("AppComponent", () => { +describe('AppComponent', () => { let fixture: ComponentFixture; let component: AppComponent; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], imports: [ CommonModule, FormsModule, @@ -63,7 +61,7 @@ describe("AppComponent", () => { MatSnackBarModule, MatToolbarModule, MatTooltipModule, - ReactiveFormsModule + ReactiveFormsModule, ], declarations: [ AdbProxyComponent, @@ -78,45 +76,47 @@ describe("AppComponent", () => { TraceViewComponent, UploadTracesComponent, ViewerSurfaceFlingerComponent, - WebAdbComponent + WebAdbComponent, ], - }).overrideComponent(AppComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); + }) + .overrideComponent(AppComponent, { + set: {changeDetection: ChangeDetectionStrategy.Default}, + }) + .compileComponents(); fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("has the expected title", () => { - expect(component.title).toEqual("winscope-ng"); + it('has the expected title', () => { + expect(component.title).toEqual('winscope-ng'); }); - it("renders the page title", () => { - expect(htmlElement.querySelector(".app-title")?.innerHTML).toContain("Winscope"); + it('renders the page title', () => { + expect(htmlElement.querySelector('.app-title')?.innerHTML).toContain('Winscope'); }); - it("displays correct elements when no data loaded", () => { + it('displays correct elements when no data loaded', () => { component.dataLoaded = false; fixture.detectChanges(); - expect(htmlElement.querySelector(".welcome-info")).toBeTruthy(); - expect(htmlElement.querySelector(".active-trace-file-info")).toBeFalsy(); - expect(htmlElement.querySelector(".collect-traces-card")).toBeTruthy(); - expect(htmlElement.querySelector(".upload-traces-card")).toBeTruthy(); - expect(htmlElement.querySelector(".viewers")).toBeFalsy(); + expect(htmlElement.querySelector('.welcome-info')).toBeTruthy(); + expect(htmlElement.querySelector('.active-trace-file-info')).toBeFalsy(); + expect(htmlElement.querySelector('.collect-traces-card')).toBeTruthy(); + expect(htmlElement.querySelector('.upload-traces-card')).toBeTruthy(); + expect(htmlElement.querySelector('.viewers')).toBeFalsy(); }); - it("displays correct elements when data loaded", () => { + it('displays correct elements when data loaded', () => { component.dataLoaded = true; fixture.detectChanges(); - expect(htmlElement.querySelector(".welcome-info")).toBeFalsy(); - expect(htmlElement.querySelector(".active-trace-file-info")).toBeTruthy(); - expect(htmlElement.querySelector(".collect-traces-card")).toBeFalsy(); - expect(htmlElement.querySelector(".upload-traces-card")).toBeFalsy(); - expect(htmlElement.querySelector(".viewers")).toBeTruthy(); + expect(htmlElement.querySelector('.welcome-info')).toBeFalsy(); + expect(htmlElement.querySelector('.active-trace-file-info')).toBeTruthy(); + expect(htmlElement.querySelector('.collect-traces-card')).toBeFalsy(); + expect(htmlElement.querySelector('.upload-traces-card')).toBeFalsy(); + expect(htmlElement.querySelector('.viewers')).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/app/components/app.component.ts b/tools/winscope-ng/src/app/components/app.component.ts index 396c5d627..348766698 100644 --- a/tools/winscope-ng/src/app/components/app.component.ts +++ b/tools/winscope-ng/src/app/components/app.component.ts @@ -17,112 +17,100 @@ import { ChangeDetectorRef, Component, - Injector, Inject, + Injector, ViewChild, - ViewEncapsulation -} from "@angular/core"; -import { createCustomElement } from "@angular/elements"; -import { TimelineComponent} from "./timeline/timeline.component"; -import {AbtChromeExtensionProtocol} from "abt_chrome_extension/abt_chrome_extension_protocol"; -import {CrossToolProtocol} from "cross_tool/cross_tool_protocol"; -import { Mediator } from "app/mediator"; -import { TraceData } from "app/trace_data"; -import { PersistentStore } from "common/utils/persistent_store"; -import { Timestamp } from "common/trace/timestamp"; -import { FileUtils } from "common/utils/file_utils"; -import { proxyClient, ProxyState } from "trace_collection/proxy_client"; -import { ViewerInputMethodComponent } from "viewers/components/viewer_input_method.component"; -import { View, Viewer } from "viewers/viewer"; -import { ViewerProtologComponent} from "viewers/viewer_protolog/viewer_protolog.component"; -import { ViewerSurfaceFlingerComponent } from "viewers/viewer_surface_flinger/viewer_surface_flinger.component"; -import { ViewerWindowManagerComponent } from "viewers/viewer_window_manager/viewer_window_manager.component"; -import { ViewerTransactionsComponent } from "viewers/viewer_transactions/viewer_transactions.component"; -import { ViewerScreenRecordingComponent } from "viewers/viewer_screen_recording/viewer_screen_recording.component"; -import { TraceType } from "common/trace/trace_type"; -import { TimelineData } from "app/timeline_data"; -import { TracingConfig } from "trace_collection/tracing_config"; -import {TRACE_INFO} from "app/trace_info"; -import {UploadTracesComponent} from "./upload_traces.component"; -import {TraceDataListener} from "interfaces/trace_data_listener"; + ViewEncapsulation, +} from '@angular/core'; +import {createCustomElement} from '@angular/elements'; +import {AbtChromeExtensionProtocol} from 'abt_chrome_extension/abt_chrome_extension_protocol'; +import {Mediator} from 'app/mediator'; +import {TimelineData} from 'app/timeline_data'; +import {TraceData} from 'app/trace_data'; +import {TRACE_INFO} from 'app/trace_info'; +import {Timestamp} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {FileUtils} from 'common/utils/file_utils'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {CrossToolProtocol} from 'cross_tool/cross_tool_protocol'; +import {TraceDataListener} from 'interfaces/trace_data_listener'; +import {proxyClient, ProxyState} from 'trace_collection/proxy_client'; +import {TracingConfig} from 'trace_collection/tracing_config'; +import {ViewerInputMethodComponent} from 'viewers/components/viewer_input_method.component'; +import {View, Viewer} from 'viewers/viewer'; +import {ViewerProtologComponent} from 'viewers/viewer_protolog/viewer_protolog.component'; +import {ViewerScreenRecordingComponent} from 'viewers/viewer_screen_recording/viewer_screen_recording.component'; +import {ViewerSurfaceFlingerComponent} from 'viewers/viewer_surface_flinger/viewer_surface_flinger.component'; +import {ViewerTransactionsComponent} from 'viewers/viewer_transactions/viewer_transactions.component'; +import {ViewerWindowManagerComponent} from 'viewers/viewer_window_manager/viewer_window_manager.component'; +import {TimelineComponent} from './timeline/timeline.component'; +import {UploadTracesComponent} from './upload_traces.component'; @Component({ - selector: "app-root", + selector: 'app-root', template: ` Winscope - +
- {{activeTraceFileInfo}} + {{ activeTraceFileInfo }}
-
- - + - - + class="viewers" + [viewers]="viewers" + [store]="store" + (downloadTracesButtonClick)="onDownloadTracesButtonClick()" + (activeViewChanged)="onActiveViewChanged($event)"> - - - - + + *ngIf="dataLoaded" + [timelineData]="timelineData" + [activeViewTraceTypes]="activeView?.dependencies" + [availableTraces]="getLoadedTraceTypes()" + (collapsedTimelineSizeChanged)="onCollapsedTimelineSizeChanged($event)"> - @@ -134,17 +122,15 @@ import {TraceDataListener} from "interfaces/trace_data_listener";
+ class="collect-traces-card homepage-card" + [traceData]="traceData" + (traceDataLoaded)="mediator.onWinscopeTraceDataLoaded()" + [store]="store"> + class="upload-traces-card homepage-card" + [traceData]="traceData" + (traceDataLoaded)="mediator.onWinscopeTraceDataLoaded()">
@@ -194,12 +180,12 @@ import {TraceDataListener} from "interfaces/trace_data_listener"; flex-grow: 1; margin: auto; } - ` + `, ], - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, }) export class AppComponent implements TraceDataListener { - title = "winscope-ng"; + title = 'winscope-ng'; changeDetectorRef: ChangeDetectorRef; traceData = new TraceData(); timelineData = new TimelineData(); @@ -220,7 +206,7 @@ export class AppComponent implements TraceDataListener { isDarkModeOn!: boolean; dataLoaded = false; activeView?: View; - activeTraceFileInfo = ""; + activeTraceFileInfo = ''; collapsedTimelineHeight = 0; @ViewChild(UploadTracesComponent) uploadTracesComponent?: UploadTracesComponent; @ViewChild(TimelineComponent) timelineComponent?: TimelineComponent; @@ -231,33 +217,45 @@ export class AppComponent implements TraceDataListener { ) { this.changeDetectorRef = changeDetectorRef; - const storeDarkMode = this.store.get("dark-mode"); - const prefersDarkQuery = window.matchMedia?.("(prefers-color-scheme: dark)"); - this.setDarkMode(storeDarkMode != null ? storeDarkMode == "true" : prefersDarkQuery.matches); + const storeDarkMode = this.store.get('dark-mode'); + const prefersDarkQuery = window.matchMedia?.('(prefers-color-scheme: dark)'); + this.setDarkMode(storeDarkMode != null ? storeDarkMode == 'true' : prefersDarkQuery.matches); - if (!customElements.get("viewer-input-method")) { - customElements.define("viewer-input-method", - createCustomElement(ViewerInputMethodComponent, {injector})); + if (!customElements.get('viewer-input-method')) { + customElements.define( + 'viewer-input-method', + createCustomElement(ViewerInputMethodComponent, {injector}) + ); } - if (!customElements.get("viewer-protolog")) { - customElements.define("viewer-protolog", - createCustomElement(ViewerProtologComponent, {injector})); + if (!customElements.get('viewer-protolog')) { + customElements.define( + 'viewer-protolog', + createCustomElement(ViewerProtologComponent, {injector}) + ); } - if (!customElements.get("viewer-screen-recording")) { - customElements.define("viewer-screen-recording", - createCustomElement(ViewerScreenRecordingComponent, {injector})); + if (!customElements.get('viewer-screen-recording')) { + customElements.define( + 'viewer-screen-recording', + createCustomElement(ViewerScreenRecordingComponent, {injector}) + ); } - if (!customElements.get("viewer-surface-flinger")) { - customElements.define("viewer-surface-flinger", - createCustomElement(ViewerSurfaceFlingerComponent, {injector})); + if (!customElements.get('viewer-surface-flinger')) { + customElements.define( + 'viewer-surface-flinger', + createCustomElement(ViewerSurfaceFlingerComponent, {injector}) + ); } - if (!customElements.get("viewer-transactions")) { - customElements.define("viewer-transactions", - createCustomElement(ViewerTransactionsComponent, {injector})); + if (!customElements.get('viewer-transactions')) { + customElements.define( + 'viewer-transactions', + createCustomElement(ViewerTransactionsComponent, {injector}) + ); } - if (!customElements.get("viewer-window-manager")) { - customElements.define("viewer-window-manager", - createCustomElement(ViewerWindowManagerComponent, {injector})); + if (!customElements.get('viewer-window-manager')) { + customElements.define( + 'viewer-window-manager', + createCustomElement(ViewerWindowManagerComponent, {injector}) + ); } TracingConfig.getInstance().initialize(localStorage); @@ -281,7 +279,7 @@ export class AppComponent implements TraceDataListener { return this.traceData.getLoadedTraces().map((trace) => trace.type); } - getVideoData(): Blob|undefined { + getVideoData(): Blob | undefined { return this.timelineData.getScreenRecordingVideo(); } @@ -298,17 +296,17 @@ export class AppComponent implements TraceDataListener { } public setDarkMode(enabled: boolean) { - document.body.classList.toggle("dark-mode", enabled); - this.store.add("dark-mode", `${enabled}`); + document.body.classList.toggle('dark-mode', enabled); + this.store.add('dark-mode', `${enabled}`); this.isDarkModeOn = enabled; } async onDownloadTracesButtonClick() { const traceFiles = await this.makeTraceFilesForDownload(); const zipFileBlob = await FileUtils.createZipArchive(traceFiles); - const zipFileName = "winscope.zip"; + const zipFileName = 'winscope.zip'; - const a = document.createElement("a"); + const a = document.createElement('a'); document.body.appendChild(a); const url = window.URL.createObjectURL(zipFileBlob); a.href = url; @@ -324,18 +322,17 @@ export class AppComponent implements TraceDataListener { this.timelineData.setActiveViewTraceTypes(view.dependencies); } - goToLink(url: string){ - window.open(url, "_blank"); + goToLink(url: string) { + window.open(url, '_blank'); } private makeActiveTraceFileInfo(view: View): string { const traceFile = this.traceData .getLoadedTraces() - .find(trace => trace.type === view.dependencies[0]) - ?.traceFile; + .find((trace) => trace.type === view.dependencies[0])?.traceFile; if (!traceFile) { - return ""; + return ''; } if (!traceFile.parentArchive) { @@ -346,9 +343,9 @@ export class AppComponent implements TraceDataListener { } private async makeTraceFilesForDownload(): Promise { - return this.traceData.getLoadedTraces().map(trace => { + return this.traceData.getLoadedTraces().map((trace) => { const traceType = TRACE_INFO[trace.type].name; - const newName = traceType + "/" + FileUtils.removeDirFromFileName(trace.traceFile.file.name); + const newName = traceType + '/' + FileUtils.removeDirFromFileName(trace.traceFile.file.name); return new File([trace.traceFile.file], newName); }); } diff --git a/tools/winscope-ng/src/app/components/app_component_stub.ts b/tools/winscope-ng/src/app/components/app_component_stub.ts index dea90e16b..2e84e8d48 100644 --- a/tools/winscope-ng/src/app/components/app_component_stub.ts +++ b/tools/winscope-ng/src/app/components/app_component_stub.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import {Viewer} from "viewers/viewer"; -import {TraceDataListener} from "interfaces/trace_data_listener"; +import {TraceDataListener} from 'interfaces/trace_data_listener'; +import {Viewer} from 'viewers/viewer'; export class AppComponentStub implements TraceDataListener { onTraceDataLoaded(viewers: Viewer[]) { diff --git a/tools/winscope-ng/src/app/components/bottomnav/bottom_drawer.component.ts b/tools/winscope-ng/src/app/components/bottomnav/bottom_drawer.component.ts index a9aa3a6d5..839ec74d2 100644 --- a/tools/winscope-ng/src/app/components/bottomnav/bottom_drawer.component.ts +++ b/tools/winscope-ng/src/app/components/bottomnav/bottom_drawer.component.ts @@ -1,46 +1,43 @@ /* -* Copyright (C) 2022 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + animate, + AnimationTriggerMetadata, + state, + style, + transition, + trigger, +} from '@angular/animations'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, + ElementRef, forwardRef, Inject, - ViewEncapsulation, - ElementRef, - NgZone, Injectable, - ViewChild, Input, -} from "@angular/core"; -import { - animate, - state, - style, - transition, - trigger, - AnimationTriggerMetadata, -} from "@angular/animations"; -import {Subject} from "rxjs"; -import { - debounceTime, - takeUntil, -} from "rxjs/operators"; + NgZone, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; +import {Subject} from 'rxjs'; +import {debounceTime, takeUntil} from 'rxjs/operators'; /** * Animations used by the Material drawers. @@ -50,30 +47,30 @@ export const matDrawerAnimations: { readonly transformDrawer: AnimationTriggerMetadata; } = { /** Animation that slides a drawer in and out. */ - transformDrawer: trigger("transform", [ + transformDrawer: trigger('transform', [ // We remove the `transform` here completely, rather than setting it to zero, because: // 1. Having a transform can cause elements with ripples or an animated // transform to shift around in Chrome with an RTL layout (see #10023). // 2. 3d transforms causes text to appear blurry on IE and Edge. state( - "open, open-instant", + 'open, open-instant', style({ - "transform": "none", - "visibility": "visible", - }), + transform: 'none', + visibility: 'visible', + }) ), state( - "void", + 'void', style({ // Avoids the shadow showing up when closed in SSR. - "box-shadow": "none", - "visibility": "hidden", - }), + 'box-shadow': 'none', + visibility: 'hidden', + }) ), - transition("void => open-instant", animate("0ms")), + transition('void => open-instant', animate('0ms')), transition( - "void <=> open, open-instant => void", - animate("400ms cubic-bezier(0.25, 0.8, 0.25, 1)"), + 'void <=> open, open-instant => void', + animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)') ), ]), }; @@ -83,33 +80,38 @@ export const matDrawerAnimations: { */ @Injectable() @Component({ - selector: "mat-drawer", - exportAs: "matDrawer", + selector: 'mat-drawer', + exportAs: 'matDrawer', template: `
`, - styles: [` - .mat-drawer.mat-drawer-bottom { - left: 0; right: 0; bottom: 0; top: unset; - position: fixed; - z-index: 5; - background-color: #F8F9FA; - box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3), 0px 1px 3px 1px rgba(0, 0, 0, 0.15); - } - `], + styles: [ + ` + .mat-drawer.mat-drawer-bottom { + left: 0; + right: 0; + bottom: 0; + top: unset; + position: fixed; + z-index: 5; + background-color: #f8f9fa; + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3), 0px 1px 3px 1px rgba(0, 0, 0, 0.15); + } + `, + ], animations: [matDrawerAnimations.transformDrawer], host: { - "class": "mat-drawer mat-drawer-bottom", + class: 'mat-drawer mat-drawer-bottom', // must prevent the browser from aligning text based on value - "[attr.align]": "null", + '[attr.align]': 'null', }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, }) export class MatDrawer { - @Input() mode: "push"|"overlay" = "overlay"; + @Input() mode: 'push' | 'overlay' = 'overlay'; @Input() baseHeight = 0; public getBaseHeight() { @@ -118,9 +120,10 @@ export class MatDrawer { } @Component({ - selector: "mat-drawer-content", - template: "", - styles: [` + selector: 'mat-drawer-content', + template: '', + styles: [ + ` .mat-drawer-content { display: flex; flex-direction: column; @@ -131,22 +134,22 @@ export class MatDrawer { width: 100%; flex-grow: 1; } - `], + `, + ], host: { - "class": "mat-drawer-content", - "[style.margin-top.px]": "contentMargins.top", - "[style.margin-bottom.px]": "contentMargins.bottom", + class: 'mat-drawer-content', + '[style.margin-top.px]': 'contentMargins.top', + '[style.margin-bottom.px]': 'contentMargins.bottom', }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, }) export class MatDrawerContent /*extends MatDrawerContentBase*/ { - private contentMargins: {top: number | null; bottom: number | null} = {top: null, bottom: null}; constructor( @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef, - @Inject(forwardRef(() => MatDrawerContainer)) public container: MatDrawerContainer, + @Inject(forwardRef(() => MatDrawerContainer)) public container: MatDrawerContainer ) {} ngAfterContentInit() { @@ -161,26 +164,27 @@ export class MatDrawerContent /*extends MatDrawerContentBase*/ { } @Component({ - selector: "mat-drawer-container", - exportAs: "matDrawerContainer", + selector: 'mat-drawer-container', + exportAs: 'matDrawerContainer', template: ` - - + `, - styles: [` - .mat-drawer-container { - display: flex; - flex-direction: column; - flex-grow: 1; - align-items: center; - align-content: center; - justify-content: center; - } - `], + styles: [ + ` + .mat-drawer-container { + display: flex; + flex-direction: column; + flex-grow: 1; + align-items: center; + align-content: center; + justify-content: center; + } + `, + ], host: { - "class": "mat-drawer-container", + class: 'mat-drawer-container', }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, @@ -189,7 +193,7 @@ export class MatDrawerContent /*extends MatDrawerContentBase*/ { export class MatDrawerContainer /*extends MatDrawerContainerBase*/ { /** Drawer that belong to this container. */ @ContentChild(MatDrawer) drawer!: MatDrawer; - @ContentChild(MatDrawer, { read: ElementRef }) drawerView!: ElementRef; + @ContentChild(MatDrawer, {read: ElementRef}) drawerView!: ElementRef; @ContentChild(MatDrawerContent) content!: MatDrawerContent; @ViewChild(MatDrawerContent) userContent!: MatDrawerContent; @@ -209,9 +213,7 @@ export class MatDrawerContainer /*extends MatDrawerContainerBase*/ { /** Emits when the component is destroyed. */ private readonly destroyed = new Subject(); - constructor( - @Inject(NgZone) private ngZone: NgZone, - ) {} + constructor(@Inject(NgZone) private ngZone: NgZone) {} ngAfterContentInit() { this.updateContentMargins(); @@ -221,7 +223,7 @@ export class MatDrawerContainer /*extends MatDrawerContainerBase*/ { this.doCheckSubject .pipe( debounceTime(10), // Arbitrary debounce time, less than a frame at 60fps - takeUntil(this.destroyed), + takeUntil(this.destroyed) ) .subscribe(() => this.updateContentMargins()); }); @@ -250,7 +252,7 @@ export class MatDrawerContainer /*extends MatDrawerContainerBase*/ { const baseHeight = this.drawer.getBaseHeight(); const height = this.getDrawerHeight(); - const shiftAmount = this.drawer.mode === "push" ? Math.max(0, height - baseHeight) : 0; + const shiftAmount = this.drawer.mode === 'push' ? Math.max(0, height - baseHeight) : 0; top -= shiftAmount; bottom += baseHeight + shiftAmount; @@ -276,4 +278,4 @@ export class MatDrawerContainer /*extends MatDrawerContainerBase*/ { getDrawerHeight(): number { return this.drawerView.nativeElement ? this.drawerView.nativeElement.offsetHeight || 0 : 0; } -} \ No newline at end of file +} diff --git a/tools/winscope-ng/src/app/components/canvas/canvas_drawer.ts b/tools/winscope-ng/src/app/components/canvas/canvas_drawer.ts index 75d89d01f..3b9fd2820 100644 --- a/tools/winscope-ng/src/app/components/canvas/canvas_drawer.ts +++ b/tools/winscope-ng/src/app/components/canvas/canvas_drawer.ts @@ -14,18 +14,18 @@ * limitations under the License. */ -import { CanvasMouseHandler } from "./canvas_mouse_handler"; +import {CanvasMouseHandler} from './canvas_mouse_handler'; -export type padding = {left: number, top: number, right: number, bottom: number}; +export type padding = {left: number; top: number; right: number; bottom: number}; export interface CanvasDrawer { draw(): void; - handler: CanvasMouseHandler - canvas: HTMLCanvasElement - ctx: CanvasRenderingContext2D - padding: padding - getXScale(): number - getYScale(): number - getWidth(): number - getHeight(): number -} \ No newline at end of file + handler: CanvasMouseHandler; + canvas: HTMLCanvasElement; + ctx: CanvasRenderingContext2D; + padding: padding; + getXScale(): number; + getYScale(): number; + getWidth(): number; + getHeight(): number; +} diff --git a/tools/winscope-ng/src/app/components/canvas/canvas_mouse_handler.ts b/tools/winscope-ng/src/app/components/canvas/canvas_mouse_handler.ts index 35ddbf241..14f9a44a1 100644 --- a/tools/winscope-ng/src/app/components/canvas/canvas_mouse_handler.ts +++ b/tools/winscope-ng/src/app/components/canvas/canvas_mouse_handler.ts @@ -14,42 +14,49 @@ * limitations under the License. */ -import { CanvasDrawer } from "./canvas_drawer"; -import { DraggableCanvasObject } from "./draggable_canvas_object"; +import {CanvasDrawer} from './canvas_drawer'; +import {DraggableCanvasObject} from './draggable_canvas_object'; export type DragListener = (x: number, y: number) => void; export type DropListener = DragListener; export class CanvasMouseHandler { - // Ordered top most element to bottom most private draggableObjects = new Array(); - private draggingObject: DraggableCanvasObject|undefined = undefined; + private draggingObject: DraggableCanvasObject | undefined = undefined; private onDrag = new Map(); private onDrop = new Map(); constructor( private drawer: CanvasDrawer, - private defaultCursor: string = "auto", + private defaultCursor: string = 'auto', private onUnhandledMouseDown: (x: number, y: number) => void = (x, y) => {} ) { - this.drawer.canvas.addEventListener("mousemove", (event) => { this.handleMouseMove(event); }); - this.drawer.canvas.addEventListener("mousedown", (event) => { this.handleMouseDown(event); }); - this.drawer.canvas.addEventListener("mouseup", (event) => { this.handleMouseUp(event); }); - this.drawer.canvas.addEventListener("mouseout", (event) => { this.handleMouseUp(event); }); + this.drawer.canvas.addEventListener('mousemove', (event) => { + this.handleMouseMove(event); + }); + this.drawer.canvas.addEventListener('mousedown', (event) => { + this.handleMouseDown(event); + }); + this.drawer.canvas.addEventListener('mouseup', (event) => { + this.handleMouseUp(event); + }); + this.drawer.canvas.addEventListener('mouseout', (event) => { + this.handleMouseUp(event); + }); } public registerDraggableObject( draggableObject: DraggableCanvasObject, onDrag: DragListener, - onDrop: DropListener, + onDrop: DropListener ) { this.onDrag.set(draggableObject, onDrag); this.onDrop.set(draggableObject, onDrop); } - public notifyDrawnOnTop(draggableObject: DraggableCanvasObject,) { + public notifyDrawnOnTop(draggableObject: DraggableCanvasObject) { const foundIndex = this.draggableObjects.indexOf(draggableObject); if (foundIndex !== -1) { this.draggableObjects.splice(foundIndex, 1); @@ -60,7 +67,7 @@ export class CanvasMouseHandler { private handleMouseDown(e: MouseEvent) { e.preventDefault(); e.stopPropagation(); - const { mouseX, mouseY } = this.getPos(e); + const {mouseX, mouseY} = this.getPos(e); const clickedObject = this.objectAt(mouseX, mouseY); if (clickedObject !== undefined) { @@ -74,7 +81,7 @@ export class CanvasMouseHandler { private handleMouseMove(e: MouseEvent) { e.preventDefault(); e.stopPropagation(); - const { mouseX, mouseY } = this.getPos(e); + const {mouseX, mouseY} = this.getPos(e); if (this.draggingObject !== undefined) { const onDragCallback = this.onDrag.get(this.draggingObject); @@ -89,7 +96,7 @@ export class CanvasMouseHandler { private handleMouseUp(e: MouseEvent) { e.preventDefault(); e.stopPropagation(); - const { mouseX, mouseY } = this.getPos(e); + const {mouseX, mouseY} = this.getPos(e); if (this.draggingObject !== undefined) { const onDropCallback = this.onDrop.get(this.draggingObject); @@ -111,29 +118,34 @@ export class CanvasMouseHandler { } if (mouseX > this.drawer.getWidth() - this.drawer.padding.right) { - mouseX = this.drawer.getWidth()- this.drawer.padding.right; + mouseX = this.drawer.getWidth() - this.drawer.padding.right; } - return { mouseX, mouseY }; + return {mouseX, mouseY}; } private updateCursor(mouseX: number, mouseY: number) { const hoverObject = this.objectAt(mouseX, mouseY); if (hoverObject !== undefined) { if (hoverObject === this.draggingObject) { - this.drawer.canvas.style.cursor = "grabbing"; + this.drawer.canvas.style.cursor = 'grabbing'; } else { - this.drawer.canvas.style.cursor = "grab"; + this.drawer.canvas.style.cursor = 'grab'; } } else { this.drawer.canvas.style.cursor = this.defaultCursor; } } - private objectAt(mouseX: number, mouseY: number): DraggableCanvasObject|undefined { + private objectAt(mouseX: number, mouseY: number): DraggableCanvasObject | undefined { for (const object of this.draggableObjects) { object.definePath(this.drawer.ctx); - if (this.drawer.ctx.isPointInPath(mouseX * this.drawer.getXScale(), mouseY * this.drawer.getYScale())) { + if ( + this.drawer.ctx.isPointInPath( + mouseX * this.drawer.getXScale(), + mouseY * this.drawer.getYScale() + ) + ) { return object; } } @@ -141,4 +153,3 @@ export class CanvasMouseHandler { return undefined; } } - diff --git a/tools/winscope-ng/src/app/components/canvas/draggable_canvas_object.ts b/tools/winscope-ng/src/app/components/canvas/draggable_canvas_object.ts index a6dba37a6..bf154ba41 100644 --- a/tools/winscope-ng/src/app/components/canvas/draggable_canvas_object.ts +++ b/tools/winscope-ng/src/app/components/canvas/draggable_canvas_object.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import { MathUtils } from "three/src/Three"; -import { Segment } from "../timeline/utils"; -import { CanvasDrawer } from "./canvas_drawer"; +import {MathUtils} from 'three/src/Three'; +import {Segment} from '../timeline/utils'; +import {CanvasDrawer} from './canvas_drawer'; export type drawConfig = { - fillStyle: string, - fill: boolean -} + fillStyle: string; + fill: boolean; +}; export class DraggableCanvasObject { - private draggingPosition: number|undefined; + private draggingPosition: number | undefined; constructor( private drawer: CanvasDrawer, @@ -33,17 +33,21 @@ export class DraggableCanvasObject { private drawConfig: drawConfig, private onDrag: (x: number) => void, private onDrop: (x: number) => void, - private rangeGetter: () => Segment, + private rangeGetter: () => Segment ) { - this.drawer.handler.registerDraggableObject(this, (x: number, ) => { - this.draggingPosition = this.clampPositionToRange(x); - this.onDrag(this.draggingPosition); - this.drawer.draw(); - }, (x: number, ) => { - this.draggingPosition = undefined; - this.onDrop(this.clampPositionToRange(x)); - this.drawer.draw(); - }); + this.drawer.handler.registerDraggableObject( + this, + (x: number) => { + this.draggingPosition = this.clampPositionToRange(x); + this.onDrag(this.draggingPosition); + this.drawer.draw(); + }, + (x: number) => { + this.draggingPosition = undefined; + this.onDrop(this.clampPositionToRange(x)); + this.drawer.draw(); + } + ); } get range(): Segment { @@ -74,4 +78,4 @@ export class DraggableCanvasObject { private clampPositionToRange(x: number): number { return MathUtils.clamp(x, this.range.from, this.range.to); } -} \ No newline at end of file +} diff --git a/tools/winscope-ng/src/app/components/collect_traces.component.spec.ts b/tools/winscope-ng/src/app/components/collect_traces.component.spec.ts index a16ae9502..557a63f29 100644 --- a/tools/winscope-ng/src/app/components/collect_traces.component.spec.ts +++ b/tools/winscope-ng/src/app/components/collect_traces.component.spec.ts @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {CollectTracesComponent} from "./collect_traces.component"; -import { MatIconModule } from "@angular/material/icon"; -import { MatCardModule } from "@angular/material/card"; -import { AdbProxyComponent } from "./adb_proxy.component"; -import { WebAdbComponent } from "./web_adb.component"; -import { TraceConfigComponent } from "./trace_config.component"; -import { MatListModule } from "@angular/material/list"; -import { MatButtonModule } from "@angular/material/button"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatProgressBarModule } from "@angular/material/progress-bar"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; -import { MatSnackBar, MatSnackBarModule } from "@angular/material/snack-bar"; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatButtonModule} from '@angular/material/button'; +import {MatCardModule} from '@angular/material/card'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatIconModule} from '@angular/material/icon'; +import {MatListModule} from '@angular/material/list'; +import {MatProgressBarModule} from '@angular/material/progress-bar'; +import {MatSnackBar, MatSnackBarModule} from '@angular/material/snack-bar'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {AdbProxyComponent} from './adb_proxy.component'; +import {CollectTracesComponent} from './collect_traces.component'; +import {TraceConfigComponent} from './trace_config.component'; +import {WebAdbComponent} from './web_adb.component'; -describe("CollectTracesComponent", () => { +describe('CollectTracesComponent', () => { let fixture: ComponentFixture; let component: CollectTracesComponent; let htmlElement: HTMLElement; @@ -43,7 +43,7 @@ describe("CollectTracesComponent", () => { MatDividerModule, MatProgressBarModule, BrowserAnimationsModule, - MatSnackBarModule + MatSnackBarModule, ], providers: [MatSnackBar], declarations: [ @@ -52,7 +52,7 @@ describe("CollectTracesComponent", () => { WebAdbComponent, TraceConfigComponent, ], - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(CollectTracesComponent); component = fixture.componentInstance; @@ -60,137 +60,141 @@ describe("CollectTracesComponent", () => { component.isAdbProxy = true; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("renders the expected card title", () => { + it('renders the expected card title', () => { fixture.detectChanges(); - expect(htmlElement.querySelector(".title")?.innerHTML).toContain("Collect Traces"); + expect(htmlElement.querySelector('.title')?.innerHTML).toContain('Collect Traces'); }); - it("displays connecting message", () => { + it('displays connecting message', () => { component.connect.isConnectingState = jasmine.createSpy().and.returnValue(true); fixture.detectChanges(); - expect(htmlElement.querySelector(".connecting-message")?.innerHTML).toContain("Connecting..."); + expect(htmlElement.querySelector('.connecting-message')?.innerHTML).toContain('Connecting...'); }); - it("displays adb set up", async () => { + it('displays adb set up', async () => { component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false); fixture.detectChanges(); - fixture.whenStable().then( () => { - expect(htmlElement.querySelector(".set-up-adb")).toBeTruthy(); - const proxyTab: HTMLButtonElement | null = htmlElement.querySelector(".proxy-tab"); + fixture.whenStable().then(() => { + expect(htmlElement.querySelector('.set-up-adb')).toBeTruthy(); + const proxyTab: HTMLButtonElement | null = htmlElement.querySelector('.proxy-tab'); expect(proxyTab).toBeInstanceOf(HTMLButtonElement); - const webTab: HTMLButtonElement | null = htmlElement.querySelector(".web-tab"); + const webTab: HTMLButtonElement | null = htmlElement.querySelector('.web-tab'); expect(webTab).toBeInstanceOf(HTMLButtonElement); }); }); - it("displays adb proxy element", async () => { - component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false); - component.isAdbProxy = true; - fixture.detectChanges(); - fixture.whenStable().then( () => { - expect(htmlElement.querySelector("adb-proxy")).toBeTruthy(); - expect(htmlElement.querySelector("web-adb")).toBeFalsy(); - }); - }); - - it("displays web adb element", async () => { - component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false); - component.isAdbProxy = false; - fixture.detectChanges(); - fixture.whenStable().then( () => { - expect(htmlElement.querySelector("adb-proxy")).toBeFalsy(); - expect(htmlElement.querySelector("web-adb")).toBeTruthy(); - }); - }); - - it("changes to adb workflow tab", async () => { + it('displays adb proxy element', async () => { component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false); component.isAdbProxy = true; fixture.detectChanges(); fixture.whenStable().then(() => { - const webTab: HTMLButtonElement | null = htmlElement.querySelector(".web-tab"); + expect(htmlElement.querySelector('adb-proxy')).toBeTruthy(); + expect(htmlElement.querySelector('web-adb')).toBeFalsy(); + }); + }); + + it('displays web adb element', async () => { + component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false); + component.isAdbProxy = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(htmlElement.querySelector('adb-proxy')).toBeFalsy(); + expect(htmlElement.querySelector('web-adb')).toBeTruthy(); + }); + }); + + it('changes to adb workflow tab', async () => { + component.connect.adbSuccess = jasmine.createSpy().and.returnValue(false); + component.isAdbProxy = true; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const webTab: HTMLButtonElement | null = htmlElement.querySelector('.web-tab'); expect(webTab).toBeInstanceOf(HTMLButtonElement); - webTab?.dispatchEvent(new Event("click")); + webTab?.dispatchEvent(new Event('click')); fixture.whenStable().then(() => { expect(component.displayWebAdbTab).toHaveBeenCalled(); }); }); }); - it("displays no connected devices", async () => { + it('displays no connected devices', async () => { component.connect.isDevicesState = jasmine.createSpy().and.returnValue(true); component.connect.devices = jasmine.createSpy().and.returnValue({}); fixture.detectChanges(); - fixture.whenStable().then( () => { - const el = htmlElement.querySelector(".devices-connecting"); + fixture.whenStable().then(() => { + const el = htmlElement.querySelector('.devices-connecting'); expect(el).toBeTruthy(); - expect(el?.innerHTML).toContain("No devices detected"); + expect(el?.innerHTML).toContain('No devices detected'); }); }); - it("displays connected authorised devices", async () => { + it('displays connected authorised devices', async () => { component.connect.isDevicesState = jasmine.createSpy().and.returnValue(true); - component.connect.devices = jasmine.createSpy().and.returnValue({"35562": {model: "Pixel 6", authorised:true}}); + component.connect.devices = jasmine + .createSpy() + .and.returnValue({'35562': {model: 'Pixel 6', authorised: true}}); fixture.detectChanges(); - fixture.whenStable().then( () => { - const el = htmlElement.querySelector(".devices-connecting"); + fixture.whenStable().then(() => { + const el = htmlElement.querySelector('.devices-connecting'); expect(el).toBeTruthy(); - expect(el?.innerHTML).toContain("Connected devices:"); - expect(el?.innerHTML).toContain("Pixel 6"); - expect(el?.innerHTML).toContain("smartphone"); + expect(el?.innerHTML).toContain('Connected devices:'); + expect(el?.innerHTML).toContain('Pixel 6'); + expect(el?.innerHTML).toContain('smartphone'); }); }); - it("displays connected unauthorised devices", async () => { + it('displays connected unauthorised devices', async () => { component.connect.isDevicesState = jasmine.createSpy().and.returnValue(true); - component.connect.devices = jasmine.createSpy().and.returnValue({"35562": {model: "Pixel 6", authorised:false}}); + component.connect.devices = jasmine + .createSpy() + .and.returnValue({'35562': {model: 'Pixel 6', authorised: false}}); fixture.detectChanges(); - fixture.whenStable().then( () => { - const el = htmlElement.querySelector(".devices-connecting"); + fixture.whenStable().then(() => { + const el = htmlElement.querySelector('.devices-connecting'); expect(el).toBeTruthy(); - expect(el?.innerHTML).toContain("Connected devices:"); - expect(el?.innerHTML).toContain("unauthorised"); - expect(el?.innerHTML).toContain("screen_lock_portrait"); + expect(el?.innerHTML).toContain('Connected devices:'); + expect(el?.innerHTML).toContain('unauthorised'); + expect(el?.innerHTML).toContain('screen_lock_portrait'); }); }); - it("displays trace collection config elements", async () => { + it('displays trace collection config elements', async () => { component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true); - const mock = {model: "Pixel 6", authorised:true}; - component.connect.devices = jasmine.createSpy().and.returnValue({"35562": mock}); + const mock = {model: 'Pixel 6', authorised: true}; + component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock}); component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock); fixture.detectChanges(); - fixture.whenStable().then( () => { - const el = htmlElement.querySelector(".trace-collection-config"); + fixture.whenStable().then(() => { + const el = htmlElement.querySelector('.trace-collection-config'); expect(el).toBeTruthy(); - expect(el?.innerHTML).toContain("smartphone"); - expect(el?.innerHTML).toContain("Pixel 6"); - expect(el?.innerHTML).toContain("35562"); + expect(el?.innerHTML).toContain('smartphone'); + expect(el?.innerHTML).toContain('Pixel 6'); + expect(el?.innerHTML).toContain('35562'); - const traceSection = htmlElement.querySelector(".trace-section"); + const traceSection = htmlElement.querySelector('.trace-section'); expect(traceSection).toBeTruthy(); - const dumpSection = htmlElement.querySelector(".dump-section"); + const dumpSection = htmlElement.querySelector('.dump-section'); expect(dumpSection).toBeTruthy(); }); }); - it("start trace button works as expected", async () => { + it('start trace button works as expected', async () => { component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true); - const mock = {model: "Pixel 6", authorised:true}; - component.connect.devices = jasmine.createSpy().and.returnValue({"35562": mock}); + const mock = {model: 'Pixel 6', authorised: true}; + component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock}); component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock); fixture.detectChanges(); - fixture.whenStable().then( () => { - const start: HTMLButtonElement | null = htmlElement.querySelector(".start-btn"); + fixture.whenStable().then(() => { + const start: HTMLButtonElement | null = htmlElement.querySelector('.start-btn'); expect(start).toBeInstanceOf(HTMLButtonElement); - start?.dispatchEvent(new Event("click")); + start?.dispatchEvent(new Event('click')); fixture.whenStable().then(() => { expect(component.startTracing).toHaveBeenCalled(); expect(component.connect.startTrace).toHaveBeenCalled(); @@ -198,17 +202,17 @@ describe("CollectTracesComponent", () => { }); }); - it("dump state button works as expected", async () => { + it('dump state button works as expected', async () => { component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true); - const mock = {model: "Pixel 6", authorised:true}; - component.connect.devices = jasmine.createSpy().and.returnValue({"35562": mock}); + const mock = {model: 'Pixel 6', authorised: true}; + component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock}); component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock); fixture.detectChanges(); - fixture.whenStable().then( () => { - const dump: HTMLButtonElement | null = htmlElement.querySelector(".dump-btn"); + fixture.whenStable().then(() => { + const dump: HTMLButtonElement | null = htmlElement.querySelector('.dump-btn'); expect(dump).toBeInstanceOf(HTMLButtonElement); - dump?.dispatchEvent(new Event("click")); + dump?.dispatchEvent(new Event('click')); fixture.whenStable().then(() => { expect(component.dumpState).toHaveBeenCalled(); expect(component.connect.dumpState).toHaveBeenCalled(); @@ -216,51 +220,51 @@ describe("CollectTracesComponent", () => { }); }); - it("change device button works as expected", async () => { + it('change device button works as expected', async () => { component.connect.isStartTraceState = jasmine.createSpy().and.returnValue(true); - const mock = {model: "Pixel 6", authorised:true}; - component.connect.devices = jasmine.createSpy().and.returnValue({"35562": mock}); + const mock = {model: 'Pixel 6', authorised: true}; + component.connect.devices = jasmine.createSpy().and.returnValue({'35562': mock}); component.connect.selectedDevice = jasmine.createSpy().and.returnValue(mock); fixture.detectChanges(); - fixture.whenStable().then( () => { - const change: HTMLButtonElement | null = htmlElement.querySelector(".change-btn"); + fixture.whenStable().then(() => { + const change: HTMLButtonElement | null = htmlElement.querySelector('.change-btn'); expect(change).toBeInstanceOf(HTMLButtonElement); - change?.dispatchEvent(new Event("click")); + change?.dispatchEvent(new Event('click')); fixture.whenStable().then(() => { expect(component.connect.resetLastDevice).toHaveBeenCalled(); }); }); }); - it("displays unknown error message", () => { + it('displays unknown error message', () => { component.connect.isErrorState = jasmine.createSpy().and.returnValue(true); - component.connect.proxy!.errorText = "bad things are happening"; + component.connect.proxy!.errorText = 'bad things are happening'; fixture.detectChanges(); - fixture.whenStable().then( () => { - const el = htmlElement.querySelector(".unknown-error"); - expect(el?.innerHTML).toContain("Error:"); - expect(el?.innerHTML).toContain("bad things are happening"); - const retry: HTMLButtonElement | null = htmlElement.querySelector(".retry-btn"); + fixture.whenStable().then(() => { + const el = htmlElement.querySelector('.unknown-error'); + expect(el?.innerHTML).toContain('Error:'); + expect(el?.innerHTML).toContain('bad things are happening'); + const retry: HTMLButtonElement | null = htmlElement.querySelector('.retry-btn'); expect(retry).toBeInstanceOf(HTMLButtonElement); - retry?.dispatchEvent(new Event("click")); + retry?.dispatchEvent(new Event('click')); fixture.whenStable().then(() => { expect(component.connect.restart).toHaveBeenCalled(); }); }); }); - it("displays end tracing elements", () => { + it('displays end tracing elements', () => { component.connect.isEndTraceState = jasmine.createSpy().and.returnValue(true); fixture.detectChanges(); - fixture.whenStable().then( () => { - const el = htmlElement.querySelector(".end-tracing"); - expect(el?.innerHTML).toContain("Tracing..."); - expect(htmlElement.querySelector("mat-progress-bar")).toBeTruthy(); + fixture.whenStable().then(() => { + const el = htmlElement.querySelector('.end-tracing'); + expect(el?.innerHTML).toContain('Tracing...'); + expect(htmlElement.querySelector('mat-progress-bar')).toBeTruthy(); - const end: HTMLButtonElement | null = htmlElement.querySelector(".end"); + const end: HTMLButtonElement | null = htmlElement.querySelector('.end'); expect(end).toBeInstanceOf(HTMLButtonElement); - end?.dispatchEvent(new Event("click")); + end?.dispatchEvent(new Event('click')); fixture.whenStable().then(() => { expect(component.endTrace).toHaveBeenCalled(); expect(component.connect.endTrace).toHaveBeenCalled(); @@ -268,12 +272,12 @@ describe("CollectTracesComponent", () => { }); }); - it("displays loading data elements", () => { + it('displays loading data elements', () => { component.connect.isLoadDataState = jasmine.createSpy().and.returnValue(true); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(htmlElement.querySelector(".load-data")?.innerHTML).toContain("Loading data..."); - expect(htmlElement.querySelector("mat-progress-bar")).toBeTruthy(); + expect(htmlElement.querySelector('.load-data')?.innerHTML).toContain('Loading data...'); + expect(htmlElement.querySelector('mat-progress-bar')).toBeTruthy(); }); }); }); diff --git a/tools/winscope-ng/src/app/components/collect_traces.component.ts b/tools/winscope-ng/src/app/components/collect_traces.component.ts index d27823ef0..7501c8702 100644 --- a/tools/winscope-ng/src/app/components/collect_traces.component.ts +++ b/tools/winscope-ng/src/app/components/collect_traces.component.ts @@ -18,38 +18,55 @@ import { ChangeDetectorRef, Component, EventEmitter, - Input, Inject, - Output, - OnInit, - OnDestroy, + Input, NgZone, - ViewEncapsulation -} from "@angular/core"; -import { TraceFile} from "common/trace/trace"; -import { TraceData} from "app/trace_data"; -import { ProxyConnection } from "trace_collection/proxy_connection"; -import { Connection } from "trace_collection/connection"; -import { ProxyState } from "trace_collection/proxy_client"; -import { traceConfigurations, configMap, SelectionConfiguration, EnableConfiguration } from "trace_collection/trace_collection_utils"; -import { PersistentStore } from "common/utils/persistent_store"; -import { MatSnackBar } from "@angular/material/snack-bar"; -import { ParserErrorSnackBarComponent } from "./parser_error_snack_bar_component"; -import { TracingConfig } from "trace_collection/tracing_config"; + OnDestroy, + OnInit, + Output, + ViewEncapsulation, +} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {TraceData} from 'app/trace_data'; +import {TraceFile} from 'common/trace/trace'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {Connection} from 'trace_collection/connection'; +import {ProxyState} from 'trace_collection/proxy_client'; +import {ProxyConnection} from 'trace_collection/proxy_connection'; +import { + configMap, + EnableConfiguration, + SelectionConfiguration, + traceConfigurations, +} from 'trace_collection/trace_collection_utils'; +import {TracingConfig} from 'trace_collection/tracing_config'; +import {ParserErrorSnackBarComponent} from './parser_error_snack_bar_component'; @Component({ - selector: "collect-traces", + selector: 'collect-traces', template: ` Collect Traces -

Connecting...

+

+ Connecting... +

- + - +
@@ -64,41 +81,66 @@ import { TracingConfig } from "trace_collection/tracing_config"; + class="available-device"> - {{ connect.devices()[deviceId].authorised ? "smartphone" : "screen_lock_portrait" }} + {{ + connect.devices()[deviceId].authorised ? 'smartphone' : 'screen_lock_portrait' + }}

- {{ connect.devices()[deviceId].authorised ? connect.devices()[deviceId]?.model : "unauthorised" }} ({{ deviceId }}) + {{ + connect.devices()[deviceId].authorised + ? connect.devices()[deviceId]?.model + : 'unauthorised' + }} + ({{ deviceId }})

-
+
smartphone

{{ connect.selectedDevice()?.model }} ({{ connect.selectedDeviceId() }}) - +

- +
-
+
- +
-
+

Loading tracing config...

@@ -109,7 +151,9 @@ import { TracingConfig } from "trace_collection/tracing_config";

Tracing...

- +
@@ -117,14 +161,20 @@ import { TracingConfig } from "trace_collection/tracing_config";
- +
- +
-
+

Dump targets

{{tracingConfig.getDumpConfig()[dumpKey].name}} + >{{ tracingConfig.getDumpConfig()[dumpKey].name }}
- +
@@ -143,9 +196,10 @@ import { TracingConfig } from "trace_collection/tracing_config";

Loading dumping config...

- +
@@ -158,15 +212,17 @@ import { TracingConfig } from "trace_collection/tracing_config"; Error:

 {{ connect.proxy?.errorText }} 
- +
-
`, styles: [ ` - .change-btn, .retry-btn { + .change-btn, + .retry-btn { margin-left: 5px; } .mat-card.collect-card { @@ -198,16 +254,25 @@ import { TracingConfig } from "trace_collection/tracing_config"; flex-direction: column; gap: 10px; } - .trace-section, .dump-section, .end-tracing, .load-data { + .trace-section, + .dump-section, + .end-tracing, + .load-data { height: 100%; } .trace-collection-config { height: 100%; } - .proxy-tab, .web-tab, .start-btn, .dump-btn, .end-btn { + .proxy-tab, + .web-tab, + .start-btn, + .dump-btn, + .end-btn { align-self: flex-start; } - .start-btn, .dump-btn, .end-btn { + .start-btn, + .dump-btn, + .end-btn { margin: auto 0 0 0; padding: 1rem 0 0 0; } @@ -232,7 +297,8 @@ import { TracingConfig } from "trace_collection/tracing_config"; height: 100%; } - .no-device-detected p, .device-selection p.instruction { + .no-device-detected p, + .device-selection p.instruction { padding-top: 1rem; opacity: 0.6; font-size: 1.2rem; @@ -272,7 +338,8 @@ import { TracingConfig } from "trace_collection/tracing_config"; height: 100%; } - .load-data p, .end-tracing p { + .load-data p, + .end-tracing p { opacity: 0.7; } @@ -292,9 +359,9 @@ import { TracingConfig } from "trace_collection/tracing_config"; load-progress { height: 100%; } - ` + `, ], - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, }) export class CollectTracesComponent implements OnInit, OnDestroy { objectKeys = Object.keys; @@ -364,24 +431,20 @@ export class CollectTracesComponent implements OnInit, OnDestroy { } public startTracing() { - console.log("begin tracing"); + console.log('begin tracing'); this.tracingConfig.requestedTraces = this.requestedTraces(); const reqEnableConfig = this.requestedEnableConfig(); - const reqSelectedSfConfig = this.requestedSelection("layers_trace"); - const reqSelectedWmConfig = this.requestedSelection("window_trace"); + const reqSelectedSfConfig = this.requestedSelection('layers_trace'); + const reqSelectedWmConfig = this.requestedSelection('window_trace'); if (this.tracingConfig.requestedTraces.length < 1) { this.connect.throwNoTargetsError(); return; } - this.connect.startTrace( - reqEnableConfig, - reqSelectedSfConfig, - reqSelectedWmConfig - ); + this.connect.startTrace(reqEnableConfig, reqSelectedSfConfig, reqSelectedWmConfig); } public async dumpState() { - console.log("begin dump"); + console.log('begin dump'); this.tracingConfig.requestedDumps = this.requestedDumps(); const dumpSuccessful = await this.connect.dumpState(); if (dumpSuccessful) { @@ -392,7 +455,7 @@ export class CollectTracesComponent implements OnInit, OnDestroy { } public async endTrace() { - console.log("end tracing"); + console.log('end tracing'); await this.connect.endTrace(); await this.loadFiles(); } @@ -400,11 +463,11 @@ export class CollectTracesComponent implements OnInit, OnDestroy { public tabClass(adbTab: boolean) { let isActive: string; if (adbTab) { - isActive = this.isAdbProxy ? "active" : "inactive"; + isActive = this.isAdbProxy ? 'active' : 'inactive'; } else { - isActive = !this.isAdbProxy ? "active" : "inactive"; + isActive = !this.isAdbProxy ? 'active' : 'inactive'; } - return ["tab", isActive]; + return ['tab', isActive]; } private onProxyChange(newState: ProxyState) { @@ -414,47 +477,41 @@ export class CollectTracesComponent implements OnInit, OnDestroy { private requestedTraces() { const tracesFromCollection: Array = []; const tracingConfig = this.tracingConfig.getTracingConfig(); - const req = Object.keys(tracingConfig) - .filter((traceKey:string) => { - const traceConfig = tracingConfig[traceKey]; - if (traceConfig.isTraceCollection) { - traceConfig.config?.enableConfigs.forEach((innerTrace:EnableConfiguration) => { - if (innerTrace.enabled) { - tracesFromCollection.push(innerTrace.key); - } - }); - return false; - } - return traceConfig.run; - }); + const req = Object.keys(tracingConfig).filter((traceKey: string) => { + const traceConfig = tracingConfig[traceKey]; + if (traceConfig.isTraceCollection) { + traceConfig.config?.enableConfigs.forEach((innerTrace: EnableConfiguration) => { + if (innerTrace.enabled) { + tracesFromCollection.push(innerTrace.key); + } + }); + return false; + } + return traceConfig.run; + }); return req.concat(tracesFromCollection); } private requestedDumps() { const dumpConfig = this.tracingConfig.getDumpConfig(); - return Object.keys(dumpConfig) - .filter((dumpKey:string) => { - return dumpConfig[dumpKey].run; - }); + return Object.keys(dumpConfig).filter((dumpKey: string) => { + return dumpConfig[dumpKey].run; + }); } private requestedEnableConfig(): Array { const req: Array = []; const tracingConfig = this.tracingConfig.getTracingConfig(); - Object.keys(tracingConfig) - .forEach((traceKey:string) => { - const trace = tracingConfig[traceKey]; - if(!trace.isTraceCollection - && trace.run - && trace.config - && trace.config.enableConfigs) { - trace.config.enableConfigs.forEach((con:EnableConfiguration) => { - if (con.enabled) { - req.push(con.key); - } - }); - } - }); + Object.keys(tracingConfig).forEach((traceKey: string) => { + const trace = tracingConfig[traceKey]; + if (!trace.isTraceCollection && trace.run && trace.config && trace.config.enableConfigs) { + trace.config.enableConfigs.forEach((con: EnableConfiguration) => { + if (con.enabled) { + req.push(con.key); + } + }); + } + }); return req; } @@ -464,22 +521,20 @@ export class CollectTracesComponent implements OnInit, OnDestroy { return undefined; } const selected: configMap = {}; - tracingConfig[traceType].config?.selectionConfigs.forEach( - (con: SelectionConfiguration) => { - selected[con.key] = con.value; - } - ); + tracingConfig[traceType].config?.selectionConfigs.forEach((con: SelectionConfiguration) => { + selected[con.key] = con.value; + }); return selected; } private async loadFiles() { - console.log("loading files", this.connect.adbData()); + console.log('loading files', this.connect.adbData()); this.traceData.clear(); - const traceFiles = this.connect.adbData().map(file => new TraceFile(file)); + const traceFiles = this.connect.adbData().map((file) => new TraceFile(file)); const parserErrors = await this.traceData.loadTraces(traceFiles); ParserErrorSnackBarComponent.showIfNeeded(this.ngZone, this.snackBar, parserErrors); this.traceDataLoaded.emit(); - console.log("finished loading data!"); + console.log('finished loading data!'); } private onLoadProgressUpdate(progress: number) { diff --git a/tools/winscope-ng/src/app/components/load_progress.component.ts b/tools/winscope-ng/src/app/components/load_progress.component.ts index befc787d9..787933c47 100644 --- a/tools/winscope-ng/src/app/components/load_progress.component.ts +++ b/tools/winscope-ng/src/app/components/load_progress.component.ts @@ -14,26 +14,25 @@ * limitations under the License. */ -import {Component, Input} from "@angular/core"; +import {Component, Input} from '@angular/core'; @Component({ - selector: "load-progress", + selector: 'load-progress', template: `

- - +

- + - + -

{{message}}

+

{{ message }}

`, styles: [ @@ -60,10 +59,10 @@ import {Component, Input} from "@angular/core"; mat-card-content { flex-grow: 1; } - ` - ] + `, + ], }) export class LoadProgressComponent { @Input() progressPercentage?: number; - @Input() message = "Loading..."; + @Input() message = 'Loading...'; } diff --git a/tools/winscope-ng/src/app/components/parser_error_snack_bar_component.ts b/tools/winscope-ng/src/app/components/parser_error_snack_bar_component.ts index 7b3f1b606..7c83a2c11 100644 --- a/tools/winscope-ng/src/app/components/parser_error_snack_bar_component.ts +++ b/tools/winscope-ng/src/app/components/parser_error_snack_bar_component.ts @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Component, Inject, NgZone} from "@angular/core"; -import {MAT_SNACK_BAR_DATA, MatSnackBar, MatSnackBarRef} from "@angular/material/snack-bar"; -import {ParserError, ParserErrorType} from "parsers/parser_factory"; -import {TRACE_INFO} from "app/trace_info"; +import {Component, Inject, NgZone} from '@angular/core'; +import {MatSnackBar, MatSnackBarRef, MAT_SNACK_BAR_DATA} from '@angular/material/snack-bar'; +import {TRACE_INFO} from 'app/trace_info'; +import {ParserError, ParserErrorType} from 'parsers/parser_factory'; @Component({ - selector: "upload-snack-bar", + selector: 'upload-snack-bar', template: `

- {{message}} + {{ message }}

-
- - - - - - - - - -
- + +
+ + + + + + + + + +
+
- - -
- Select up to 2 additional traces to display. -
- - {{ TRACE_INFO[trace].icon }} - {{ TRACE_INFO[trace].name }} - -
- - -
- - - {{ TRACE_INFO[selectedTrace].icon }} - - -
-
+ + +
Select up to 2 additional traces to display.
+ + {{ TRACE_INFO[trace].icon }} + {{ TRACE_INFO[trace].name }} + +
+ + +
+ + + {{ TRACE_INFO[selectedTrace].icon }} + + +
+
+ #miniTimeline>
- +
-
+

No timeline to show!

All loaded traces contain no timestamps!

-
+

No timeline to show!

Only a single timestamp has been recorded.

-`, - styles: [` - .navbar { - display: flex; - width: 100%; - flex-direction: row; - align-items: center; - justify-content: center; - } - #expanded-nav { - display: flex; - border-bottom: 1px solid #3333 - } - #time-selector { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - } - .time-selector-form { - display: flex; - flex-direction: column; - width: 15em; - } - .time-selector-form .time-input { - width: 100%; - margin-bottom: -1.34375em; - text-align: center; - } - #mini-timeline { - flex-grow: 1; - align-self: stretch; - } - #video-content { - position: relative; - min-width: 20rem; - min-height: 35rem; - align-self: stretch; - text-align: center; - border: 2px solid black; - flex-basis: 0px; - flex-grow: 1; - display: flex; - align-items: center; - } - #video { - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 100%; - } - #expanded-nav { - display: flex; - flex-direction: row; - } - #expanded-timeline { - flex-grow: 1; - } - #trace-selector .mat-form-field-infix { - width: 50px; - padding: 0 0.75rem 0 0.5rem; - border-top: unset; - } - #trace-selector .mat-icon { - padding: 2px; - } - #trace-selector .shown-selection { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: auto; - } - #trace-selector .mat-select-trigger { - height: unset; - } - #trace-selector .mat-form-field-wrapper { - padding: 0; - } - .mat-select-panel { - max-height: unset!important; - font-family: 'Roboto', sans-serif; - } - .tip { - padding: 1.5rem; - font-weight: 200; - border-bottom: solid 1px #DADCE0; - } - .actions { - border-top: solid 1px #DADCE0; - width: 100%; - padding: 1.5rem; - float: right; - display: flex; - justify-content: flex-end; - } - .no-video-message { - padding: 1rem; - font-family: 'Roboto', sans-serif; - } - .no-timestamps-msg { - padding: 1rem; - align-items: center; - display: flex; - flex-direction: column; - } - `], + `, + styles: [ + ` + .navbar { + display: flex; + width: 100%; + flex-direction: row; + align-items: center; + justify-content: center; + } + #expanded-nav { + display: flex; + border-bottom: 1px solid #3333; + } + #time-selector { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + } + .time-selector-form { + display: flex; + flex-direction: column; + width: 15em; + } + .time-selector-form .time-input { + width: 100%; + margin-bottom: -1.34375em; + text-align: center; + } + #mini-timeline { + flex-grow: 1; + align-self: stretch; + } + #video-content { + position: relative; + min-width: 20rem; + min-height: 35rem; + align-self: stretch; + text-align: center; + border: 2px solid black; + flex-basis: 0px; + flex-grow: 1; + display: flex; + align-items: center; + } + #video { + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + } + #expanded-nav { + display: flex; + flex-direction: row; + } + #expanded-timeline { + flex-grow: 1; + } + #trace-selector .mat-form-field-infix { + width: 50px; + padding: 0 0.75rem 0 0.5rem; + border-top: unset; + } + #trace-selector .mat-icon { + padding: 2px; + } + #trace-selector .shown-selection { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: auto; + } + #trace-selector .mat-select-trigger { + height: unset; + } + #trace-selector .mat-form-field-wrapper { + padding: 0; + } + .mat-select-panel { + max-height: unset !important; + font-family: 'Roboto', sans-serif; + } + .tip { + padding: 1.5rem; + font-weight: 200; + border-bottom: solid 1px #dadce0; + } + .actions { + border-top: solid 1px #dadce0; + width: 100%; + padding: 1.5rem; + float: right; + display: flex; + justify-content: flex-end; + } + .no-video-message { + padding: 1rem; + font-family: 'Roboto', sans-serif; + } + .no-timestamps-msg { + padding: 1rem; + align-items: center; + display: flex; + flex-direction: column; + } + `, + ], }) export class TimelineComponent implements TimestampChangeListener { - public readonly TOGGLE_BUTTON_CLASS: string = "button-toggle-expansion"; + public readonly TOGGLE_BUTTON_CLASS: string = 'button-toggle-expansion'; public readonly MAX_SELECTED_TRACES = 3; - @Input() set activeViewTraceTypes(types: TraceType[]|undefined) { + @Input() set activeViewTraceTypes(types: TraceType[] | undefined) { if (!types) { return; } @@ -297,35 +312,44 @@ export class TimelineComponent implements TimestampChangeListener { this.selectedTracesFormControl.setValue(this.selectedTraces); } - public internalActiveTrace: TraceType|undefined = undefined; + public internalActiveTrace: TraceType | undefined = undefined; @Input() timelineData!: TimelineData; @Input() availableTraces: TraceType[] = []; @Output() collapsedTimelineSizeChanged = new EventEmitter(); - @ViewChild("miniTimeline") private miniTimelineComponent!: MiniTimelineComponent; - @ViewChild("collapsedTimeline") private collapsedTimelineRef!: ElementRef; + @ViewChild('miniTimeline') private miniTimelineComponent!: MiniTimelineComponent; + @ViewChild('collapsedTimeline') private collapsedTimelineRef!: ElementRef; selectedTraces: TraceType[] = []; selectedTracesFormControl = new FormControl(); - selectedElapsedTimeFormControl = new FormControl("undefined", Validators.compose([ - Validators.required, - Validators.pattern(TimeUtils.HUMAN_ELAPSED_TIMESTAMP_REGEX)])); - selectedRealTimeFormControl = new FormControl("undefined", Validators.compose([ - Validators.required, - Validators.pattern(TimeUtils.HUMAN_REAL_TIMESTAMP_REGEX)])); - selectedNsFormControl = new FormControl("undefined", Validators.compose([ - Validators.required, - Validators.pattern(TimeUtils.NS_TIMESTAMP_REGEX)])); + selectedElapsedTimeFormControl = new FormControl( + 'undefined', + Validators.compose([ + Validators.required, + Validators.pattern(TimeUtils.HUMAN_ELAPSED_TIMESTAMP_REGEX), + ]) + ); + selectedRealTimeFormControl = new FormControl( + 'undefined', + Validators.compose([ + Validators.required, + Validators.pattern(TimeUtils.HUMAN_REAL_TIMESTAMP_REGEX), + ]) + ); + selectedNsFormControl = new FormControl( + 'undefined', + Validators.compose([Validators.required, Validators.pattern(TimeUtils.NS_TIMESTAMP_REGEX)]) + ); timestampForm = new FormGroup({ selectedElapsedTime: this.selectedElapsedTimeFormControl, selectedRealTime: this.selectedRealTimeFormControl, selectedNs: this.selectedNsFormControl, }); - videoUrl: SafeUrl|undefined; + videoUrl: SafeUrl | undefined; private expanded = false; @@ -333,8 +357,8 @@ export class TimelineComponent implements TimestampChangeListener { constructor( @Inject(DomSanitizer) private sanitizer: DomSanitizer, - @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef) { - } + @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef + ) {} ngOnInit() { if (this.timelineData.hasTimestamps()) { @@ -343,8 +367,9 @@ export class TimelineComponent implements TimestampChangeListener { const screenRecordingVideo = this.timelineData.getScreenRecordingVideo(); if (screenRecordingVideo) { - this.videoUrl = - this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(screenRecordingVideo)); + this.videoUrl = this.sanitizer.bypassSecurityTrustUrl( + URL.createObjectURL(screenRecordingVideo) + ); } } @@ -357,7 +382,7 @@ export class TimelineComponent implements TimestampChangeListener { return this.timelineData.searchCorrespondingScreenRecordingTimeSeconds(this.currentTimestamp); } - private seekTimestamp: Timestamp|undefined; + private seekTimestamp: Timestamp | undefined; get currentTimestamp(): Timestamp { if (this.seekTimestamp !== undefined) { @@ -366,13 +391,13 @@ export class TimelineComponent implements TimestampChangeListener { const timestamp = this.timelineData.getCurrentTimestamp(); if (timestamp === undefined) { - throw Error("A timestamp should have been set by the time the timeline is loaded"); + throw Error('A timestamp should have been set by the time the timeline is loaded'); } return timestamp; } - onCurrentTimestampChanged(timestamp: Timestamp|undefined): void { + onCurrentTimestampChanged(timestamp: Timestamp | undefined): void { if (!timestamp) { return; } @@ -392,14 +417,18 @@ export class TimelineComponent implements TimestampChangeListener { return this.timelineData.getTimestampType() === TimestampType.REAL; } - updateSeekTimestamp(timestamp: Timestamp|undefined) { + updateSeekTimestamp(timestamp: Timestamp | undefined) { this.seekTimestamp = timestamp; this.updateTimeInputValuesToCurrentTimestamp(); } private updateTimeInputValuesToCurrentTimestamp() { - this.selectedElapsedTimeFormControl.setValue(TimeUtils.format(new ElapsedTimestamp(this.currentTimestamp.getValueNs()), false)); - this.selectedRealTimeFormControl.setValue(TimeUtils.format(new RealTimestamp(this.currentTimestamp.getValueNs()))); + this.selectedElapsedTimeFormControl.setValue( + TimeUtils.format(new ElapsedTimestamp(this.currentTimestamp.getValueNs()), false) + ); + this.selectedRealTimeFormControl.setValue( + TimeUtils.format(new RealTimestamp(this.currentTimestamp.getValueNs())) + ); this.selectedNsFormControl.setValue(`${this.currentTimestamp.getValueNs()} ns`); } @@ -409,8 +438,10 @@ export class TimelineComponent implements TimestampChangeListener { } // Reached limit of options and is not a selected element - if ((this.selectedTracesFormControl.value?.length ?? 0) >= this.MAX_SELECTED_TRACES - && this.selectedTracesFormControl.value?.find((el: TraceType) => el === trace) === undefined) { + if ( + (this.selectedTracesFormControl.value?.length ?? 0) >= this.MAX_SELECTED_TRACES && + this.selectedTracesFormControl.value?.find((el: TraceType) => el === trace) === undefined + ) { return true; } @@ -425,14 +456,14 @@ export class TimelineComponent implements TimestampChangeListener { this.selectedTraces = this.selectedTracesFormControl.value; } - @HostListener("document:keydown", ["$event"]) + @HostListener('document:keydown', ['$event']) handleKeyboardEvent(event: KeyboardEvent) { switch (event.key) { - case "ArrowLeft": { + case 'ArrowLeft': { this.moveToPreviousEntry(); break; } - case "ArrowRight": { + case 'ArrowRight': { this.moveToNextEntry(); break; } @@ -440,16 +471,20 @@ export class TimelineComponent implements TimestampChangeListener { } hasPrevEntry(): boolean { - if (!this.internalActiveTrace || - (this.timelineData.getTimelines().get(this.internalActiveTrace)?.length ?? 0) === 0) { + if ( + !this.internalActiveTrace || + (this.timelineData.getTimelines().get(this.internalActiveTrace)?.length ?? 0) === 0 + ) { return false; } return this.timelineData.getPreviousTimestampFor(this.internalActiveTrace) !== undefined; } hasNextEntry(): boolean { - if (!this.internalActiveTrace || - (this.timelineData.getTimelines().get(this.internalActiveTrace)?.length ?? 0) === 0) { + if ( + !this.internalActiveTrace || + (this.timelineData.getTimelines().get(this.internalActiveTrace)?.length ?? 0) === 0 + ) { return false; } return this.timelineData.getNextTimestampFor(this.internalActiveTrace) !== undefined; @@ -470,7 +505,7 @@ export class TimelineComponent implements TimestampChangeListener { } humanElapsedTimeInputChange(event: Event) { - if (event.type !== "change") { + if (event.type !== 'change') { return; } const target = event.target as HTMLInputElement; @@ -480,7 +515,7 @@ export class TimelineComponent implements TimestampChangeListener { } humanRealTimeInputChanged(event: Event) { - if (event.type !== "change") { + if (event.type !== 'change') { return; } const target = event.target as HTMLInputElement; @@ -491,7 +526,7 @@ export class TimelineComponent implements TimestampChangeListener { } nanosecondsInputTimeChange(event: Event) { - if (event.type !== "change") { + if (event.type !== 'change') { return; } const target = event.target as HTMLInputElement; diff --git a/tools/winscope-ng/src/app/components/timeline/timeline_component_stub.ts b/tools/winscope-ng/src/app/components/timeline/timeline_component_stub.ts index a9b998da4..e68e47774 100644 --- a/tools/winscope-ng/src/app/components/timeline/timeline_component_stub.ts +++ b/tools/winscope-ng/src/app/components/timeline/timeline_component_stub.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import {Timestamp} from "common/trace/timestamp"; -import {TimestampChangeListener} from "interfaces/timestamp_change_listener"; +import {Timestamp} from 'common/trace/timestamp'; +import {TimestampChangeListener} from 'interfaces/timestamp_change_listener'; export class TimelineComponentStub implements TimestampChangeListener { - onCurrentTimestampChanged(timestamp: Timestamp|undefined) { + onCurrentTimestampChanged(timestamp: Timestamp | undefined) { // do nothing } } diff --git a/tools/winscope-ng/src/app/components/timeline/utils.ts b/tools/winscope-ng/src/app/components/timeline/utils.ts index 782f0c806..442efaed5 100644 --- a/tools/winscope-ng/src/app/components/timeline/utils.ts +++ b/tools/winscope-ng/src/app/components/timeline/utils.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { TraceType } from "common/trace/trace_type"; +import {TraceType} from 'common/trace/trace_type'; -export type Segment = { from: number, to: number } -export type BigIntSegment = { from: bigint, to: bigint } -export type TimelineData = Map +export type Segment = {from: number; to: number}; +export type BigIntSegment = {from: bigint; to: bigint}; +export type TimelineData = Map; diff --git a/tools/winscope-ng/src/app/components/trace_config.component.spec.ts b/tools/winscope-ng/src/app/components/trace_config.component.spec.ts index 1a99a0b43..ac4573e8d 100644 --- a/tools/winscope-ng/src/app/components/trace_config.component.spec.ts +++ b/tools/winscope-ng/src/app/components/trace_config.component.spec.ts @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CommonModule } from "@angular/common"; -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {TraceConfigComponent} from "./trace_config.component"; -import { MatCheckboxModule } from "@angular/material/checkbox"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { MatInputModule } from "@angular/material/input"; -import { MatSelectModule } from "@angular/material/select"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; +import {CommonModule} from '@angular/common'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatInputModule} from '@angular/material/input'; +import {MatSelectModule} from '@angular/material/select'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {TraceConfigComponent} from './trace_config.component'; -describe("TraceConfigComponent", () => { +describe('TraceConfigComponent', () => { let fixture: ComponentFixture; let component: TraceConfigComponent; let htmlElement: HTMLElement; @@ -38,97 +38,100 @@ describe("TraceConfigComponent", () => { MatFormFieldModule, MatInputModule, MatSelectModule, - BrowserAnimationsModule + BrowserAnimationsModule, ], declarations: [TraceConfigComponent], - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(TraceConfigComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; component.traces = { - "layers_trace": { - name: "layers_trace", + layers_trace: { + name: 'layers_trace', isTraceCollection: undefined, run: false, config: { - enableConfigs: [{ - name:"trace buffers", - key:"tracebuffers", - enabled:true - }], - selectionConfigs: [{ - key: "tracinglevel", - name: "tracing level", - options: [ - "verbose", - "debug", - "critical", - ], - value: "debug" - }] - }} + enableConfigs: [ + { + name: 'trace buffers', + key: 'tracebuffers', + enabled: true, + }, + ], + selectionConfigs: [ + { + key: 'tracinglevel', + name: 'tracing level', + options: ['verbose', 'debug', 'critical'], + value: 'debug', + }, + ], + }, + }, }; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("check that trace checkbox ticked on default run", () => { - component.traces["layers_trace"].run = true; + it('check that trace checkbox ticked on default run', () => { + component.traces['layers_trace'].run = true; fixture.detectChanges(); - const box = htmlElement.querySelector(".trace-checkbox"); - expect(box?.innerHTML).toContain("aria-checked=\"true\""); - expect(box?.innerHTML).toContain("layers_trace"); + const box = htmlElement.querySelector('.trace-checkbox'); + expect(box?.innerHTML).toContain('aria-checked="true"'); + expect(box?.innerHTML).toContain('layers_trace'); }); - it("check that trace checkbox not ticked on default run", () => { - component.traces["layers_trace"].run = false; + it('check that trace checkbox not ticked on default run', () => { + component.traces['layers_trace'].run = false; fixture.detectChanges(); - const box = htmlElement.querySelector(".trace-checkbox"); - expect(box?.innerHTML).toContain("aria-checked=\"false\""); + const box = htmlElement.querySelector('.trace-checkbox'); + expect(box?.innerHTML).toContain('aria-checked="false"'); }); - it("check that correct advanced enable config shows", () => { - component.traces["layers_trace"].config!.selectionConfigs = []; + it('check that correct advanced enable config shows', () => { + component.traces['layers_trace'].config!.selectionConfigs = []; fixture.detectChanges(); - const enable_config_opt = htmlElement.querySelector(".enable-config-opt"); + const enable_config_opt = htmlElement.querySelector('.enable-config-opt'); expect(enable_config_opt).toBeTruthy(); - expect(enable_config_opt?.innerHTML).toContain("trace buffers"); - expect(enable_config_opt?.innerHTML).not.toContain("tracing level"); + expect(enable_config_opt?.innerHTML).toContain('trace buffers'); + expect(enable_config_opt?.innerHTML).not.toContain('tracing level'); - const selection_config_opt = htmlElement.querySelector(".selection-config-opt"); + const selection_config_opt = htmlElement.querySelector('.selection-config-opt'); expect(selection_config_opt).toBeFalsy(); }); - it("check that correct advanced selection config shows", () => { - component.traces["layers_trace"].config!.enableConfigs = []; + it('check that correct advanced selection config shows', () => { + component.traces['layers_trace'].config!.enableConfigs = []; fixture.detectChanges(); - const enable_config_opt = htmlElement.querySelector(".enable-config-opt"); + const enable_config_opt = htmlElement.querySelector('.enable-config-opt'); expect(enable_config_opt).toBeFalsy(); - const selection_config_opt = htmlElement.querySelector(".selection-config-opt"); + const selection_config_opt = htmlElement.querySelector('.selection-config-opt'); expect(selection_config_opt).toBeTruthy(); - expect(selection_config_opt?.innerHTML).not.toContain("trace buffers"); - expect(selection_config_opt?.innerHTML).toContain("tracing level"); + expect(selection_config_opt?.innerHTML).not.toContain('trace buffers'); + expect(selection_config_opt?.innerHTML).toContain('tracing level'); }); - it("check that changing enable config causes box to change", async () => { - component.traces["layers_trace"].config!.enableConfigs[0].enabled = false; + it('check that changing enable config causes box to change', async () => { + component.traces['layers_trace'].config!.enableConfigs[0].enabled = false; fixture.detectChanges(); await fixture.whenStable(); - expect(htmlElement.querySelector(".enable-config")?.innerHTML).toContain("aria-checked=\"false\""); + expect(htmlElement.querySelector('.enable-config')?.innerHTML).toContain( + 'aria-checked="false"' + ); }); - it("check that changing selected config causes select to change", async () => { + it('check that changing selected config causes select to change', async () => { fixture.detectChanges(); - expect(htmlElement.querySelector(".config-selection")?.innerHTML).toContain("value=\"debug\""); - component.traces["layers_trace"].config!.selectionConfigs[0].value = "verbose"; + expect(htmlElement.querySelector('.config-selection')?.innerHTML).toContain('value="debug"'); + component.traces['layers_trace'].config!.selectionConfigs[0].value = 'verbose'; fixture.detectChanges(); await fixture.whenStable(); - expect(htmlElement.querySelector(".config-selection")?.innerHTML).toContain("value=\"verbose\""); + expect(htmlElement.querySelector('.config-selection')?.innerHTML).toContain('value="verbose"'); }); }); diff --git a/tools/winscope-ng/src/app/components/trace_config.component.ts b/tools/winscope-ng/src/app/components/trace_config.component.ts index 0437f927f..250233dd1 100644 --- a/tools/winscope-ng/src/app/components/trace_config.component.ts +++ b/tools/winscope-ng/src/app/components/trace_config.component.ts @@ -13,11 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; -import { EnableConfiguration, SelectionConfiguration, TraceConfiguration, TraceConfigurationMap } from "trace_collection/trace_collection_utils"; +import {Component, Input} from '@angular/core'; +import { + EnableConfiguration, + SelectionConfiguration, + TraceConfiguration, + TraceConfigurationMap, +} from 'trace_collection/trace_collection_utils'; @Component({ - selector: "trace-config", + selector: 'trace-config', template: `

Trace targets

@@ -29,13 +34,14 @@ import { EnableConfiguration, SelectionConfiguration, TraceConfiguration, TraceC [checked]="traces[traceKey].run" [indeterminate]="traces[traceKey].isTraceCollection ? someTraces(traces[traceKey]) : false" (change)="changeRunTrace($event.checked, traces[traceKey])" - >{{traces[traceKey].name}} + >{{ traces[traceKey].name }} -

{{traces[traceKey].name}} configuration

+

{{ traces[traceKey].name }} configuration

{{enableConfig.name}} + >{{ enableConfig.name }}
-
+
+ {{ selectionConfig.name }} - {{selectionConfig.name}} - - - {{ option }} + + {{ + option + }}
@@ -73,16 +83,16 @@ import { EnableConfiguration, SelectionConfiguration, TraceConfiguration, TraceC grid-template-columns: repeat(3, 1fr); column-gap: 10px; } - .enable-config-opt, .selection-config-opt { + .enable-config-opt, + .selection-config-opt { display: flex; flex-direction: row; flex-wrap: wrap; gap: 10px; } - ` - ] + `, + ], }) - export class TraceConfigComponent { objectKeys = Object.keys; @Input() traces!: TraceConfigurationMap; @@ -114,8 +124,7 @@ export class TraceConfigComponent { } public someTraces(trace: TraceConfiguration): boolean { - return this.traceEnableConfigs(trace).filter(trace => trace.enabled).length > 0 - && !trace.run; + return this.traceEnableConfigs(trace).filter((trace) => trace.enabled).length > 0 && !trace.run; } public changeRunTrace(run: boolean, trace: TraceConfiguration): void { @@ -127,7 +136,7 @@ export class TraceConfigComponent { public changeTraceCollectionConfig(trace: TraceConfiguration): void { if (trace.isTraceCollection) { - trace.run = this.traceEnableConfigs(trace).every((c: EnableConfiguration) => c.enabled); + trace.run = this.traceEnableConfigs(trace).every((c: EnableConfiguration) => c.enabled); } } } diff --git a/tools/winscope-ng/src/app/components/trace_view.component.spec.ts b/tools/winscope-ng/src/app/components/trace_view.component.spec.ts index 3b8076b07..36a4def9d 100644 --- a/tools/winscope-ng/src/app/components/trace_view.component.spec.ts +++ b/tools/winscope-ng/src/app/components/trace_view.component.spec.ts @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {CommonModule} from "@angular/common"; -import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from "@angular/core"; -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {MatCardModule} from "@angular/material/card"; -import {MatDividerModule} from "@angular/material/divider"; -import {TraceViewComponent} from "./trace_view.component"; -import {ViewerStub} from "viewers/viewer_stub"; +import {CommonModule} from '@angular/common'; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatCardModule} from '@angular/material/card'; +import {MatDividerModule} from '@angular/material/divider'; +import {ViewerStub} from 'viewers/viewer_stub'; +import {TraceViewComponent} from './trace_view.component'; -describe("TraceViewComponent", () => { +describe('TraceViewComponent', () => { let fixture: ComponentFixture; let component: TraceViewComponent; let htmlElement: HTMLElement; @@ -29,84 +29,77 @@ describe("TraceViewComponent", () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [TraceViewComponent], - imports: [ - CommonModule, - MatCardModule, - MatDividerModule - ], - schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] + imports: [CommonModule, MatCardModule, MatDividerModule], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(TraceViewComponent); htmlElement = fixture.nativeElement; component = fixture.componentInstance; component.viewers = [ - new ViewerStub("Title0", "Content0"), - new ViewerStub("Title1", "Content1") + new ViewerStub('Title0', 'Content0'), + new ViewerStub('Title1', 'Content1'), ]; component.ngOnChanges(); fixture.detectChanges(); }); - it("can be created", () => { + it('can be created', () => { fixture.detectChanges(); expect(component).toBeTruthy(); }); - it("creates viewer tabs", () => { - const tabs: NodeList = htmlElement.querySelectorAll(".tab"); + it('creates viewer tabs', () => { + const tabs: NodeList = htmlElement.querySelectorAll('.tab'); expect(tabs.length).toEqual(2); - expect(tabs.item(0)!.textContent).toEqual("Title0"); - expect(tabs.item(1)!.textContent).toEqual("Title1"); + expect(tabs.item(0)!.textContent).toContain('Title0'); + expect(tabs.item(1)!.textContent).toContain('Title1'); }); - it("changes active view on click", () => { + it('changes active view on click', () => { const getVisibleTabContents = () => { const contents: HTMLElement[] = []; - htmlElement - .querySelectorAll(".trace-view-content div") - .forEach(content => { - if ((content as HTMLElement).style.display != "none") { - contents.push(content as HTMLElement); - } - }); + htmlElement.querySelectorAll('.trace-view-content div').forEach((content) => { + if ((content as HTMLElement).style.display != 'none') { + contents.push(content as HTMLElement); + } + }); return contents; }; - const tabButtons = htmlElement.querySelectorAll(".tab"); + const tabButtons = htmlElement.querySelectorAll('.tab'); // Initially tab 0 fixture.detectChanges(); let visibleTabContents = getVisibleTabContents(); expect(visibleTabContents.length).toEqual(1); - expect(visibleTabContents[0].innerHTML).toEqual("Content0"); + expect(visibleTabContents[0].innerHTML).toEqual('Content0'); // Switch to tab 1 - tabButtons[1].dispatchEvent(new Event("click")); + tabButtons[1].dispatchEvent(new Event('click')); fixture.detectChanges(); visibleTabContents = getVisibleTabContents(); expect(visibleTabContents.length).toEqual(1); - expect(visibleTabContents[0].innerHTML).toEqual("Content1"); + expect(visibleTabContents[0].innerHTML).toEqual('Content1'); // Switch to tab 0 - tabButtons[0].dispatchEvent(new Event("click")); + tabButtons[0].dispatchEvent(new Event('click')); fixture.detectChanges(); visibleTabContents = getVisibleTabContents(); expect(visibleTabContents.length).toEqual(1); - expect(visibleTabContents[0].innerHTML).toEqual("Content0"); + expect(visibleTabContents[0].innerHTML).toEqual('Content0'); }); - it("emits event on download button click", () => { - const spy = spyOn(component.downloadTracesButtonClick, "emit"); + it('emits event on download button click', () => { + const spy = spyOn(component.downloadTracesButtonClick, 'emit'); - const downloadButton: null|HTMLButtonElement = - htmlElement.querySelector(".save-button"); + const downloadButton: null | HTMLButtonElement = htmlElement.querySelector('.save-button'); expect(downloadButton).toBeInstanceOf(HTMLButtonElement); - downloadButton?.dispatchEvent(new Event("click")); + downloadButton?.dispatchEvent(new Event('click')); fixture.detectChanges(); expect(spy).toHaveBeenCalledTimes(1); - downloadButton?.dispatchEvent(new Event("click")); + downloadButton?.dispatchEvent(new Event('click')); fixture.detectChanges(); expect(spy).toHaveBeenCalledTimes(2); }); diff --git a/tools/winscope-ng/src/app/components/trace_view.component.ts b/tools/winscope-ng/src/app/components/trace_view.component.ts index 8b914bd77..3a8fab6dd 100644 --- a/tools/winscope-ng/src/app/components/trace_view.component.ts +++ b/tools/winscope-ng/src/app/components/trace_view.component.ts @@ -14,17 +14,16 @@ * limitations under the License. */ -import {Component, ElementRef, EventEmitter, Inject, Input, Output} from "@angular/core"; -import { TraceType } from "common/trace/trace_type"; -import { PersistentStore } from "common/utils/persistent_store"; -import {Viewer, View, ViewType} from "viewers/viewer"; +import {Component, ElementRef, EventEmitter, Inject, Input, Output} from '@angular/core'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {View, Viewer, ViewType} from 'viewers/viewer'; interface Tab extends View { addedToDom: boolean; } @Component({ - selector: "trace-view", + selector: 'trace-view', template: `
@@ -40,24 +39,24 @@ interface Tab extends View {
-
-
+
`, styles: [ ` @@ -91,8 +90,8 @@ interface Tab extends View { height: 100%; overflow: auto; } - ` - ] + `, + ], }) export class TraceViewComponent { @Input() viewers!: Viewer[]; @@ -103,7 +102,7 @@ export class TraceViewComponent { private elementRef: ElementRef; public tabs: Tab[] = []; - private currentActiveTab: undefined|Tab; + private currentActiveTab: undefined | Tab; constructor(@Inject(ElementRef) elementRef: ElementRef) { this.elementRef = elementRef; @@ -120,10 +119,10 @@ export class TraceViewComponent { private renderViewsTab() { this.tabs = this.viewers - .map(viewer => viewer.getViews()) + .map((viewer) => viewer.getViews()) .flat() - .filter(view => (view.type === ViewType.TAB)) - .map(view => { + .filter((view) => view.type === ViewType.TAB) + .map((view) => { return { type: view.type, htmlElement: view.htmlElement, @@ -133,7 +132,7 @@ export class TraceViewComponent { }; }); - this.tabs.forEach(tab => { + this.tabs.forEach((tab) => { // TODO: setting "store" this way is a hack. // Store should be part of View's interface. (tab.htmlElement as any).store = this.store; @@ -146,28 +145,31 @@ export class TraceViewComponent { private renderViewsOverlay() { const views: View[] = this.viewers - .map(viewer => viewer.getViews()) + .map((viewer) => viewer.getViews()) .flat() - .filter(view => (view.type === ViewType.OVERLAY)); + .filter((view) => view.type === ViewType.OVERLAY); if (views.length > 1) { throw new Error( - "Only one overlay view is supported. To allow more overlay views, either create more than" + - " one draggable containers in this component or move the cdkDrag directives into the" + - " overlay view when the new Angular's directive composition API is available" + - " (https://github.com/angular/angular/issues/8785)."); + 'Only one overlay view is supported. To allow more overlay views, either create more than' + + ' one draggable containers in this component or move the cdkDrag directives into the' + + " overlay view when the new Angular's directive composition API is available" + + ' (https://github.com/angular/angular/issues/8785).' + ); } - views.forEach(view => { - view.htmlElement.style.pointerEvents = "all"; - const container = this.elementRef.nativeElement.querySelector(".overlay .draggable-container")!; + views.forEach((view) => { + view.htmlElement.style.pointerEvents = 'all'; + const container = this.elementRef.nativeElement.querySelector( + '.overlay .draggable-container' + )!; container.appendChild(view.htmlElement); }); } private showTab(tab: Tab) { if (this.currentActiveTab) { - this.currentActiveTab.htmlElement.style.display = "none"; + this.currentActiveTab.htmlElement.style.display = 'none'; } if (!tab.addedToDom) { @@ -176,12 +178,11 @@ export class TraceViewComponent { // (added to the DOM) it has style.display == "". This fixes the // initialization/rendering issues with cdk-virtual-scroll-viewport // components inside the tab contents. - const traceViewContent = this.elementRef.nativeElement.querySelector(".trace-view-content")!; + const traceViewContent = this.elementRef.nativeElement.querySelector('.trace-view-content')!; traceViewContent.appendChild(tab.htmlElement); tab.addedToDom = true; - } - else { - tab.htmlElement.style.display = ""; + } else { + tab.htmlElement.style.display = ''; } this.currentActiveTab = tab; diff --git a/tools/winscope-ng/src/app/components/upload_traces.component.spec.ts b/tools/winscope-ng/src/app/components/upload_traces.component.spec.ts index 3670fc2a3..13bc42a6f 100644 --- a/tools/winscope-ng/src/app/components/upload_traces.component.spec.ts +++ b/tools/winscope-ng/src/app/components/upload_traces.component.spec.ts @@ -13,23 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {UploadTracesComponent} from "./upload_traces.component"; -import { MatCardModule } from "@angular/material/card"; -import { MatSnackBar, MatSnackBarModule } from "@angular/material/snack-bar"; -import {TraceData} from "app/trace_data"; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatCardModule} from '@angular/material/card'; +import {MatSnackBar, MatSnackBarModule} from '@angular/material/snack-bar'; +import {TraceData} from 'app/trace_data'; +import {UploadTracesComponent} from './upload_traces.component'; -describe("UploadTracesComponent", () => { +describe('UploadTracesComponent', () => { let fixture: ComponentFixture; let component: UploadTracesComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - imports: [ - MatCardModule, - MatSnackBarModule - ], + imports: [MatCardModule, MatSnackBarModule], providers: [MatSnackBar], declarations: [UploadTracesComponent], }).compileComponents(); @@ -43,8 +40,7 @@ describe("UploadTracesComponent", () => { component.traceData = traceData; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - }); diff --git a/tools/winscope-ng/src/app/components/upload_traces.component.ts b/tools/winscope-ng/src/app/components/upload_traces.component.ts index 336d900ff..fe7ff8801 100644 --- a/tools/winscope-ng/src/app/components/upload_traces.component.ts +++ b/tools/winscope-ng/src/app/components/upload_traces.component.ts @@ -20,90 +20,83 @@ import { Inject, Input, NgZone, - Output -} from "@angular/core"; -import {MatSnackBar} from "@angular/material/snack-bar"; -import {TraceData} from "app/trace_data"; -import {TRACE_INFO} from "app/trace_info"; -import {Trace, TraceFile} from "common/trace/trace"; -import {FileUtils, OnFile} from "common/utils/file_utils"; -import {ParserErrorSnackBarComponent} from "./parser_error_snack_bar_component"; -import {FilesDownloadListener} from "interfaces/files_download_listener"; + Output, +} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {TraceData} from 'app/trace_data'; +import {TRACE_INFO} from 'app/trace_info'; +import {Trace, TraceFile} from 'common/trace/trace'; +import {FileUtils, OnFile} from 'common/utils/file_utils'; +import {FilesDownloadListener} from 'interfaces/files_download_listener'; +import {ParserErrorSnackBarComponent} from './parser_error_snack_bar_component'; @Component({ - selector: "upload-traces", + selector: 'upload-traces', template: ` Upload Traces + class="drop-box" + ref="drop-box" + (dragleave)="onFileDragOut($event)" + (dragover)="onFileDragIn($event)" + (drop)="onHandleFileDrop($event)" + (click)="fileDropRef.click()"> + id="fileDropRef" + hidden + type="file" + multiple + #fileDropRef + (change)="onInputFiles($event)" /> - + + *ngIf="!isLoadingFiles && this.traceData.getLoadedTraces().length > 0" + class="uploaded-files"> - {{TRACE_INFO[trace.type].icon}} + {{ TRACE_INFO[trace.type].icon }} -

- {{trace.traceFile.file.name}} ({{TRACE_INFO[trace.type].name}}) -

+

{{ trace.traceFile.file.name }} ({{ TRACE_INFO[trace.type].name }})

-
-
+

-

- Drag your .winscope file(s) or click to upload -

+

Drag your .winscope file(s) or click to upload

-
- - - +
`, @@ -171,13 +164,13 @@ import {FilesDownloadListener} from "interfaces/files_download_listener"; mat-card-content { flex-grow: 1; } - ` - ] + `, + ], }) export class UploadTracesComponent implements FilesDownloadListener { TRACE_INFO = TRACE_INFO; isLoadingFiles = false; - progressMessage = ""; + progressMessage = ''; progressPercentage?: number; @Input() traceData!: TraceData; @@ -187,8 +180,7 @@ export class UploadTracesComponent implements FilesDownloadListener { @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef, @Inject(MatSnackBar) private snackBar: MatSnackBar, @Inject(NgZone) private ngZone: NgZone - ) { - } + ) {} ngOnInit() { this.traceData.clear(); @@ -196,7 +188,7 @@ export class UploadTracesComponent implements FilesDownloadListener { public onFilesDownloadStart() { this.isLoadingFiles = true; - this.progressMessage = "Downloading files..."; + this.progressMessage = 'Downloading files...'; this.progressPercentage = undefined; this.changeDetectorRef.detectChanges(); } @@ -233,7 +225,7 @@ export class UploadTracesComponent implements FilesDownloadListener { e.preventDefault(); e.stopPropagation(); const droppedFiles = e.dataTransfer?.files; - if(!droppedFiles) return; + if (!droppedFiles) return; await this.processFiles(Array.from(droppedFiles)); } @@ -250,7 +242,7 @@ export class UploadTracesComponent implements FilesDownloadListener { const onProgressUpdate = (progress: number) => { const now = Date.now(); - if ((Date.now() - lastUiProgressUpdate) < UI_PROGRESS_UPDATE_PERIOD_MS) { + if (Date.now() - lastUiProgressUpdate < UI_PROGRESS_UPDATE_PERIOD_MS) { // Let's limit the amount of UI updates, because the progress bar component // renders weird stuff when updated too frequently return; @@ -267,11 +259,11 @@ export class UploadTracesComponent implements FilesDownloadListener { }; this.isLoadingFiles = true; - this.progressMessage = "Unzipping files..."; + this.progressMessage = 'Unzipping files...'; this.changeDetectorRef.detectChanges(); await FileUtils.unzipFilesIfNeeded(files, onFile, onProgressUpdate); - this.progressMessage = "Parsing files..."; + this.progressMessage = 'Parsing files...'; this.changeDetectorRef.detectChanges(); const parserErrors = await this.traceData.loadTraces(traceFiles, onProgressUpdate); diff --git a/tools/winscope-ng/src/app/components/upload_traces_component_stub.ts b/tools/winscope-ng/src/app/components/upload_traces_component_stub.ts index 7b68fd8b5..7ae7acdfb 100644 --- a/tools/winscope-ng/src/app/components/upload_traces_component_stub.ts +++ b/tools/winscope-ng/src/app/components/upload_traces_component_stub.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {FilesDownloadListener} from "interfaces/files_download_listener"; +import {FilesDownloadListener} from 'interfaces/files_download_listener'; export class UploadTracesComponentStub implements FilesDownloadListener { onFilesDownloadStart() { diff --git a/tools/winscope-ng/src/app/components/web_adb.component.spec.ts b/tools/winscope-ng/src/app/components/web_adb.component.spec.ts index f8dff11b6..d888cec7b 100644 --- a/tools/winscope-ng/src/app/components/web_adb.component.spec.ts +++ b/tools/winscope-ng/src/app/components/web_adb.component.spec.ts @@ -13,20 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {WebAdbComponent} from "./web_adb.component"; -import { MatIconModule } from "@angular/material/icon"; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatIconModule} from '@angular/material/icon'; +import {WebAdbComponent} from './web_adb.component'; -describe("WebAdbComponent", () => { +describe('WebAdbComponent', () => { let fixture: ComponentFixture; let component: WebAdbComponent; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ - MatIconModule - ], + imports: [MatIconModule], declarations: [WebAdbComponent], }).compileComponents(); fixture = TestBed.createComponent(WebAdbComponent); @@ -34,13 +32,13 @@ describe("WebAdbComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("renders the info message", () => { + it('renders the info message', () => { fixture.detectChanges(); - expect(htmlElement.querySelector(".adb-info")?.innerHTML).toBe("Add new device"); - expect(htmlElement.querySelector(".adb-icon")?.innerHTML).toBe("info"); + expect(htmlElement.querySelector('.adb-info')?.innerHTML).toBe('Add new device'); + expect(htmlElement.querySelector('.adb-icon')?.innerHTML).toBe('info'); }); }); diff --git a/tools/winscope-ng/src/app/components/web_adb.component.ts b/tools/winscope-ng/src/app/components/web_adb.component.ts index ac576f99b..006d6be06 100644 --- a/tools/winscope-ng/src/app/components/web_adb.component.ts +++ b/tools/winscope-ng/src/app/components/web_adb.component.ts @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Component} from "@angular/core"; +import {Component} from '@angular/core'; @Component({ - selector: "web-adb", + selector: 'web-adb', template: ` -

- info - Add new device -

-

Click the button below to follow instructions in the Chrome pop-up.

-

Selecting a device will kill all existing ADB connections.

- +

+ info + Add new device +

+

Click the button below to follow instructions in the Chrome pop-up.

+

Selecting a device will kill all existing ADB connections.

+ `, styles: [ ` @@ -33,11 +33,12 @@ import {Component} from "@angular/core"; flex-direction: row; align-items: center; } - .adb-info, .web-select-btn { + .adb-info, + .web-select-btn { margin-left: 5px; } - ` - ] + `, + ], }) export class WebAdbComponent { adbDevice = null; diff --git a/tools/winscope-ng/src/app/mediator.spec.ts b/tools/winscope-ng/src/app/mediator.spec.ts index 6aac6e7e7..cbaf55160 100644 --- a/tools/winscope-ng/src/app/mediator.spec.ts +++ b/tools/winscope-ng/src/app/mediator.spec.ts @@ -14,23 +14,23 @@ * limitations under the License. */ -import {AppComponentStub} from "./components/app_component_stub"; -import {TimelineComponentStub} from "./components/timeline/timeline_component_stub"; -import {UploadTracesComponentStub} from "./components/upload_traces_component_stub"; -import {Mediator} from "./mediator"; -import {AbtChromeExtensionProtocolStub} from "abt_chrome_extension/abt_chrome_extension_protocol_stub"; -import {CrossToolProtocolStub} from "cross_tool/cross_tool_protocol_stub"; -import {TraceFile} from "common/trace/trace"; -import {RealTimestamp} from "common/trace/timestamp"; -import {UnitTestUtils} from "test/unit/utils"; -import {ViewerFactory} from "viewers/viewer_factory"; -import {ViewerStub} from "viewers/viewer_stub"; -import {TimelineData} from "./timeline_data"; -import {TraceData} from "./trace_data"; -import {MockStorage} from "test/unit/mock_storage"; +import {AbtChromeExtensionProtocolStub} from 'abt_chrome_extension/abt_chrome_extension_protocol_stub'; +import {RealTimestamp} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {CrossToolProtocolStub} from 'cross_tool/cross_tool_protocol_stub'; +import {MockStorage} from 'test/unit/mock_storage'; +import {UnitTestUtils} from 'test/unit/utils'; +import {ViewerFactory} from 'viewers/viewer_factory'; +import {ViewerStub} from 'viewers/viewer_stub'; +import {AppComponentStub} from './components/app_component_stub'; +import {TimelineComponentStub} from './components/timeline/timeline_component_stub'; +import {UploadTracesComponentStub} from './components/upload_traces_component_stub'; +import {Mediator} from './mediator'; +import {TimelineData} from './timeline_data'; +import {TraceData} from './trace_data'; -describe("Mediator", () => { - const viewerStub = new ViewerStub("Title"); +describe('Mediator', () => { + const viewerStub = new ViewerStub('Title'); let traceData: TraceData; let timelineData: TimelineData; let abtChromeExtensionProtocol: AbtChromeExtensionProtocolStub; @@ -63,13 +63,13 @@ describe("Mediator", () => { mediator.setTimelineComponent(timelineComponent); mediator.setUploadTracesComponent(uploadTracesComponent); - spyOn(ViewerFactory.prototype, "createViewers").and.returnValue([viewerStub]); + spyOn(ViewerFactory.prototype, 'createViewers').and.returnValue([viewerStub]); }); - it("handles data load event from Winscope", async () => { - spyOn(timelineData, "initialize").and.callThrough(); - spyOn(appComponent, "onTraceDataLoaded"); - spyOn(viewerStub, "notifyCurrentTraceEntries"); + it('handles data load event from Winscope', async () => { + spyOn(timelineData, 'initialize').and.callThrough(); + spyOn(appComponent, 'onTraceDataLoaded'); + spyOn(viewerStub, 'notifyCurrentTraceEntries'); await loadTraces(); expect(timelineData.initialize).toHaveBeenCalledTimes(0); @@ -89,16 +89,16 @@ describe("Mediator", () => { //TODO: test "data from ABT chrome extension" when FileUtils is fully compatible with Node.js // (b/262269229). - it("handles start download event from ABT chrome extension", () => { - spyOn(uploadTracesComponent, "onFilesDownloadStart"); + it('handles start download event from ABT chrome extension', () => { + spyOn(uploadTracesComponent, 'onFilesDownloadStart'); expect(uploadTracesComponent.onFilesDownloadStart).toHaveBeenCalledTimes(0); abtChromeExtensionProtocol.onBuganizerAttachmentsDownloadStart(); expect(uploadTracesComponent.onFilesDownloadStart).toHaveBeenCalledTimes(1); }); - it("handles empty downloaded files from ABT chrome extension", async () => { - spyOn(uploadTracesComponent, "onFilesDownloaded"); + it('handles empty downloaded files from ABT chrome extension', async () => { + spyOn(uploadTracesComponent, 'onFilesDownloaded'); expect(uploadTracesComponent.onFilesDownloaded).toHaveBeenCalledTimes(0); // Pass files even if empty so that the upload component will update the progress bar @@ -107,13 +107,13 @@ describe("Mediator", () => { expect(uploadTracesComponent.onFilesDownloaded).toHaveBeenCalledTimes(1); }); - it("propagates current timestamp changed through timeline", async () => { + it('propagates current timestamp changed through timeline', async () => { await loadTraces(); mediator.onWinscopeTraceDataLoaded(); - spyOn(viewerStub, "notifyCurrentTraceEntries"); - spyOn(timelineComponent, "onCurrentTimestampChanged"); - spyOn(crossToolProtocol, "sendTimestamp"); + spyOn(viewerStub, 'notifyCurrentTraceEntries'); + spyOn(timelineComponent, 'onCurrentTimestampChanged'); + spyOn(crossToolProtocol, 'sendTimestamp'); expect(viewerStub.notifyCurrentTraceEntries).toHaveBeenCalledTimes(0); expect(timelineComponent.onCurrentTimestampChanged).toHaveBeenCalledTimes(0); expect(crossToolProtocol.sendTimestamp).toHaveBeenCalledTimes(0); @@ -137,13 +137,13 @@ describe("Mediator", () => { expect(crossToolProtocol.sendTimestamp).toHaveBeenCalledTimes(2); }); - describe("timestamp received from remote tool", () => { - it("propagates timestamp changes", async () => { + describe('timestamp received from remote tool', () => { + it('propagates timestamp changes', async () => { await loadTraces(); mediator.onWinscopeTraceDataLoaded(); - spyOn(viewerStub, "notifyCurrentTraceEntries"); - spyOn(timelineComponent, "onCurrentTimestampChanged"); + spyOn(viewerStub, 'notifyCurrentTraceEntries'); + spyOn(timelineComponent, 'onCurrentTimestampChanged'); expect(viewerStub.notifyCurrentTraceEntries).toHaveBeenCalledTimes(0); expect(timelineComponent.onCurrentTimestampChanged).toHaveBeenCalledTimes(0); @@ -167,8 +167,8 @@ describe("Mediator", () => { await loadTraces(); mediator.onWinscopeTraceDataLoaded(); - spyOn(viewerStub, "notifyCurrentTraceEntries"); - spyOn(crossToolProtocol, "sendTimestamp"); + spyOn(viewerStub, 'notifyCurrentTraceEntries'); + spyOn(crossToolProtocol, 'sendTimestamp'); // receive timestamp await crossToolProtocol.onTimestampReceived(TIMESTAMP_10); @@ -176,8 +176,8 @@ describe("Mediator", () => { expect(crossToolProtocol.sendTimestamp).toHaveBeenCalledTimes(0); }); - it("defers propagation till traces are loaded and visualized", async () => { - spyOn(timelineComponent, "onCurrentTimestampChanged"); + it('defers propagation till traces are loaded and visualized', async () => { + spyOn(timelineComponent, 'onCurrentTimestampChanged'); // keep timestamp for later await crossToolProtocol.onTimestampReceived(TIMESTAMP_10); @@ -196,12 +196,17 @@ describe("Mediator", () => { const loadTraces = async () => { const traces = [ - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/SurfaceFlinger.pb")), - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/WindowManager.pb")), - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4")), + new TraceFile( + await UnitTestUtils.getFixtureFile('traces/elapsed_and_real_timestamp/SurfaceFlinger.pb') + ), + new TraceFile( + await UnitTestUtils.getFixtureFile('traces/elapsed_and_real_timestamp/WindowManager.pb') + ), + new TraceFile( + await UnitTestUtils.getFixtureFile( + 'traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4' + ) + ), ]; const errors = await traceData.loadTraces(traces); expect(errors).toEqual([]); diff --git a/tools/winscope-ng/src/app/mediator.ts b/tools/winscope-ng/src/app/mediator.ts index ede1a1e53..64d720f59 100644 --- a/tools/winscope-ng/src/app/mediator.ts +++ b/tools/winscope-ng/src/app/mediator.ts @@ -14,25 +14,26 @@ * limitations under the License. */ -import {TimelineData} from "./timeline_data"; -import {TraceData} from "./trace_data"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {BuganizerAttachmentsDownloadEmitter} from "interfaces/buganizer_attachments_download_emitter"; -import {FilesDownloadListener} from "interfaces/files_download_listener"; -import {RemoteBugreportReceiver} from "interfaces/remote_bugreport_receiver"; -import {RemoteTimestampReceiver} from "interfaces/remote_timestamp_receiver"; -import {RemoteTimestampSender} from "interfaces/remote_timestamp_sender"; -import {Runnable} from "interfaces/runnable"; -import {TimestampChangeListener} from "interfaces/timestamp_change_listener"; -import {TraceDataListener} from "interfaces/trace_data_listener"; -import {Viewer} from "viewers/viewer"; -import {ViewerFactory} from "viewers/viewer_factory"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {BuganizerAttachmentsDownloadEmitter} from 'interfaces/buganizer_attachments_download_emitter'; +import {FilesDownloadListener} from 'interfaces/files_download_listener'; +import {RemoteBugreportReceiver} from 'interfaces/remote_bugreport_receiver'; +import {RemoteTimestampReceiver} from 'interfaces/remote_timestamp_receiver'; +import {RemoteTimestampSender} from 'interfaces/remote_timestamp_sender'; +import {Runnable} from 'interfaces/runnable'; +import {TimestampChangeListener} from 'interfaces/timestamp_change_listener'; +import {TraceDataListener} from 'interfaces/trace_data_listener'; +import {Viewer} from 'viewers/viewer'; +import {ViewerFactory} from 'viewers/viewer_factory'; +import {TimelineData} from './timeline_data'; +import {TraceData} from './trace_data'; -export type CrossToolProtocolDependencyInversion = - RemoteBugreportReceiver & RemoteTimestampReceiver & RemoteTimestampSender; -export type AbtChromeExtensionProtocolDependencyInversion = - BuganizerAttachmentsDownloadEmitter & Runnable; +export type CrossToolProtocolDependencyInversion = RemoteBugreportReceiver & + RemoteTimestampReceiver & + RemoteTimestampSender; +export type AbtChromeExtensionProtocolDependencyInversion = BuganizerAttachmentsDownloadEmitter & + Runnable; export type AppComponentDependencyInversion = TraceDataListener; export type TimelineComponentDependencyInversion = TimestampChangeListener; export type UploadTracesComponentDependencyInversion = FilesDownloadListener; @@ -50,7 +51,7 @@ export class Mediator { private viewers: Viewer[] = []; private isChangingCurrentTimestamp = false; private isTraceDataVisualized = false; - private lastRemoteToolTimestampReceived: Timestamp|undefined; + private lastRemoteToolTimestampReceived: Timestamp | undefined; constructor( traceData: TraceData, @@ -58,8 +59,8 @@ export class Mediator { abtChromeExtensionProtocol: AbtChromeExtensionProtocolDependencyInversion, crossToolProtocol: CrossToolProtocolDependencyInversion, appComponent: AppComponentDependencyInversion, - storage: Storage) { - + storage: Storage + ) { this.traceData = traceData; this.timelineData = timelineData; this.abtChromeExtensionProtocol = abtChromeExtensionProtocol; @@ -67,13 +68,15 @@ export class Mediator { this.appComponent = appComponent; this.storage = storage; - this.timelineData.setOnCurrentTimestampChanged(timestamp => { + this.timelineData.setOnCurrentTimestampChanged((timestamp) => { this.onWinscopeCurrentTimestampChanged(timestamp); }); - this.crossToolProtocol.setOnBugreportReceived(async (bugreport: File, timestamp?: Timestamp) => { - await this.onRemoteBugreportReceived(bugreport, timestamp); - }); + this.crossToolProtocol.setOnBugreportReceived( + async (bugreport: File, timestamp?: Timestamp) => { + await this.onRemoteBugreportReceived(bugreport, timestamp); + } + ); this.crossToolProtocol.setOnTimestampReceived(async (timestamp: Timestamp) => { this.onRemoteTimestampReceived(timestamp); @@ -83,18 +86,20 @@ export class Mediator { this.onBuganizerAttachmentsDownloadStart(); }); - this.abtChromeExtensionProtocol.setOnBuganizerAttachmentsDownloaded(async (attachments: File[]) => { - await this.onBuganizerAttachmentsDownloaded(attachments); - }); + this.abtChromeExtensionProtocol.setOnBuganizerAttachmentsDownloaded( + async (attachments: File[]) => { + await this.onBuganizerAttachmentsDownloaded(attachments); + } + ); } public setUploadTracesComponent( - uploadTracesComponent: UploadTracesComponentDependencyInversion|undefined + uploadTracesComponent: UploadTracesComponentDependencyInversion | undefined ) { this.uploadTracesComponent = uploadTracesComponent; } - public setTimelineComponent(timelineComponent: TimelineComponentDependencyInversion|undefined) { + public setTimelineComponent(timelineComponent: TimelineComponentDependencyInversion | undefined) { this.timelineComponent = timelineComponent; } @@ -110,19 +115,19 @@ export class Mediator { this.processTraceData(); } - public onWinscopeCurrentTimestampChanged(timestamp: Timestamp|undefined) { + public onWinscopeCurrentTimestampChanged(timestamp: Timestamp | undefined) { this.executeIgnoringRecursiveTimestampNotifications(() => { const entries = this.traceData.getTraceEntries(timestamp); - this.viewers.forEach(viewer => { + this.viewers.forEach((viewer) => { viewer.notifyCurrentTraceEntries(entries); }); if (timestamp) { if (timestamp.getType() !== TimestampType.REAL) { console.warn( - "Cannot propagate timestamp change to remote tool." + - ` Remote tool expects timestamp type ${TimestampType.REAL},` + - ` but Winscope wants to notify timestamp type ${timestamp.getType()}.` + 'Cannot propagate timestamp change to remote tool.' + + ` Remote tool expects timestamp type ${TimestampType.REAL},` + + ` but Winscope wants to notify timestamp type ${timestamp.getType()}.` ); } else { this.crossToolProtocol.sendTimestamp(timestamp); @@ -159,9 +164,9 @@ export class Mediator { if (this.timelineData.getTimestampType() !== timestamp.getType()) { console.warn( - "Cannot apply new timestamp received from remote tool." + - ` Remote tool notified timestamp type ${timestamp.getType()},` + - ` but Winscope is accepting timestamp type ${this.timelineData.getTimestampType()}.` + 'Cannot apply new timestamp received from remote tool.' + + ` Remote tool notified timestamp type ${timestamp.getType()},` + + ` but Winscope is accepting timestamp type ${this.timelineData.getTimestampType()}.` ); return; } @@ -171,7 +176,7 @@ export class Mediator { } const entries = this.traceData.getTraceEntries(timestamp); - this.viewers.forEach(viewer => { + this.viewers.forEach((viewer) => { viewer.notifyCurrentTraceEntries(entries); }); @@ -200,7 +205,7 @@ export class Mediator { } private createViewers() { - const traceTypes = this.traceData.getLoadedTraces().map(trace => trace.type); + const traceTypes = this.traceData.getLoadedTraces().map((trace) => trace.type); this.viewers = new ViewerFactory().createViewers(new Set(traceTypes), this.storage); // Make sure to update the viewers active entries as soon as they are created. diff --git a/tools/winscope-ng/src/app/timeline_data.spec.ts b/tools/winscope-ng/src/app/timeline_data.spec.ts index d920e6327..ebd273fe2 100644 --- a/tools/winscope-ng/src/app/timeline_data.spec.ts +++ b/tools/winscope-ng/src/app/timeline_data.spec.ts @@ -14,53 +14,55 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {TimelineData} from "./timeline_data"; -import {Timeline} from "./trace_data"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {TimelineData} from './timeline_data'; +import {Timeline} from './trace_data'; class TimestampChangedObserver { - onCurrentTimestampChanged(timestamp: Timestamp|undefined) { + onCurrentTimestampChanged(timestamp: Timestamp | undefined) { // do nothing } } -describe("TimelineData", () => { +describe('TimelineData', () => { let timelineData: TimelineData; const timestampChangedObserver = new TimestampChangedObserver(); const timestamp10 = new Timestamp(TimestampType.REAL, 10n); const timestamp11 = new Timestamp(TimestampType.REAL, 11n); - const timelines: Timeline[] = [{ - traceType: TraceType.SURFACE_FLINGER, - timestamps: [timestamp10] - }, - { - traceType: TraceType.WINDOW_MANAGER, - timestamps: [timestamp11] - }]; + const timelines: Timeline[] = [ + { + traceType: TraceType.SURFACE_FLINGER, + timestamps: [timestamp10], + }, + { + traceType: TraceType.WINDOW_MANAGER, + timestamps: [timestamp11], + }, + ]; beforeEach(() => { timelineData = new TimelineData(); - timelineData.setOnCurrentTimestampChanged(timestamp => { + timelineData.setOnCurrentTimestampChanged((timestamp) => { timestampChangedObserver.onCurrentTimestampChanged(timestamp); }); }); - it("sets timelines", () => { + it('sets timelines', () => { expect(timelineData.getCurrentTimestamp()).toBeUndefined(); timelineData.initialize(timelines, undefined); expect(timelineData.getCurrentTimestamp()).toEqual(timestamp10); }); - it("uses first timestamp by default", () => { + it('uses first timestamp by default', () => { timelineData.initialize(timelines, undefined); expect(timelineData.getCurrentTimestamp()?.getValueNs()).toEqual(10n); }); - it("uses explicit timestamp if set", () => { + it('uses explicit timestamp if set', () => { timelineData.initialize(timelines, undefined); expect(timelineData.getCurrentTimestamp()?.getValueNs()).toEqual(10n); @@ -72,7 +74,7 @@ describe("TimelineData", () => { expect(timelineData.getCurrentTimestamp()).toEqual(explicitTimestamp); }); - it("sets active trace types and update current timestamp accordingly", () => { + it('sets active trace types and update current timestamp accordingly', () => { timelineData.initialize(timelines, undefined); timelineData.setActiveViewTraceTypes([]); @@ -88,8 +90,8 @@ describe("TimelineData", () => { expect(timelineData.getCurrentTimestamp()).toEqual(timestamp10); }); - it("notifies callback when current timestamp changes", () => { - spyOn(timestampChangedObserver, "onCurrentTimestampChanged"); + it('notifies callback when current timestamp changes', () => { + spyOn(timestampChangedObserver, 'onCurrentTimestampChanged'); expect(timestampChangedObserver.onCurrentTimestampChanged).toHaveBeenCalledTimes(0); timelineData.initialize(timelines, undefined); @@ -102,7 +104,7 @@ describe("TimelineData", () => { it("doesn't notify observers when current timestamp doesn't change", () => { timelineData.initialize(timelines, undefined); - spyOn(timestampChangedObserver, "onCurrentTimestampChanged"); + spyOn(timestampChangedObserver, 'onCurrentTimestampChanged'); expect(timestampChangedObserver.onCurrentTimestampChanged).toHaveBeenCalledTimes(0); timelineData.setActiveViewTraceTypes([TraceType.SURFACE_FLINGER]); @@ -112,47 +114,69 @@ describe("TimelineData", () => { expect(timestampChangedObserver.onCurrentTimestampChanged).toHaveBeenCalledTimes(0); }); - it("hasTimestamps()", () => { + it('hasTimestamps()', () => { expect(timelineData.hasTimestamps()).toBeFalse(); timelineData.initialize([], undefined); expect(timelineData.hasTimestamps()).toBeFalse(); - timelineData.initialize([{ - traceType: TraceType.SURFACE_FLINGER, - timestamps: [] - }], undefined); + timelineData.initialize( + [ + { + traceType: TraceType.SURFACE_FLINGER, + timestamps: [], + }, + ], + undefined + ); expect(timelineData.hasTimestamps()).toBeFalse(); - timelineData.initialize([{ - traceType: TraceType.SURFACE_FLINGER, - timestamps: [new Timestamp(TimestampType.REAL, 10n)] - }], undefined); + timelineData.initialize( + [ + { + traceType: TraceType.SURFACE_FLINGER, + timestamps: [new Timestamp(TimestampType.REAL, 10n)], + }, + ], + undefined + ); expect(timelineData.hasTimestamps()).toBeTrue(); }); - it("hasMoreThanOneDistinctTimestamp()", () => { + it('hasMoreThanOneDistinctTimestamp()', () => { expect(timelineData.hasMoreThanOneDistinctTimestamp()).toBeFalse(); timelineData.initialize([], undefined); expect(timelineData.hasMoreThanOneDistinctTimestamp()).toBeFalse(); - timelineData.initialize([{ - traceType: TraceType.SURFACE_FLINGER, - timestamps: [new Timestamp(TimestampType.REAL, 10n)] - }, { - traceType: TraceType.WINDOW_MANAGER, - timestamps: [new Timestamp(TimestampType.REAL, 10n)] - }], undefined); + timelineData.initialize( + [ + { + traceType: TraceType.SURFACE_FLINGER, + timestamps: [new Timestamp(TimestampType.REAL, 10n)], + }, + { + traceType: TraceType.WINDOW_MANAGER, + timestamps: [new Timestamp(TimestampType.REAL, 10n)], + }, + ], + undefined + ); expect(timelineData.hasMoreThanOneDistinctTimestamp()).toBeFalse(); - timelineData.initialize([{ - traceType: TraceType.SURFACE_FLINGER, - timestamps: [new Timestamp(TimestampType.REAL, 10n)] - }, { - traceType: TraceType.WINDOW_MANAGER, - timestamps: [new Timestamp(TimestampType.REAL, 11n)] - }], undefined); + timelineData.initialize( + [ + { + traceType: TraceType.SURFACE_FLINGER, + timestamps: [new Timestamp(TimestampType.REAL, 10n)], + }, + { + traceType: TraceType.WINDOW_MANAGER, + timestamps: [new Timestamp(TimestampType.REAL, 11n)], + }, + ], + undefined + ); expect(timelineData.hasMoreThanOneDistinctTimestamp()).toBeTrue(); }); }); diff --git a/tools/winscope-ng/src/app/timeline_data.ts b/tools/winscope-ng/src/app/timeline_data.ts index b2c9b49e8..d33cc176d 100644 --- a/tools/winscope-ng/src/app/timeline_data.ts +++ b/tools/winscope-ng/src/app/timeline_data.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import {Timeline} from "./trace_data"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import { ArrayUtils } from "common/utils/array_utils"; -import { FunctionUtils} from "common/utils/function_utils"; -import {TimeUtils} from "common/utils/time_utils"; -import {ScreenRecordingUtils} from "common/trace/screen_recording_utils"; +import {ScreenRecordingUtils} from 'common/trace/screen_recording_utils'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {ArrayUtils} from 'common/utils/array_utils'; +import {FunctionUtils} from 'common/utils/function_utils'; +import {TimeUtils} from 'common/utils/time_utils'; +import {Timeline} from './trace_data'; -export type TimestampCallbackType = (timestamp: Timestamp|undefined) => void; -export type TimeRange = { from: Timestamp, to: Timestamp } -type TimestampWithIndex = {index: number, timestamp: Timestamp}; +export type TimestampCallbackType = (timestamp: Timestamp | undefined) => void; +export type TimeRange = {from: Timestamp; to: Timestamp}; +type TimestampWithIndex = {index: number; timestamp: Timestamp}; export class TimelineData { private timelines = new Map(); @@ -35,21 +35,21 @@ export class TimelineData { private activeViewTraceTypes: TraceType[] = []; // dependencies of current active view private onCurrentTimestampChanged: TimestampCallbackType = FunctionUtils.DO_NOTHING; - public initialize(timelines: Timeline[], screenRecordingVideo: Blob|undefined) { + public initialize(timelines: Timeline[], screenRecordingVideo: Blob | undefined) { this.clear(); this.screenRecordingVideo = screenRecordingVideo; - const allTimestamps = timelines.flatMap(timeline => timeline.timestamps); - if (allTimestamps.some(timestamp => timestamp.getType() != allTimestamps[0].getType())) { - throw Error("Added timeline has inconsistent timestamps."); + const allTimestamps = timelines.flatMap((timeline) => timeline.timestamps); + if (allTimestamps.some((timestamp) => timestamp.getType() != allTimestamps[0].getType())) { + throw Error('Added timeline has inconsistent timestamps.'); } if (allTimestamps.length > 0) { this.timestampType = allTimestamps[0].getType(); } - timelines.forEach(timeline => { + timelines.forEach((timeline) => { this.timelines.set(timeline.traceType, timeline.timestamps); }); @@ -60,7 +60,7 @@ export class TimelineData { this.onCurrentTimestampChanged = callback; } - getCurrentTimestamp(): Timestamp|undefined { + getCurrentTimestamp(): Timestamp | undefined { if (this.explicitlySetTimestamp !== undefined) { return this.explicitlySetTimestamp; } @@ -70,18 +70,18 @@ export class TimelineData { return this.getFirstTimestamp(); } - public setCurrentTimestamp(timestamp: Timestamp|undefined) { + public setCurrentTimestamp(timestamp: Timestamp | undefined) { if (!this.hasTimestamps()) { - console.warn("Attempted to set timestamp on traces with no timestamps/entries..."); + console.warn('Attempted to set timestamp on traces with no timestamps/entries...'); return; } if (timestamp !== undefined) { if (this.timestampType === undefined) { - throw Error("Attempted to set explicit timestamp but no timestamp type is available"); + throw Error('Attempted to set explicit timestamp but no timestamp type is available'); } if (timestamp.getType() !== this.timestampType) { - throw Error("Attempted to set explicit timestamp with incompatible type"); + throw Error('Attempted to set explicit timestamp with incompatible type'); } } @@ -90,24 +90,23 @@ export class TimelineData { }); } - public setActiveViewTraceTypes(types: TraceType[]) { this.applyOperationAndNotifyIfCurrentTimestampChanged(() => { this.activeViewTraceTypes = types; }); } - public getTimestampType(): TimestampType|undefined { + public getTimestampType(): TimestampType | undefined { return this.timestampType; } public getFullRange(): TimeRange { if (!this.hasTimestamps()) { - throw Error("Trying to get full range when there are no timestamps"); + throw Error('Trying to get full range when there are no timestamps'); } return { from: this.getFirstTimestamp()!, - to: this.getLastTimestamp()! + to: this.getLastTimestamp()!, }; } @@ -123,15 +122,15 @@ export class TimelineData { this.explicitlySetSelection = selection; } - public getTimelines(): Map { + public getTimelines(): Map { return this.timelines; } - public getScreenRecordingVideo(): Blob|undefined { + public getScreenRecordingVideo(): Blob | undefined { return this.screenRecordingVideo; } - public searchCorrespondingScreenRecordingTimeSeconds(timestamp: Timestamp): number|undefined { + public searchCorrespondingScreenRecordingTimeSeconds(timestamp: Timestamp): number | undefined { const timestamps = this.timelines.get(TraceType.SCREEN_RECORDING); if (!timestamps) { return undefined; @@ -139,7 +138,10 @@ export class TimelineData { const firstTimestamp = timestamps[0]; - const correspondingTimestamp = this.searchCorrespondingTimestampFor(TraceType.SCREEN_RECORDING, timestamp)?.timestamp; + const correspondingTimestamp = this.searchCorrespondingTimestampFor( + TraceType.SCREEN_RECORDING, + timestamp + )?.timestamp; if (correspondingTimestamp === undefined) { return undefined; } @@ -148,25 +150,29 @@ export class TimelineData { } public hasTimestamps(): boolean { - return Array.from(this.timelines.values()).some(timestamps => timestamps.length > 0); + return Array.from(this.timelines.values()).some((timestamps) => timestamps.length > 0); } public hasMoreThanOneDistinctTimestamp(): boolean { return this.hasTimestamps() && this.getFirstTimestamp() !== this.getLastTimestamp(); } - public getCurrentTimestampFor(type: TraceType): Timestamp|undefined { + public getCurrentTimestampFor(type: TraceType): Timestamp | undefined { return this.searchCorrespondingTimestampFor(type, this.getCurrentTimestamp())?.timestamp; } - public getPreviousTimestampFor(type: TraceType): Timestamp|undefined { - const currentIndex = - this.searchCorrespondingTimestampFor(type, this.getCurrentTimestamp())?.index; + public getPreviousTimestampFor(type: TraceType): Timestamp | undefined { + const currentIndex = this.searchCorrespondingTimestampFor( + type, + this.getCurrentTimestamp() + )?.index; if (currentIndex === undefined) { // Only acceptable reason for this to be undefined is if we are before the first entry for this type - if (this.timelines.get(type)!.length === 0 || - this.getCurrentTimestamp()!.getValueNs() < this.timelines.get(type)![0].getValueNs()) { + if ( + this.timelines.get(type)!.length === 0 || + this.getCurrentTimestamp()!.getValueNs() < this.timelines.get(type)![0].getValueNs() + ) { return undefined; } throw Error(`Missing active timestamp for trace type ${type}`); @@ -180,7 +186,7 @@ export class TimelineData { return this.timelines.get(type)?.[previousIndex]; } - public getNextTimestampFor(type: TraceType): Timestamp|undefined { + public getNextTimestampFor(type: TraceType): Timestamp | undefined { const currentIndex = this.searchCorrespondingTimestampFor(type, this.getCurrentTimestamp())?.index ?? -1; @@ -190,7 +196,7 @@ export class TimelineData { const timestamps = this.timelines.get(type); if (timestamps === undefined) { - throw Error("Timestamps for tracetype not found"); + throw Error('Timestamps for tracetype not found'); } const nextIndex = currentIndex + 1; if (nextIndex >= timestamps.length) { @@ -225,36 +231,38 @@ export class TimelineData { }); } - private getFirstTimestamp(): Timestamp|undefined { + private getFirstTimestamp(): Timestamp | undefined { if (!this.hasTimestamps()) { return undefined; } return Array.from(this.timelines.values()) - .map(timestamps => timestamps[0]) - .filter(timestamp => timestamp !== undefined) - .reduce((prev, current) => prev < current ? prev : current); + .map((timestamps) => timestamps[0]) + .filter((timestamp) => timestamp !== undefined) + .reduce((prev, current) => (prev < current ? prev : current)); } - private getLastTimestamp(): Timestamp|undefined { + private getLastTimestamp(): Timestamp | undefined { if (!this.hasTimestamps()) { return undefined; } return Array.from(this.timelines.values()) - .map(timestamps => timestamps[timestamps.length-1]) - .filter(timestamp => timestamp !== undefined) - .reduce((prev, current) => prev > current ? prev : current); + .map((timestamps) => timestamps[timestamps.length - 1]) + .filter((timestamp) => timestamp !== undefined) + .reduce((prev, current) => (prev > current ? prev : current)); } - private searchCorrespondingTimestampFor(type: TraceType, timestamp: Timestamp|undefined): - TimestampWithIndex|undefined { + private searchCorrespondingTimestampFor( + type: TraceType, + timestamp: Timestamp | undefined + ): TimestampWithIndex | undefined { if (timestamp === undefined) { return undefined; } if (timestamp.getType() !== this.timestampType) { - throw Error("Invalid timestamp type"); + throw Error('Invalid timestamp type'); } const timeline = this.timelines.get(type); @@ -265,17 +273,17 @@ export class TimelineData { if (index === undefined) { return undefined; } - return { index, timestamp: timeline[index] }; + return {index, timestamp: timeline[index]}; } - private getFirstTimestampOfActiveViewTraces(): Timestamp|undefined { + private getFirstTimestampOfActiveViewTraces(): Timestamp | undefined { if (this.activeViewTraceTypes.length === 0) { return undefined; } const activeTimestamps = this.activeViewTraceTypes - .map(traceType => this.timelines.get(traceType)!) - .map(timestamps => timestamps[0]) - .filter(timestamp => timestamp !== undefined) + .map((traceType) => this.timelines.get(traceType)!) + .map((timestamps) => timestamps[0]) + .filter((timestamp) => timestamp !== undefined) .sort(TimeUtils.compareFn); if (activeTimestamps.length === 0) { return undefined; diff --git a/tools/winscope-ng/src/app/trace_data.spec.ts b/tools/winscope-ng/src/app/trace_data.spec.ts index 58e071383..6e4b67165 100644 --- a/tools/winscope-ng/src/app/trace_data.spec.ts +++ b/tools/winscope-ng/src/app/trace_data.spec.ts @@ -13,28 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {TraceData} from "./trace_data"; -import {UnitTestUtils} from "test/unit/utils"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {TraceData} from './trace_data'; -describe("TraceData", () => { +describe('TraceData', () => { let traceData: TraceData; beforeEach(async () => { traceData = new TraceData(); }); - it("can load valid trace files", async () => { + it('can load valid trace files', async () => { expect(traceData.getLoadedTraces().length).toEqual(0); await loadValidSfWmTraces(); expect(traceData.getLoadedTraces().length).toEqual(2); }); - it("is robust to invalid trace files", async () => { + it('is robust to invalid trace files', async () => { const invalidTraceFiles = [ - new TraceFile(await UnitTestUtils.getFixtureFile("winscope_homepage.png")) + new TraceFile(await UnitTestUtils.getFixtureFile('winscope_homepage.png')), ]; const errors = await traceData.loadTraces(invalidTraceFiles); @@ -42,22 +42,20 @@ describe("TraceData", () => { expect(traceData.getLoadedTraces().length).toEqual(0); }); - it("is robust to mixed valid and invalid trace files", async () => { + it('is robust to mixed valid and invalid trace files', async () => { expect(traceData.getLoadedTraces().length).toEqual(0); const traces = [ - new TraceFile(await UnitTestUtils.getFixtureFile("winscope_homepage.png")), - new TraceFile(await UnitTestUtils.getFixtureFile("traces/dump_WindowManager.pb")) + new TraceFile(await UnitTestUtils.getFixtureFile('winscope_homepage.png')), + new TraceFile(await UnitTestUtils.getFixtureFile('traces/dump_WindowManager.pb')), ]; const errors = await traceData.loadTraces(traces); expect(traceData.getLoadedTraces().length).toEqual(1); expect(errors.length).toEqual(1); }); - it("is robust to trace files with no entries", async () => { + it('is robust to trace files with no entries', async () => { const traceFilesWithNoEntries = [ - new TraceFile( - await UnitTestUtils.getFixtureFile("traces/no_entries_InputMethodClients.pb") - ) + new TraceFile(await UnitTestUtils.getFixtureFile('traces/no_entries_InputMethodClients.pb')), ]; const errors = await traceData.loadTraces(traceFilesWithNoEntries); @@ -71,7 +69,7 @@ describe("TraceData", () => { expect(timelines[0].timestamps).toEqual([]); }); - it("can remove traces", async () => { + it('can remove traces', async () => { await loadValidSfWmTraces(); expect(traceData.getLoadedTraces().length).toEqual(2); @@ -82,24 +80,26 @@ describe("TraceData", () => { expect(traceData.getLoadedTraces().length).toEqual(0); }); - it("gets loaded traces", async () => { + it('gets loaded traces', async () => { await loadValidSfWmTraces(); const traces = traceData.getLoadedTraces(); expect(traces.length).toEqual(2); expect(traces[0].traceFile.file).toBeTruthy(); - const actualTraceTypes = new Set(traces.map(trace => trace.type)); + const actualTraceTypes = new Set(traces.map((trace) => trace.type)); const expectedTraceTypes = new Set([TraceType.SURFACE_FLINGER, TraceType.WINDOW_MANAGER]); expect(actualTraceTypes).toEqual(expectedTraceTypes); }); - it("gets trace entries for a given timestamp", async () => { + it('gets trace entries for a given timestamp', async () => { const traceFiles = [ - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/SurfaceFlinger.pb")), - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/WindowManager.pb")) + new TraceFile( + await UnitTestUtils.getFixtureFile('traces/elapsed_and_real_timestamp/SurfaceFlinger.pb') + ), + new TraceFile( + await UnitTestUtils.getFixtureFile('traces/elapsed_and_real_timestamp/WindowManager.pb') + ), ]; const errors = await traceData.loadTraces(traceFiles); @@ -124,26 +124,29 @@ describe("TraceData", () => { } }); - it("gets timelines", async () => { + it('gets timelines', async () => { await loadValidSfWmTraces(); const timelines = traceData.getTimelines(); - const actualTraceTypes = new Set(timelines.map(timeline => timeline.traceType)); + const actualTraceTypes = new Set(timelines.map((timeline) => timeline.traceType)); const expectedTraceTypes = new Set([TraceType.SURFACE_FLINGER, TraceType.WINDOW_MANAGER]); expect(actualTraceTypes).toEqual(expectedTraceTypes); - timelines.forEach(timeline => { + timelines.forEach((timeline) => { expect(timeline.timestamps.length).toBeGreaterThan(0); }); }); - it("gets screenrecording data", async () => { + it('gets screenrecording data', async () => { expect(traceData.getScreenRecordingVideo()).toBeUndefined(); const traceFiles = [ - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4")) + new TraceFile( + await UnitTestUtils.getFixtureFile( + 'traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4' + ) + ), ]; await traceData.loadTraces(traceFiles); @@ -152,7 +155,7 @@ describe("TraceData", () => { expect(video!.size).toBeGreaterThan(0); }); - it("can be cleared", async () => { + it('can be cleared', async () => { await loadValidSfWmTraces(); expect(traceData.getLoadedTraces().length).toBeGreaterThan(0); expect(traceData.getTimelines().length).toBeGreaterThan(0); @@ -164,10 +167,12 @@ describe("TraceData", () => { const loadValidSfWmTraces = async () => { const traceFiles = [ - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/SurfaceFlinger.pb")), - new TraceFile(await UnitTestUtils.getFixtureFile( - "traces/elapsed_and_real_timestamp/WindowManager.pb")), + new TraceFile( + await UnitTestUtils.getFixtureFile('traces/elapsed_and_real_timestamp/SurfaceFlinger.pb') + ), + new TraceFile( + await UnitTestUtils.getFixtureFile('traces/elapsed_and_real_timestamp/WindowManager.pb') + ), ]; const errors = await traceData.loadTraces(traceFiles); diff --git a/tools/winscope-ng/src/app/trace_data.ts b/tools/winscope-ng/src/app/trace_data.ts index cdc7ad11a..5654b598f 100644 --- a/tools/winscope-ng/src/app/trace_data.ts +++ b/tools/winscope-ng/src/app/trace_data.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import {ArrayUtils} from "common/utils/array_utils"; -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {Trace, TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {FunctionUtils, OnProgressUpdateType} from "common/utils/function_utils"; -import {Parser} from "parsers/parser"; -import {ParserError, ParserFactory} from "parsers/parser_factory"; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {Trace, TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {ArrayUtils} from 'common/utils/array_utils'; +import {FunctionUtils, OnProgressUpdateType} from 'common/utils/function_utils'; +import {Parser} from 'parsers/parser'; +import {ParserError, ParserFactory} from 'parsers/parser_factory'; interface Timeline { traceType: TraceType; @@ -35,43 +35,47 @@ class TraceData { public async loadTraces( traceFiles: TraceFile[], - onLoadProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING): - Promise { - const [parsers, parserErrors] = - await this.parserFactory.createParsers(traceFiles, onLoadProgressUpdate); + onLoadProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING + ): Promise { + const [parsers, parserErrors] = await this.parserFactory.createParsers( + traceFiles, + onLoadProgressUpdate + ); this.parsers = parsers; return parserErrors; } public removeTrace(type: TraceType) { - this.parsers = this.parsers.filter(parser => parser.getTraceType() !== type); + this.parsers = this.parsers.filter((parser) => parser.getTraceType() !== type); } public getLoadedTraces(): Trace[] { return this.parsers.map((parser: Parser) => parser.getTrace()); } - public getTraceEntries(timestamp: Timestamp|undefined): Map { + public getTraceEntries(timestamp: Timestamp | undefined): Map { const traceEntries: Map = new Map(); if (!timestamp) { return traceEntries; } - this.parsers.forEach(parser => { + this.parsers.forEach((parser) => { const targetTimestamp = timestamp; const entry = parser.getTraceEntry(targetTimestamp); let prevEntry = null; const parserTimestamps = parser.getTimestamps(timestamp.getType()); if (parserTimestamps === undefined) { - throw new Error(`Unexpected timestamp type ${timestamp.getType()}.` - + ` Not supported by parser for trace type: ${parser.getTraceType()}`); + throw new Error( + `Unexpected timestamp type ${timestamp.getType()}.` + + ` Not supported by parser for trace type: ${parser.getTraceType()}` + ); } const index = ArrayUtils.binarySearchLowerOrEqual(parserTimestamps, targetTimestamp); if (index !== undefined && index > 0) { - prevEntry = parser.getTraceEntry(parserTimestamps[index-1]); + prevEntry = parser.getTraceEntry(parserTimestamps[index - 1]); } if (entry !== undefined) { @@ -86,7 +90,7 @@ class TraceData { const timelines = this.parsers.map((parser): Timeline => { const timestamps = parser.getTimestamps(this.getCommonTimestampType()); if (timestamps === undefined) { - throw Error("Failed to get timestamps from parser"); + throw Error('Failed to get timestamps from parser'); } return {traceType: parser.getTraceType(), timestamps: timestamps}; }); @@ -94,9 +98,10 @@ class TraceData { return timelines; } - public getScreenRecordingVideo(): undefined|Blob { - const parser = this.parsers - .find((parser) => parser.getTraceType() === TraceType.SCREEN_RECORDING); + public getScreenRecordingVideo(): undefined | Blob { + const parser = this.parsers.find( + (parser) => parser.getTraceType() === TraceType.SCREEN_RECORDING + ); if (!parser) { return undefined; } @@ -122,13 +127,13 @@ class TraceData { const priorityOrder = [TimestampType.REAL, TimestampType.ELAPSED]; for (const type of priorityOrder) { - if (this.parsers.every(it => it.getTimestamps(type) !== undefined)) { + if (this.parsers.every((it) => it.getTimestamps(type) !== undefined)) { this.commonTimestampType = type; return this.commonTimestampType; } } - throw Error("Failed to find common timestamp type across all traces"); + throw Error('Failed to find common timestamp type across all traces'); } } diff --git a/tools/winscope-ng/src/app/trace_icons.ts b/tools/winscope-ng/src/app/trace_icons.ts index 104c0ff32..fb4ceee38 100644 --- a/tools/winscope-ng/src/app/trace_icons.ts +++ b/tools/winscope-ng/src/app/trace_icons.ts @@ -1,21 +1,21 @@ -import { TraceType } from "common/trace/trace_type"; +import {TraceType} from 'common/trace/trace_type'; -const WINDOW_MANAGER_ICON = "view_compact"; -const SURFACE_FLINGER_ICON = "filter_none"; -const SCREEN_RECORDING_ICON = "videocam"; -const TRANSACTION_ICON = "timeline"; -const WAYLAND_ICON = "filter_none"; -const PROTO_LOG_ICON = "notes"; -const SYSTEM_UI_ICON = "filter_none"; -const LAUNCHER_ICON = "filter_none"; -const IME_ICON = "keyboard"; -const ACCESSIBILITY_ICON = "filter_none"; -const TAG_ICON = "details"; -const TRACE_ERROR_ICON = "warning"; +const WINDOW_MANAGER_ICON = 'view_compact'; +const SURFACE_FLINGER_ICON = 'filter_none'; +const SCREEN_RECORDING_ICON = 'videocam'; +const TRANSACTION_ICON = 'timeline'; +const WAYLAND_ICON = 'filter_none'; +const PROTO_LOG_ICON = 'notes'; +const SYSTEM_UI_ICON = 'filter_none'; +const LAUNCHER_ICON = 'filter_none'; +const IME_ICON = 'keyboard'; +const ACCESSIBILITY_ICON = 'filter_none'; +const TAG_ICON = 'details'; +const TRACE_ERROR_ICON = 'warning'; type iconMap = { - [key: number]: string; -} + [key: number]: string; +}; export const TRACE_ICONS: iconMap = { [TraceType.ACCESSIBILITY]: ACCESSIBILITY_ICON, diff --git a/tools/winscope-ng/src/app/trace_info.ts b/tools/winscope-ng/src/app/trace_info.ts index 06226cf09..946aacd4b 100644 --- a/tools/winscope-ng/src/app/trace_info.ts +++ b/tools/winscope-ng/src/app/trace_info.ts @@ -14,108 +14,108 @@ * limitations under the License. */ -import { TraceType } from "common/trace/trace_type"; +import {TraceType} from 'common/trace/trace_type'; -const WINDOW_MANAGER_ICON = "web"; -const SURFACE_FLINGER_ICON = "layers"; -const SCREEN_RECORDING_ICON = "videocam"; -const TRANSACTION_ICON = "show_chart"; -const WAYLAND_ICON = "filter_none"; -const PROTO_LOG_ICON = "notes"; -const SYSTEM_UI_ICON = "filter_none"; -const LAUNCHER_ICON = "filter_none"; -const IME_ICON = "keyboard_alt"; -const ACCESSIBILITY_ICON = "accessibility_new"; -const TAG_ICON = "details"; -const TRACE_ERROR_ICON = "warning"; +const WINDOW_MANAGER_ICON = 'web'; +const SURFACE_FLINGER_ICON = 'layers'; +const SCREEN_RECORDING_ICON = 'videocam'; +const TRANSACTION_ICON = 'show_chart'; +const WAYLAND_ICON = 'filter_none'; +const PROTO_LOG_ICON = 'notes'; +const SYSTEM_UI_ICON = 'filter_none'; +const LAUNCHER_ICON = 'filter_none'; +const IME_ICON = 'keyboard_alt'; +const ACCESSIBILITY_ICON = 'accessibility_new'; +const TAG_ICON = 'details'; +const TRACE_ERROR_ICON = 'warning'; type traceInfoMap = { - [key: number]: { - name: string, - icon: string, - color: string, - }; -} + [key: number]: { + name: string; + icon: string; + color: string; + }; +}; export const TRACE_INFO: traceInfoMap = { [TraceType.ACCESSIBILITY]: { - name: "Accessibility", + name: 'Accessibility', icon: ACCESSIBILITY_ICON, - color: "#FF63B8", + color: '#FF63B8', }, [TraceType.WINDOW_MANAGER]: { - name: "Window Manager", + name: 'Window Manager', icon: WINDOW_MANAGER_ICON, - color: "#AF5CF7", + color: '#AF5CF7', }, [TraceType.SURFACE_FLINGER]: { - name: "Surface Flinger", + name: 'Surface Flinger', icon: SURFACE_FLINGER_ICON, - color: "#4ECDE6", + color: '#4ECDE6', }, [TraceType.SCREEN_RECORDING]: { - name: "Screen Recording", + name: 'Screen Recording', icon: SCREEN_RECORDING_ICON, - color: "#8A9CF9", + color: '#8A9CF9', }, [TraceType.TRANSACTIONS]: { - name: "Transactions", + name: 'Transactions', icon: TRANSACTION_ICON, - color: "#5BB974", + color: '#5BB974', }, [TraceType.TRANSACTIONS_LEGACY]: { - name: "Transactions Legacy", + name: 'Transactions Legacy', icon: TRANSACTION_ICON, - color: "#5BB974", + color: '#5BB974', }, [TraceType.WAYLAND]: { - name: "Wayland", + name: 'Wayland', icon: WAYLAND_ICON, - color: "#FDC274", + color: '#FDC274', }, [TraceType.WAYLAND_DUMP]: { - name: "Wayland Dump", + name: 'Wayland Dump', icon: WAYLAND_ICON, - color: "#D01884", + color: '#D01884', }, [TraceType.PROTO_LOG]: { - name: "ProtoLog", + name: 'ProtoLog', icon: PROTO_LOG_ICON, - color: "#40A58A", + color: '#40A58A', }, [TraceType.SYSTEM_UI]: { - name: "System UI", + name: 'System UI', icon: SYSTEM_UI_ICON, - color: "#7A86FF", + color: '#7A86FF', }, [TraceType.LAUNCHER]: { - name: "Launcher", + name: 'Launcher', icon: LAUNCHER_ICON, - color: "#137333", + color: '#137333', }, [TraceType.INPUT_METHOD_CLIENTS]: { - name: "IME Clients", + name: 'IME Clients', icon: IME_ICON, - color: "#FA903E", + color: '#FA903E', }, [TraceType.INPUT_METHOD_SERVICE]: { - name: "IME Service", + name: 'IME Service', icon: IME_ICON, - color: "#F29900", + color: '#F29900', }, [TraceType.INPUT_METHOD_MANAGER_SERVICE]: { - name: "IME Manager Service", + name: 'IME Manager Service', icon: IME_ICON, - color: "#D93025", + color: '#D93025', }, [TraceType.TAG]: { - name: "Tag", + name: 'Tag', icon: TAG_ICON, - color: "#4575B4", + color: '#4575B4', }, [TraceType.ERROR]: { - name: "Error", + name: 'Error', icon: TRACE_ERROR_ICON, - color: "#D73027", + color: '#D73027', }, }; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts b/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts index 3cf05501e..53b558fcc 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts @@ -14,284 +14,308 @@ * limitations under the License. */ +import {ArrayUtils} from 'common/utils/array_utils'; +import {PropertiesDump} from 'viewers/common/ui_tree_utils'; +import intDefMapping from '../../../../../../../prebuilts/misc/common/winscope/intDefMapping.json'; import { - toSize, toActiveBuffer, toColor, toColor3, toPoint, toPointF, toRect, - toRectF, toRegion, toMatrix22, toTransform, toInsets + toActiveBuffer, + toColor, + toColor3, + toInsets, + toMatrix22, + toPoint, + toPointF, + toRect, + toRectF, + toRegion, + toSize, + toTransform, } from './common'; -import {ArrayUtils} from "common/utils/array_utils"; -import { PropertiesDump } from "viewers/common/ui_tree_utils"; -import intDefMapping from - '../../../../../../../prebuilts/misc/common/winscope/intDefMapping.json'; -import config from './Configuration.json' +import config from './Configuration.json'; function readIntdefMap(): Map { - const map = new Map(); - const keys = Object.keys(config.intDefColumn); + const map = new Map(); + const keys = Object.keys(config.intDefColumn); - keys.forEach(key => { - const value = config.intDefColumn[key]; - map.set(key, value); - }); + keys.forEach((key) => { + const value = config.intDefColumn[key]; + map.set(key, value); + }); - return map; + return map; } export default class ObjectFormatter { - static displayDefaults: boolean = false - private static INVALID_ELEMENT_PROPERTIES = config.invalidProperties; + static displayDefaults: boolean = false; + private static INVALID_ELEMENT_PROPERTIES = config.invalidProperties; - private static FLICKER_INTDEF_MAP = readIntdefMap(); + private static FLICKER_INTDEF_MAP = readIntdefMap(); - static cloneObject(entry: any): any { - const obj: any = {} - const properties = ObjectFormatter.getProperties(entry); - properties.forEach(prop => obj[prop] = entry[prop]); - return obj; - } + static cloneObject(entry: any): any { + const obj: any = {}; + const properties = ObjectFormatter.getProperties(entry); + properties.forEach((prop) => (obj[prop] = entry[prop])); + return obj; + } - /** - * Get the true properties of an entry excluding functions, kotlin gernerated - * variables, explicitly excluded properties, and flicker objects already in - * the hierarchy that shouldn't be traversed when formatting the entry - * @param entry The entry for which we want to get the properties for - * @return The "true" properties of the entry as described above - */ - static getProperties(entry: any): string[] { - const props: string[] = []; - let obj = entry; + /** + * Get the true properties of an entry excluding functions, kotlin gernerated + * variables, explicitly excluded properties, and flicker objects already in + * the hierarchy that shouldn't be traversed when formatting the entry + * @param entry The entry for which we want to get the properties for + * @return The "true" properties of the entry as described above + */ + static getProperties(entry: any): string[] { + const props: string[] = []; + let obj = entry; - do { - const properties = Object.getOwnPropertyNames(obj).filter(it => { - // filter out functions - if (typeof (entry[it]) === 'function') return false; - // internal propertires from kotlinJs - if (it.includes(`$`)) return false; - // private kotlin variables from kotlin - if (it.startsWith(`_`)) return false; - // some predefined properties used only internally (e.g., children, ref, diff) - if (this.INVALID_ELEMENT_PROPERTIES.includes(it)) return false; + do { + const properties = Object.getOwnPropertyNames(obj).filter((it) => { + // filter out functions + if (typeof entry[it] === 'function') return false; + // internal propertires from kotlinJs + if (it.includes(`$`)) return false; + // private kotlin variables from kotlin + if (it.startsWith(`_`)) return false; + // some predefined properties used only internally (e.g., children, ref, diff) + if (this.INVALID_ELEMENT_PROPERTIES.includes(it)) return false; - const value = entry[it]; - // only non-empty arrays of non-flicker objects (otherwise they are in hierarchy) - if (Array.isArray(value) && value.length > 0) return !value[0].stableId; - // non-flicker object - return !(value?.stableId); - }); - properties.forEach(function (prop) { - if (typeof (entry[prop]) !== 'function' && props.indexOf(prop) === -1) { - props.push(prop); - } - }); - obj = Object.getPrototypeOf(obj); - } while (obj); - - return props; - } - - /** - * Format a Winscope entry to be displayed in the UI - * Accounts for different user display settings (e.g. hiding empty/default values) - * @param obj The raw object to format - * @return The formatted object - */ - static format(obj: any): PropertiesDump { - const properties = this.getProperties(obj); - const sortedProperties = properties.sort() - - const result: PropertiesDump = {}; - sortedProperties.forEach(entry => { - const key = entry; - const value: any = obj[key]; - - if (value === null || value === undefined) { - if (this.displayDefaults) { - result[key] = value; - } - return - } - - if (value || this.displayDefaults) { - // raw values (e.g., false or 0) - if (!value) { - result[key] = value - // flicker obj - } else if (value.prettyPrint) { - const isEmpty = value.isEmpty === true; - if (!isEmpty || this.displayDefaults) { - result[key] = value.prettyPrint(); - } - } else { - // converted proto to flicker - const translatedObject = this.translateObject(key, value); - if (translatedObject) { - if (translatedObject.prettyPrint) { - result[key] = translatedObject.prettyPrint(); - } - else { - result[key] = translatedObject; - } - // objects - recursive call - } else if (value && typeof (value) == `object`) { - const childObj = this.format(value) as any; - const isEmpty = Object.entries(childObj).length == 0 || childObj.isEmpty; - if (!isEmpty || this.displayDefaults) { - result[key] = childObj; - } - } else { - // values - result[key] = this.translateIntDef(obj, key, value); - } - } - - } - }) - - return result; - } - - /** - * Translate some predetermined proto objects into their flicker equivalent - * - * Returns null if the object cannot be translated - * - * @param obj Object to translate - */ - private static translateObject(key: string, obj: any) { - const type = obj?.$type?.name ?? obj?.constructor?.name; - switch (type) { - case `SizeProto`: return toSize(obj); - case `ActiveBufferProto`: return toActiveBuffer(obj); - case `Color3`: return toColor3(obj); - case `ColorProto`: return toColor(obj); - case `Long`: return obj?.toString(); - case `PointProto`: return toPoint(obj); - case `PositionProto`: return toPointF(obj); - // It is necessary to check for a keyword insets because the proto - // definition of insets and rects uses the same object type - case `RectProto`: return key.toLowerCase().includes("insets") ? toInsets(obj) : toRect(obj); - case `Matrix22`: return toMatrix22(obj); - case `FloatRectProto`: return toRectF(obj); - case `RegionProto`: return toRegion(obj); - case `TransformProto`: return toTransform(obj); - case 'ColorTransformProto': { - const formatted = this.formatColorTransform(obj.val); - return `${formatted}`; - } + const value = entry[it]; + // only non-empty arrays of non-flicker objects (otherwise they are in hierarchy) + if (Array.isArray(value) && value.length > 0) return !value[0].stableId; + // non-flicker object + return !value?.stableId; + }); + properties.forEach(function (prop) { + if (typeof entry[prop] !== 'function' && props.indexOf(prop) === -1) { + props.push(prop); } + }); + obj = Object.getPrototypeOf(obj); + } while (obj); - // Raw long number (no type name, no constructor name, no useful toString() method) - if (ArrayUtils.equal(Object.keys(obj).sort(), ["high_", "low_"])) { - const high = BigInt(obj.high_) << 32n; - let low = BigInt(obj.low_); - if (low < 0) { - low = -low; - } - return (high | low).toString(); + return props; + } + + /** + * Format a Winscope entry to be displayed in the UI + * Accounts for different user display settings (e.g. hiding empty/default values) + * @param obj The raw object to format + * @return The formatted object + */ + static format(obj: any): PropertiesDump { + const properties = this.getProperties(obj); + const sortedProperties = properties.sort(); + + const result: PropertiesDump = {}; + sortedProperties.forEach((entry) => { + const key = entry; + const value: any = obj[key]; + + if (value === null || value === undefined) { + if (this.displayDefaults) { + result[key] = value; } + return; + } - return null; - } - - private static formatColorTransform(vals: any) { - const fixedVals = vals.map((v: any) => v.toFixed(1)); - let formatted = ``; - for (let i = 0; i < fixedVals.length; i += 4) { - formatted += `[`; - formatted += fixedVals.slice(i, i + 4).join(', '); - formatted += `] `; - } - return formatted; - } - - /** - * Obtains from the proto field, the metadata related to the typedef type (if any) - * - * @param obj Proto object - * @param propertyName Property to search - */ - private static getTypeDefSpec(obj: any, propertyName: string): string | null { - const fields = obj?.$type?.fields; - if (!fields) { - return null; - } - - const options = fields[propertyName]?.options; - if (!options) { - return null; - } - - return options["(.android.typedef)"]; - } - - /** - * Translate intdef properties into their string representation - * - * For proto objects check the - * - * @param parentObj Object containing the value to parse - * @param propertyName Property to search - * @param value Property value - */ - private static translateIntDef(parentObj: any, propertyName: string, value: any): string { - const parentClassName = parentObj.constructor.name; - const propertyPath = `${parentClassName}.${propertyName}`; - - let translatedValue: string = value; - // Parse Flicker objects (no intdef annotation supported) - if (this.FLICKER_INTDEF_MAP.has(propertyPath)) { - translatedValue = this.getIntFlagsAsStrings(value, - this.FLICKER_INTDEF_MAP.get(propertyPath)); + if (value || this.displayDefaults) { + // raw values (e.g., false or 0) + if (!value) { + result[key] = value; + // flicker obj + } else if (value.prettyPrint) { + const isEmpty = value.isEmpty === true; + if (!isEmpty || this.displayDefaults) { + result[key] = value.prettyPrint(); + } } else { - // If it's a proto, search on the proto definition for the intdef type - const typeDefSpec = this.getTypeDefSpec(parentObj, propertyName); - if (typeDefSpec) { - translatedValue = this.getIntFlagsAsStrings(value, typeDefSpec); + // converted proto to flicker + const translatedObject = this.translateObject(key, value); + if (translatedObject) { + if (translatedObject.prettyPrint) { + result[key] = translatedObject.prettyPrint(); + } else { + result[key] = translatedObject; } + // objects - recursive call + } else if (value && typeof value == `object`) { + const childObj = this.format(value) as any; + const isEmpty = Object.entries(childObj).length == 0 || childObj.isEmpty; + if (!isEmpty || this.displayDefaults) { + result[key] = childObj; + } + } else { + // values + result[key] = this.translateIntDef(obj, key, value); + } } + } + }); - return translatedValue; + return result; + } + + /** + * Translate some predetermined proto objects into their flicker equivalent + * + * Returns null if the object cannot be translated + * + * @param obj Object to translate + */ + private static translateObject(key: string, obj: any) { + const type = obj?.$type?.name ?? obj?.constructor?.name; + switch (type) { + case `SizeProto`: + return toSize(obj); + case `ActiveBufferProto`: + return toActiveBuffer(obj); + case `Color3`: + return toColor3(obj); + case `ColorProto`: + return toColor(obj); + case `Long`: + return obj?.toString(); + case `PointProto`: + return toPoint(obj); + case `PositionProto`: + return toPointF(obj); + // It is necessary to check for a keyword insets because the proto + // definition of insets and rects uses the same object type + case `RectProto`: + return key.toLowerCase().includes('insets') ? toInsets(obj) : toRect(obj); + case `Matrix22`: + return toMatrix22(obj); + case `FloatRectProto`: + return toRectF(obj); + case `RegionProto`: + return toRegion(obj); + case `TransformProto`: + return toTransform(obj); + case 'ColorTransformProto': { + const formatted = this.formatColorTransform(obj.val); + return `${formatted}`; + } } - /** - * Translate a property from its numerical value into its string representation - * - * @param intFlags Property value - * @param annotationType IntDef type to use - */ - private static getIntFlagsAsStrings(intFlags: any, annotationType: string): string { - const flags = []; - - const mapping = intDefMapping[annotationType].values; - const knownFlagValues = Object.keys(mapping).reverse().map(x => parseInt(x)); - - if (knownFlagValues.length == 0) { - console.warn("No mapping for type", annotationType) - return intFlags + "" - } - - // Will only contain bits that have not been associated with a flag. - const parsedIntFlags = parseInt(intFlags); - let leftOver = parsedIntFlags; - - for (const flagValue of knownFlagValues) { - if (((leftOver & flagValue) && ((intFlags & flagValue) === flagValue)) - || (parsedIntFlags === 0 && flagValue === 0)) { - flags.push(mapping[flagValue]); - - leftOver = leftOver & ~flagValue; - } - } - - if (flags.length === 0) { - console.error('No valid flag mappings found for ', - intFlags, 'of type', annotationType); - } - - if (leftOver) { - // If 0 is a valid flag value that isn't in the intDefMapping - // it will be ignored - flags.push(leftOver); - } - - return flags.join(' | '); + // Raw long number (no type name, no constructor name, no useful toString() method) + if (ArrayUtils.equal(Object.keys(obj).sort(), ['high_', 'low_'])) { + const high = BigInt(obj.high_) << 32n; + let low = BigInt(obj.low_); + if (low < 0) { + low = -low; + } + return (high | low).toString(); } + + return null; + } + + private static formatColorTransform(vals: any) { + const fixedVals = vals.map((v: any) => v.toFixed(1)); + let formatted = ``; + for (let i = 0; i < fixedVals.length; i += 4) { + formatted += `[`; + formatted += fixedVals.slice(i, i + 4).join(', '); + formatted += `] `; + } + return formatted; + } + + /** + * Obtains from the proto field, the metadata related to the typedef type (if any) + * + * @param obj Proto object + * @param propertyName Property to search + */ + private static getTypeDefSpec(obj: any, propertyName: string): string | null { + const fields = obj?.$type?.fields; + if (!fields) { + return null; + } + + const options = fields[propertyName]?.options; + if (!options) { + return null; + } + + return options['(.android.typedef)']; + } + + /** + * Translate intdef properties into their string representation + * + * For proto objects check the + * + * @param parentObj Object containing the value to parse + * @param propertyName Property to search + * @param value Property value + */ + private static translateIntDef(parentObj: any, propertyName: string, value: any): string { + const parentClassName = parentObj.constructor.name; + const propertyPath = `${parentClassName}.${propertyName}`; + + let translatedValue: string = value; + // Parse Flicker objects (no intdef annotation supported) + if (this.FLICKER_INTDEF_MAP.has(propertyPath)) { + translatedValue = this.getIntFlagsAsStrings( + value, + this.FLICKER_INTDEF_MAP.get(propertyPath) + ); + } else { + // If it's a proto, search on the proto definition for the intdef type + const typeDefSpec = this.getTypeDefSpec(parentObj, propertyName); + if (typeDefSpec) { + translatedValue = this.getIntFlagsAsStrings(value, typeDefSpec); + } + } + + return translatedValue; + } + + /** + * Translate a property from its numerical value into its string representation + * + * @param intFlags Property value + * @param annotationType IntDef type to use + */ + private static getIntFlagsAsStrings(intFlags: any, annotationType: string): string { + const flags = []; + + const mapping = intDefMapping[annotationType].values; + const knownFlagValues = Object.keys(mapping) + .reverse() + .map((x) => parseInt(x)); + + if (knownFlagValues.length == 0) { + console.warn('No mapping for type', annotationType); + return intFlags + ''; + } + + // Will only contain bits that have not been associated with a flag. + const parsedIntFlags = parseInt(intFlags); + let leftOver = parsedIntFlags; + + for (const flagValue of knownFlagValues) { + if ( + (leftOver & flagValue && (intFlags & flagValue) === flagValue) || + (parsedIntFlags === 0 && flagValue === 0) + ) { + flags.push(mapping[flagValue]); + + leftOver = leftOver & ~flagValue; + } + } + + if (flags.length === 0) { + console.error('No valid flag mappings found for ', intFlags, 'of type', annotationType); + } + + if (leftOver) { + // If 0 is a valid flag value that isn't in the intDefMapping + // it will be ignored + flags.push(leftOver); + } + + return flags.join(' | '); + } } diff --git a/tools/winscope-ng/src/common/trace/flickerlib/common.js b/tools/winscope-ng/src/common/trace/flickerlib/common.js index f7f6f768d..76ff58a38 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/common.js +++ b/tools/winscope-ng/src/common/trace/flickerlib/common.js @@ -14,82 +14,75 @@ * limitations under the License. */ -import { TimeUtils } from 'common/utils/time_utils'; - // Imports all the compiled common Flicker library classes and exports them // as clean es6 modules rather than having them be commonjs modules // WM -const WindowManagerTrace = require('flicker').com.android.server.wm.traces. - common.windowmanager.WindowManagerTrace; -const WindowManagerState = require('flicker').com.android.server.wm.traces. - common.windowmanager.WindowManagerState; -const WindowManagerTraceEntryBuilder = require('flicker').com.android.server.wm. - traces.common.windowmanager.WindowManagerTraceEntryBuilder; -const Activity = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.Activity; -const Configuration = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.Configuration; -const ConfigurationContainer = require('flicker').com.android.server.wm.traces. - common.windowmanager.windows.ConfigurationContainer; -const DisplayArea = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.DisplayArea; -const DisplayContent = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.DisplayContent; -const DisplayCutout = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.DisplayCutout; -const KeyguardControllerState = require('flicker').com.android.server.wm. - traces.common.windowmanager.windows.KeyguardControllerState; -const RootWindowContainer = require('flicker').com.android.server.wm.traces. - common.windowmanager.windows.RootWindowContainer; -const Task = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.Task; -const TaskFragment = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.TaskFragment; -const WindowConfiguration = require('flicker').com.android.server.wm.traces. - common.windowmanager.windows.WindowConfiguration; -const WindowContainer = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.WindowContainer; -const WindowLayoutParams= require('flicker').com.android.server.wm.traces. - common.windowmanager.windows.WindowLayoutParams; -const WindowManagerPolicy = require('flicker').com.android.server.wm.traces. - common.windowmanager.windows.WindowManagerPolicy; -const WindowState = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.WindowState; -const WindowToken = require('flicker').com.android.server.wm.traces.common. - windowmanager.windows.WindowToken; +const WindowManagerTrace = + require('flicker').com.android.server.wm.traces.common.windowmanager.WindowManagerTrace; +const WindowManagerState = + require('flicker').com.android.server.wm.traces.common.windowmanager.WindowManagerState; +const WindowManagerTraceEntryBuilder = + require('flicker').com.android.server.wm.traces.common.windowmanager + .WindowManagerTraceEntryBuilder; +const Activity = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.Activity; +const Configuration = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.Configuration; +const ConfigurationContainer = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows + .ConfigurationContainer; +const DisplayArea = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.DisplayArea; +const DisplayContent = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.DisplayContent; +const DisplayCutout = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.DisplayCutout; +const KeyguardControllerState = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows + .KeyguardControllerState; +const RootWindowContainer = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.RootWindowContainer; +const Task = require('flicker').com.android.server.wm.traces.common.windowmanager.windows.Task; +const TaskFragment = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.TaskFragment; +const WindowConfiguration = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.WindowConfiguration; +const WindowContainer = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.WindowContainer; +const WindowLayoutParams = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.WindowLayoutParams; +const WindowManagerPolicy = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.WindowManagerPolicy; +const WindowState = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.WindowState; +const WindowToken = + require('flicker').com.android.server.wm.traces.common.windowmanager.windows.WindowToken; // SF -const Layer = require('flicker').com.android.server.wm.traces.common. - layers.Layer; -const LayerProperties = require('flicker').com.android.server.wm.traces.common. - layers.LayerProperties; -const BaseLayerTraceEntry = require('flicker').com.android.server.wm.traces.common. - layers.BaseLayerTraceEntry; -const LayerTraceEntry = require('flicker').com.android.server.wm.traces.common. - layers.LayerTraceEntry; -const LayerTraceEntryBuilder = require('flicker').com.android.server.wm.traces. - common.layers.LayerTraceEntryBuilder; -const LayersTrace = require('flicker').com.android.server.wm.traces.common. - layers.LayersTrace; -const Matrix22 = require('flicker').com.android.server.wm.traces.common - .Matrix22; -const Matrix33 = require('flicker').com.android.server.wm.traces.common - .Matrix33; -const Transform = require('flicker').com.android.server.wm.traces.common. - layers.Transform; -const Display = require('flicker').com.android.server.wm.traces.common. - layers.Display; +const Layer = require('flicker').com.android.server.wm.traces.common.layers.Layer; +const LayerProperties = + require('flicker').com.android.server.wm.traces.common.layers.LayerProperties; +const BaseLayerTraceEntry = + require('flicker').com.android.server.wm.traces.common.layers.BaseLayerTraceEntry; +const LayerTraceEntry = + require('flicker').com.android.server.wm.traces.common.layers.LayerTraceEntry; +const LayerTraceEntryBuilder = + require('flicker').com.android.server.wm.traces.common.layers.LayerTraceEntryBuilder; +const LayersTrace = require('flicker').com.android.server.wm.traces.common.layers.LayersTrace; +const Matrix22 = require('flicker').com.android.server.wm.traces.common.Matrix22; +const Matrix33 = require('flicker').com.android.server.wm.traces.common.Matrix33; +const Transform = require('flicker').com.android.server.wm.traces.common.layers.Transform; +const Display = require('flicker').com.android.server.wm.traces.common.layers.Display; // Common const Size = require('flicker').com.android.server.wm.traces.common.Size; -const ActiveBuffer = require('flicker').com.android.server.wm.traces.common - .ActiveBuffer; +const ActiveBuffer = require('flicker').com.android.server.wm.traces.common.ActiveBuffer; const Color3 = require('flicker').com.android.server.wm.traces.common.Color3; const Color = require('flicker').com.android.server.wm.traces.common.Color; const Insets = require('flicker').com.android.server.wm.traces.common.Insets; -const PlatformConsts = require('flicker').com.android.server.wm.traces.common - .service.PlatformConsts; +const PlatformConsts = + require('flicker').com.android.server.wm.traces.common.service.PlatformConsts; const Point = require('flicker').com.android.server.wm.traces.common.Point; const PointF = require('flicker').com.android.server.wm.traces.common.PointF; const Rect = require('flicker').com.android.server.wm.traces.common.Rect; @@ -202,7 +195,6 @@ function toInsets(proto) { return EMPTY_INSETS; } - function toRect(proto) { if (proto == null) { return EMPTY_RECT; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts b/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts index c9c41e0ea..79d050ad1 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/layers/Layer.ts @@ -14,87 +14,96 @@ * limitations under the License. */ - -import { Layer, LayerProperties, Rect, toActiveBuffer, toColor, toRect, toRectF, toRegion } from "../common" -import { shortenName } from '../mixin' -import Transform from './Transform' +import { + Layer, + LayerProperties, + Rect, + toActiveBuffer, + toColor, + toRect, + toRectF, + toRegion, +} from '../common'; +import {shortenName} from '../mixin'; +import Transform from './Transform'; Layer.fromProto = function (proto: any, excludesCompositionState = false): Layer { - const visibleRegion = toRegion(proto.visibleRegion) - const activeBuffer = toActiveBuffer(proto.activeBuffer) - const bounds = toRectF(proto.bounds) - const color = toColor(proto.color) - const screenBounds = toRectF(proto.screenBounds) - const sourceBounds = toRectF(proto.sourceBounds) - const transform = Transform.fromProto(proto.transform, proto.position) - const bufferTransform = Transform.fromProto(proto.bufferTransform, /* position */ null) - const hwcCrop = toRectF(proto.hwcCrop) - const hwcFrame = toRect(proto.hwcFrame) - const requestedColor = toColor(proto.requestedColor) - const requestedTransform = - Transform.fromProto(proto.requestedTransform, proto.requestedPosition) - const cornerRadiusCrop = toRectF(proto.cornerRadiusCrop) - const inputTransform = - Transform.fromProto(proto.inputWindowInfo ? proto.inputWindowInfo.transform : null) - const inputRegion = - toRegion(proto.inputWindowInfo ? proto.inputWindowInfo.touchableRegion : null) - let crop: Rect - if (proto.crop) { - crop = toRect(proto.crop) - } + const visibleRegion = toRegion(proto.visibleRegion); + const activeBuffer = toActiveBuffer(proto.activeBuffer); + const bounds = toRectF(proto.bounds); + const color = toColor(proto.color); + const screenBounds = toRectF(proto.screenBounds); + const sourceBounds = toRectF(proto.sourceBounds); + const transform = Transform.fromProto(proto.transform, proto.position); + const bufferTransform = Transform.fromProto(proto.bufferTransform, /* position */ null); + const hwcCrop = toRectF(proto.hwcCrop); + const hwcFrame = toRect(proto.hwcFrame); + const requestedColor = toColor(proto.requestedColor); + const requestedTransform = Transform.fromProto(proto.requestedTransform, proto.requestedPosition); + const cornerRadiusCrop = toRectF(proto.cornerRadiusCrop); + const inputTransform = Transform.fromProto( + proto.inputWindowInfo ? proto.inputWindowInfo.transform : null + ); + const inputRegion = toRegion( + proto.inputWindowInfo ? proto.inputWindowInfo.touchableRegion : null + ); + let crop: Rect; + if (proto.crop) { + crop = toRect(proto.crop); + } - const properties = new LayerProperties( - visibleRegion, - activeBuffer, - /* flags */ proto.flags, - bounds, - color, - /* isOpaque */ proto.isOpaque, - /* shadowRadius */ proto.shadowRadius, - /* cornerRadius */ proto.cornerRadius, - /* type */ proto.type ?? ``, - screenBounds, - transform, - sourceBounds, - /* effectiveScalingMode */ proto.effectiveScalingMode, - bufferTransform, - /* hwcCompositionType */ proto.hwcCompositionType, - hwcCrop, - hwcFrame, - /* backgroundBlurRadius */ proto.backgroundBlurRadius, - crop, - /* isRelativeOf */ proto.isRelativeOf, - /* zOrderRelativeOfId */ proto.zOrderRelativeOf, - /* stackId */ proto.layerStack, - requestedTransform, - requestedColor, - cornerRadiusCrop, - inputTransform, - inputRegion, - excludesCompositionState - ); + const properties = new LayerProperties( + visibleRegion, + activeBuffer, + /* flags */ proto.flags, + bounds, + color, + /* isOpaque */ proto.isOpaque, + /* shadowRadius */ proto.shadowRadius, + /* cornerRadius */ proto.cornerRadius, + /* type */ proto.type ?? ``, + screenBounds, + transform, + sourceBounds, + /* effectiveScalingMode */ proto.effectiveScalingMode, + bufferTransform, + /* hwcCompositionType */ proto.hwcCompositionType, + hwcCrop, + hwcFrame, + /* backgroundBlurRadius */ proto.backgroundBlurRadius, + crop, + /* isRelativeOf */ proto.isRelativeOf, + /* zOrderRelativeOfId */ proto.zOrderRelativeOf, + /* stackId */ proto.layerStack, + requestedTransform, + requestedColor, + cornerRadiusCrop, + inputTransform, + inputRegion, + excludesCompositionState + ); - const entry = new Layer( - /* name */ proto.name ?? ``, - /* id */ proto.id, - /*parentId */ proto.parent, - /* z */ proto.z, - /* currFrame */ proto.currFrame, - properties - ); + const entry = new Layer( + /* name */ proto.name ?? ``, + /* id */ proto.id, + /*parentId */ proto.parent, + /* z */ proto.z, + /* currFrame */ proto.currFrame, + properties + ); - addAttributes(entry, proto); - return entry -} + addAttributes(entry, proto); + return entry; +}; function addAttributes(entry: Layer, proto: any) { - entry.kind = `${entry.id}`; - entry.shortName = shortenName(entry.name); - entry.proto = proto; - entry.rect = entry.bounds; - entry.rect.transform = entry.transform; - entry.rect.ref = entry; - entry.rect.label = entry.name; + entry.kind = `${entry.id}`; + entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.rect = entry.bounds; + entry.rect.transform = entry.transform; + entry.rect.ref = entry; + entry.rect.label = entry.name; } export {Layer}; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/layers/LayerTraceEntry.ts b/tools/winscope-ng/src/common/trace/flickerlib/layers/LayerTraceEntry.ts index 1a6d61eab..165bb50df 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/layers/LayerTraceEntry.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/layers/LayerTraceEntry.ts @@ -14,73 +14,79 @@ * limitations under the License. */ -import { Display, LayerTraceEntry, LayerTraceEntryBuilder, toRect, toSize, toTransform } from "../common"; -import {Layer} from "./Layer"; -import {getPropertiesForDisplay} from "../mixin"; -import { TimeUtils } from "common/utils/time_utils"; -import { ElapsedTimestamp, RealTimestamp } from "common/trace/timestamp"; +import {ElapsedTimestamp, RealTimestamp} from 'common/trace/timestamp'; +import {TimeUtils} from 'common/utils/time_utils'; +import { + Display, + LayerTraceEntry, + LayerTraceEntryBuilder, + toRect, + toSize, + toTransform, +} from '../common'; +import {getPropertiesForDisplay} from '../mixin'; +import {Layer} from './Layer'; LayerTraceEntry.fromProto = function ( - protos: object[], - displayProtos: object[], - elapsedTimestamp: bigint, - vSyncId: number, - hwcBlob: string, - where = "", - realToElapsedTimeOffsetNs: bigint|undefined = undefined, - useElapsedTime = false, - excludesCompositionState = false + protos: object[], + displayProtos: object[], + elapsedTimestamp: bigint, + vSyncId: number, + hwcBlob: string, + where = '', + realToElapsedTimeOffsetNs: bigint | undefined = undefined, + useElapsedTime = false, + excludesCompositionState = false ): LayerTraceEntry { - const layers = protos.map(it => Layer.fromProto(it, excludesCompositionState)); - const displays = (displayProtos || []).map(it => newDisplay(it)); - const builder = new LayerTraceEntryBuilder( - `${elapsedTimestamp}`, - layers, - displays, - vSyncId, - hwcBlob, - where, - `${realToElapsedTimeOffsetNs ?? 0}` - ); - const entry: LayerTraceEntry = builder.build(); + const layers = protos.map((it) => Layer.fromProto(it, excludesCompositionState)); + const displays = (displayProtos || []).map((it) => newDisplay(it)); + const builder = new LayerTraceEntryBuilder( + `${elapsedTimestamp}`, + layers, + displays, + vSyncId, + hwcBlob, + where, + `${realToElapsedTimeOffsetNs ?? 0}` + ); + const entry: LayerTraceEntry = builder.build(); - addAttributes(entry, protos, - realToElapsedTimeOffsetNs === undefined || useElapsedTime); - return entry; -} + addAttributes(entry, protos, realToElapsedTimeOffsetNs === undefined || useElapsedTime); + return entry; +}; function addAttributes(entry: LayerTraceEntry, protos: object[], useElapsedTime = false) { - entry.kind = "entry"; - // Avoid parsing the entry root because it is an array of layers - // containing all trace information, this slows down the property tree. - // Instead parse only key properties for debugging - const newObj = getPropertiesForDisplay(entry); - if (newObj.rects) delete newObj.rects; - if (newObj.flattenedLayers) delete newObj.flattenedLayers; - if (newObj.physicalDisplays) delete newObj.physicalDisplays; - if (newObj.physicalDisplayBounds) delete newObj.physicalDisplayBounds; - if (newObj.isVisible) delete newObj.isVisible; - entry.proto = newObj; - if (useElapsedTime || entry.clockTimestamp == undefined) { - entry.name = TimeUtils.format(new ElapsedTimestamp(BigInt(entry.elapsedTimestamp))); - entry.shortName = entry.name; - } else { - entry.name = TimeUtils.format(new RealTimestamp(entry.clockTimestamp)); - entry.shortName = entry.name; - } - entry.isVisible = true; + entry.kind = 'entry'; + // Avoid parsing the entry root because it is an array of layers + // containing all trace information, this slows down the property tree. + // Instead parse only key properties for debugging + const newObj = getPropertiesForDisplay(entry); + if (newObj.rects) delete newObj.rects; + if (newObj.flattenedLayers) delete newObj.flattenedLayers; + if (newObj.physicalDisplays) delete newObj.physicalDisplays; + if (newObj.physicalDisplayBounds) delete newObj.physicalDisplayBounds; + if (newObj.isVisible) delete newObj.isVisible; + entry.proto = newObj; + if (useElapsedTime || entry.clockTimestamp == undefined) { + entry.name = TimeUtils.format(new ElapsedTimestamp(BigInt(entry.elapsedTimestamp))); + entry.shortName = entry.name; + } else { + entry.name = TimeUtils.format(new RealTimestamp(entry.clockTimestamp)); + entry.shortName = entry.name; + } + entry.isVisible = true; } function newDisplay(proto: any): Display { - return new Display( - proto.id, - proto.name, - proto.layerStack, - toSize(proto.size), - toRect(proto.layerStackSpaceRect), - toTransform(proto.transform), - proto.isVirtual - ) + return new Display( + proto.id, + proto.name, + proto.layerStack, + toSize(proto.size), + toRect(proto.layerStackSpaceRect), + toTransform(proto.transform), + proto.isVirtual + ); } export {LayerTraceEntry}; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts b/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts index 654667d0a..ab6e7fb6e 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/layers/Transform.ts @@ -14,77 +14,75 @@ * limitations under the License. */ -import { Transform, Matrix33 } from "../common" +import {Matrix33, Transform} from '../common'; Transform.fromProto = function (transformProto: any, positionProto: any): Transform { - const entry = new Transform( - transformProto?.type ?? 0, - getMatrix(transformProto, positionProto)) + const entry = new Transform(transformProto?.type ?? 0, getMatrix(transformProto, positionProto)); - return entry -} + return entry; +}; function getMatrix(transform: any, position: any): Matrix33 { - const x = position?.x ?? 0 - const y = position?.y ?? 0 + const x = position?.x ?? 0; + const y = position?.y ?? 0; - if (transform == null || isSimpleTransform(transform.type)) { - return getDefaultTransform(transform?.type, x, y) - } + if (transform == null || isSimpleTransform(transform.type)) { + return getDefaultTransform(transform?.type, x, y); + } - return new Matrix33(transform.dsdx, transform.dtdx, x, transform.dsdy, transform.dtdy, y) + return new Matrix33(transform.dsdx, transform.dtdx, x, transform.dsdy, transform.dtdy, y); } function getDefaultTransform(type: number, x: number, y: number): Matrix33 { - // IDENTITY - if (!type) { - return new Matrix33(1, 0, x, 0, 1, y) - } + // IDENTITY + if (!type) { + return new Matrix33(1, 0, x, 0, 1, y); + } - // ROT_270 = ROT_90|FLIP_H|FLIP_V - if (isFlagSet(type, ROT_90_VAL | FLIP_V_VAL | FLIP_H_VAL)) { - return new Matrix33(0, -1, x, 1, 0, y) - } + // ROT_270 = ROT_90|FLIP_H|FLIP_V + if (isFlagSet(type, ROT_90_VAL | FLIP_V_VAL | FLIP_H_VAL)) { + return new Matrix33(0, -1, x, 1, 0, y); + } - // ROT_180 = FLIP_H|FLIP_V - if (isFlagSet(type, FLIP_V_VAL | FLIP_H_VAL)) { - return new Matrix33(-1, 0, x, 0, -1, y) - } + // ROT_180 = FLIP_H|FLIP_V + if (isFlagSet(type, FLIP_V_VAL | FLIP_H_VAL)) { + return new Matrix33(-1, 0, x, 0, -1, y); + } - // ROT_90 - if (isFlagSet(type, ROT_90_VAL)) { - return new Matrix33(0, 1, x, -1, 0, y) - } + // ROT_90 + if (isFlagSet(type, ROT_90_VAL)) { + return new Matrix33(0, 1, x, -1, 0, y); + } - // IDENTITY - if (isFlagClear(type, SCALE_VAL | ROTATE_VAL)) { - return new Matrix33(1, 0, x, 0, 1, y) - } + // IDENTITY + if (isFlagClear(type, SCALE_VAL | ROTATE_VAL)) { + return new Matrix33(1, 0, x, 0, 1, y); + } - throw new Error(`Unknown transform type ${type}`) + throw new Error(`Unknown transform type ${type}`); } export function isFlagSet(type: number, bits: number): Boolean { - type = type || 0; - return (type & bits) === bits; + type = type || 0; + return (type & bits) === bits; } export function isFlagClear(type: number, bits: number): Boolean { - return (type & bits) === 0; + return (type & bits) === 0; } export function isSimpleTransform(type: number): Boolean { - return isFlagClear(type, ROT_INVALID_VAL | SCALE_VAL) + return isFlagClear(type, ROT_INVALID_VAL | SCALE_VAL); } /* transform type flags */ -const ROTATE_VAL = 0x0002 -const SCALE_VAL = 0x0004 +const ROTATE_VAL = 0x0002; +const SCALE_VAL = 0x0004; /* orientation flags */ -const FLIP_H_VAL = 0x0100 // (1 << 0 << 8) -const FLIP_V_VAL = 0x0200 // (1 << 1 << 8) -const ROT_90_VAL = 0x0400 // (1 << 2 << 8) -const ROT_INVALID_VAL = 0x8000 // (0x80 << 8) +const FLIP_H_VAL = 0x0100; // (1 << 0 << 8) +const FLIP_V_VAL = 0x0200; // (1 << 1 << 8) +const ROT_90_VAL = 0x0400; // (1 << 2 << 8) +const ROT_INVALID_VAL = 0x8000; // (0x80 << 8) -export default Transform +export default Transform; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/mixin.ts b/tools/winscope-ng/src/common/trace/flickerlib/mixin.ts index 5625ba1f6..e18d0d71b 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/mixin.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/mixin.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import ObjectFormatter from "./ObjectFormatter" +import ObjectFormatter from './ObjectFormatter'; /** * Get the properties of a WM object for display. @@ -23,39 +23,39 @@ import ObjectFormatter from "./ObjectFormatter" * @param proto Associated proto object */ export function getPropertiesForDisplay(entry: any): any { - if (!entry) { - return - } + if (!entry) { + return; + } - let obj: any = {} - const properties = ObjectFormatter.getProperties(entry) - properties.forEach(prop => obj[prop] = entry[prop]); + let obj: any = {}; + const properties = ObjectFormatter.getProperties(entry); + properties.forEach((prop) => (obj[prop] = entry[prop])); - // we remove the children property from the object to avoid it showing the - // the properties view of the element as we can always see those elements' - // properties by changing the target element in the hierarchy tree view. - if (obj.children) delete obj.children - if (obj.proto) delete obj.proto + // we remove the children property from the object to avoid it showing the + // the properties view of the element as we can always see those elements' + // properties by changing the target element in the hierarchy tree view. + if (obj.children) delete obj.children; + if (obj.proto) delete obj.proto; - obj.proto = Object.assign({}, entry.proto) - if (obj.proto.children) delete obj.proto.children - if (obj.proto.childWindows) delete obj.proto.childWindows - if (obj.proto.childrenWindows) delete obj.proto.childrenWindows - if (obj.proto.childContainers) delete obj.proto.childContainers - if (obj.proto.windowToken) delete obj.proto.windowToken - if (obj.proto.rootDisplayArea) delete obj.proto.rootDisplayArea - if (obj.proto.rootWindowContainer) delete obj.proto.rootWindowContainer - if (obj.proto.windowContainer?.children) delete obj.proto.windowContainer.children - obj = ObjectFormatter.format(obj) + obj.proto = Object.assign({}, entry.proto); + if (obj.proto.children) delete obj.proto.children; + if (obj.proto.childWindows) delete obj.proto.childWindows; + if (obj.proto.childrenWindows) delete obj.proto.childrenWindows; + if (obj.proto.childContainers) delete obj.proto.childContainers; + if (obj.proto.windowToken) delete obj.proto.windowToken; + if (obj.proto.rootDisplayArea) delete obj.proto.rootDisplayArea; + if (obj.proto.rootWindowContainer) delete obj.proto.rootWindowContainer; + if (obj.proto.windowContainer?.children) delete obj.proto.windowContainer.children; + obj = ObjectFormatter.format(obj); - return obj + return obj; } export function shortenName(name: any): string { - const classParts = (name + "").split(".") - if (classParts.length <= 3) { - return name - } - const className = classParts.slice(-1)[0] // last element - return `${classParts[0]}.${classParts[1]}.(...).${className}` + const classParts = (name + '').split('.'); + if (classParts.length <= 3) { + return name; + } + const className = classParts.slice(-1)[0]; // last element + return `${classParts[0]}.${classParts[1]}.(...).${className}`; } diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/Activity.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/Activity.ts index 2a33d65a0..734605775 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/Activity.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/Activity.ts @@ -14,42 +14,42 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { Activity } from "../common" -import WindowContainer from "./WindowContainer" +import {Activity} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; Activity.fromProto = function (proto: any, nextSeq: () => number): Activity { - if (proto == null) { - return null; - } else { - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.windowToken.windowContainer, - /* protoChildren */ proto.windowToken.windowContainer?.children ?? [], - /* isActivityInTree */ true, - /* computedZ */ nextSeq, - /* nameOverride */ null, - /* identifierOverride */ proto.identifier, - ); + if (proto == null) { + return null; + } else { + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.windowToken.windowContainer, + /* protoChildren */ proto.windowToken.windowContainer?.children ?? [], + /* isActivityInTree */ true, + /* computedZ */ nextSeq, + /* nameOverride */ null, + /* identifierOverride */ proto.identifier + ); - const entry = new Activity( - proto.name, - proto.state, - proto.visible, - proto.frontOfTask, - proto.procId, - proto.translucent, - windowContainer - ); + const entry = new Activity( + proto.name, + proto.state, + proto.visible, + proto.frontOfTask, + proto.procId, + proto.translucent, + windowContainer + ); - addAttributes(entry, proto); - return entry; - } -} + addAttributes(entry, proto); + return entry; + } +}; function addAttributes(entry: Activity, proto: any) { - entry.proto = proto; - entry.kind = entry.constructor.name; - entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.kind = entry.constructor.name; + entry.shortName = shortenName(entry.name); } export default Activity; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayArea.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayArea.ts index 22e6f24fc..9ff98c046 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayArea.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayArea.ts @@ -14,33 +14,37 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { DisplayArea } from "../common" -import WindowContainer from "./WindowContainer" +import {DisplayArea} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; -DisplayArea.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): DisplayArea { - if (proto == null) { - return null; - } else { - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.windowContainer, - /* protoChildren */ proto.windowContainer?.children ?? [], - /* isActivityInTree */ isActivityInTree, - /* computedZ */ nextSeq, - /* nameOverride */ proto.name, - ); +DisplayArea.fromProto = function ( + proto: any, + isActivityInTree: Boolean, + nextSeq: () => number +): DisplayArea { + if (proto == null) { + return null; + } else { + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.windowContainer, + /* protoChildren */ proto.windowContainer?.children ?? [], + /* isActivityInTree */ isActivityInTree, + /* computedZ */ nextSeq, + /* nameOverride */ proto.name + ); - const entry = new DisplayArea(proto.isTaskDisplayArea, windowContainer); + const entry = new DisplayArea(proto.isTaskDisplayArea, windowContainer); - addAttributes(entry, proto); - return entry; - } -} + addAttributes(entry, proto); + return entry; + } +}; function addAttributes(entry: DisplayArea, proto: any) { - entry.proto = proto; - entry.kind = entry.constructor.name; - entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.kind = entry.constructor.name; + entry.shortName = shortenName(entry.name); } export default DisplayArea; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayContent.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayContent.ts index efc751919..47a95366c 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayContent.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/DisplayContent.ts @@ -14,74 +14,78 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { toInsets, toRect, DisplayContent, DisplayCutout, PlatformConsts, Rect } from "../common" -import WindowContainer from "./WindowContainer" +import {DisplayContent, DisplayCutout, PlatformConsts, Rect, toInsets, toRect} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; -DisplayContent.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): DisplayContent { - if (proto == null) { - return null; - } else { - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.rootDisplayArea.windowContainer, - /* protoChildren */ proto.rootDisplayArea.windowContainer?.children ?? [], - /* isActivityInTree */ isActivityInTree, - /* computedZ */ nextSeq, - /* nameOverride */ proto.displayInfo?.name ?? null, - ); - const displayRectWidth = proto.displayInfo?.logicalWidth ?? 0; - const displayRectHeight = proto.displayInfo?.logicalHeight ?? 0; - const appRectWidth = proto.displayInfo?.appWidth ?? 0; - const appRectHeight = proto.displayInfo?.appHeight ?? 0; - const defaultBounds = proto.pinnedStackController?.defaultBounds ?? null; - const movementBounds = proto.pinnedStackController?.movementBounds ?? null; +DisplayContent.fromProto = function ( + proto: any, + isActivityInTree: Boolean, + nextSeq: () => number +): DisplayContent { + if (proto == null) { + return null; + } else { + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.rootDisplayArea.windowContainer, + /* protoChildren */ proto.rootDisplayArea.windowContainer?.children ?? [], + /* isActivityInTree */ isActivityInTree, + /* computedZ */ nextSeq, + /* nameOverride */ proto.displayInfo?.name ?? null + ); + const displayRectWidth = proto.displayInfo?.logicalWidth ?? 0; + const displayRectHeight = proto.displayInfo?.logicalHeight ?? 0; + const appRectWidth = proto.displayInfo?.appWidth ?? 0; + const appRectHeight = proto.displayInfo?.appHeight ?? 0; + const defaultBounds = proto.pinnedStackController?.defaultBounds ?? null; + const movementBounds = proto.pinnedStackController?.movementBounds ?? null; - const entry = new DisplayContent( - proto.id, - proto.focusedRootTaskId, - proto.resumedActivity?.title ?? "", - proto.singleTaskInstance, - toRect(defaultBounds), - toRect(movementBounds), - new Rect(0, 0, displayRectWidth, displayRectHeight), - new Rect(0, 0, appRectWidth, appRectHeight), - proto.dpi, - proto.displayInfo?.flags ?? 0, - toRect(proto.displayFrames?.stableBounds), - proto.surfaceSize, - proto.focusedApp, - proto.appTransition?.lastUsedAppTransition ?? "", - proto.appTransition?.appTransitionState ?? "", - PlatformConsts.Rotation.Companion.getByValue(proto.displayRotation?.rotation ?? 0), - proto.displayRotation?.lastOrientation ?? 0, - createDisplayCutout(proto.displayInfo?.cutout), - windowContainer - ); + const entry = new DisplayContent( + proto.id, + proto.focusedRootTaskId, + proto.resumedActivity?.title ?? '', + proto.singleTaskInstance, + toRect(defaultBounds), + toRect(movementBounds), + new Rect(0, 0, displayRectWidth, displayRectHeight), + new Rect(0, 0, appRectWidth, appRectHeight), + proto.dpi, + proto.displayInfo?.flags ?? 0, + toRect(proto.displayFrames?.stableBounds), + proto.surfaceSize, + proto.focusedApp, + proto.appTransition?.lastUsedAppTransition ?? '', + proto.appTransition?.appTransitionState ?? '', + PlatformConsts.Rotation.Companion.getByValue(proto.displayRotation?.rotation ?? 0), + proto.displayRotation?.lastOrientation ?? 0, + createDisplayCutout(proto.displayInfo?.cutout), + windowContainer + ); - addAttributes(entry, proto); - return entry; - } -} + addAttributes(entry, proto); + return entry; + } +}; function createDisplayCutout(proto: any | null): DisplayCutout | null { - if(proto == null) { - return null; - } else { - return new DisplayCutout( - toInsets(proto?.insets), - toRect(proto?.boundLeft), - toRect(proto?.boundTop), - toRect(proto?.boundRight), - toRect(proto?.boundBottom), - toInsets(proto?.waterfallInsets) - ); - } + if (proto == null) { + return null; + } else { + return new DisplayCutout( + toInsets(proto?.insets), + toRect(proto?.boundLeft), + toRect(proto?.boundTop), + toRect(proto?.boundRight), + toRect(proto?.boundBottom), + toInsets(proto?.waterfallInsets) + ); + } } function addAttributes(entry: DisplayContent, proto: any) { - entry.proto = proto; - entry.kind = entry.constructor.name; - entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.kind = entry.constructor.name; + entry.shortName = shortenName(entry.name); } export default DisplayContent; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/Task.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/Task.ts index 2111b5986..5e51bbd71 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/Task.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/Task.ts @@ -14,52 +14,52 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { Task, toRect } from "../common" -import WindowContainer from "./WindowContainer" +import {Task, toRect} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; Task.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): Task { - if (proto == null) { - return null; - } else { - const windowContainerProto = proto.taskFragment?.windowContainer ?? proto.windowContainer; - const windowContainer = WindowContainer.fromProto( - /* proto */ windowContainerProto, - /* protoChildren */ windowContainerProto?.children ?? [], - /* isActivityInTree */ isActivityInTree, - /* computedZ */ nextSeq, - ); + if (proto == null) { + return null; + } else { + const windowContainerProto = proto.taskFragment?.windowContainer ?? proto.windowContainer; + const windowContainer = WindowContainer.fromProto( + /* proto */ windowContainerProto, + /* protoChildren */ windowContainerProto?.children ?? [], + /* isActivityInTree */ isActivityInTree, + /* computedZ */ nextSeq + ); - const entry = new Task( - proto.taskFragment?.activityType ?? proto.activityType, - proto.fillsParent, - toRect(proto.bounds), - proto.id, - proto.rootTaskId, - proto.taskFragment?.displayId, - toRect(proto.lastNonFullscreenBounds), - proto.realActivity, - proto.origActivity, - proto.resizeMode, - proto.resumedActivity?.title ?? "", - proto.animatingBounds, - proto.surfaceWidth, - proto.surfaceHeight, - proto.createdByOrganizer, - proto.taskFragment?.minWidth ?? proto.minWidth, - proto.taskFragment?.minHeight ?? proto.minHeight, - windowContainer - ); + const entry = new Task( + proto.taskFragment?.activityType ?? proto.activityType, + proto.fillsParent, + toRect(proto.bounds), + proto.id, + proto.rootTaskId, + proto.taskFragment?.displayId, + toRect(proto.lastNonFullscreenBounds), + proto.realActivity, + proto.origActivity, + proto.resizeMode, + proto.resumedActivity?.title ?? '', + proto.animatingBounds, + proto.surfaceWidth, + proto.surfaceHeight, + proto.createdByOrganizer, + proto.taskFragment?.minWidth ?? proto.minWidth, + proto.taskFragment?.minHeight ?? proto.minHeight, + windowContainer + ); - addAttributes(entry, proto); - return entry; - } -} + addAttributes(entry, proto); + return entry; + } +}; function addAttributes(entry: Task, proto: any) { - entry.proto = proto; - entry.kind = entry.constructor.name; - entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.kind = entry.constructor.name; + entry.shortName = shortenName(entry.name); } export default Task; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/TaskFragment.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/TaskFragment.ts index 358947b65..507568feb 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/TaskFragment.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/TaskFragment.ts @@ -14,37 +14,41 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { TaskFragment } from "../common" -import WindowContainer from "./WindowContainer" +import {TaskFragment} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; -TaskFragment.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): TaskFragment { - if (proto == null) { - return null; - } else { - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.windowContainer, - /* protoChildren */ proto.windowContainer?.children ?? [], - /* isActivityInTree */ isActivityInTree, - /* computedZ */ nextSeq, - ); - const entry = new TaskFragment( - proto.activityType, - proto.displayId, - proto.minWidth, - proto.minHeight, - windowContainer, - ); +TaskFragment.fromProto = function ( + proto: any, + isActivityInTree: Boolean, + nextSeq: () => number +): TaskFragment { + if (proto == null) { + return null; + } else { + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.windowContainer, + /* protoChildren */ proto.windowContainer?.children ?? [], + /* isActivityInTree */ isActivityInTree, + /* computedZ */ nextSeq + ); + const entry = new TaskFragment( + proto.activityType, + proto.displayId, + proto.minWidth, + proto.minHeight, + windowContainer + ); - addAttributes(entry, proto); - return entry; - } -} + addAttributes(entry, proto); + return entry; + } +}; function addAttributes(entry: TaskFragment, proto: any) { - entry.proto = proto; - entry.kind = entry.constructor.name; - entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.kind = entry.constructor.name; + entry.shortName = shortenName(entry.name); } export default TaskFragment; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts index 8c4e34a2d..d91211164 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowContainer.ts @@ -14,123 +14,137 @@ * limitations under the License. */ -import { shortenName } from '../mixin' +import {shortenName} from '../mixin'; import { - Configuration, - ConfigurationContainer, - toRect, - WindowConfiguration, - WindowContainer - } from "../common" + Configuration, + ConfigurationContainer, + toRect, + WindowConfiguration, + WindowContainer, +} from '../common'; -import Activity from "./Activity" -import DisplayArea from "./DisplayArea" -import DisplayContent from "./DisplayContent" -import Task from "./Task" -import TaskFragment from "./TaskFragment" -import WindowState from "./WindowState" -import WindowToken from "./WindowToken" +import Activity from './Activity'; +import DisplayArea from './DisplayArea'; +import DisplayContent from './DisplayContent'; +import Task from './Task'; +import TaskFragment from './TaskFragment'; +import WindowState from './WindowState'; +import WindowToken from './WindowToken'; WindowContainer.fromProto = function ( - proto: any, - protoChildren: any[], - isActivityInTree: boolean, - nextSeq: () => number, - nameOverride: string|null = null, - identifierOverride: string|null = null, - tokenOverride: any = null, + proto: any, + protoChildren: any[], + isActivityInTree: boolean, + nextSeq: () => number, + nameOverride: string | null = null, + identifierOverride: string | null = null, + tokenOverride: any = null ): WindowContainer { - if (proto == null) { - return null; - } + if (proto == null) { + return null; + } - const containerOrder = nextSeq(); - const children = protoChildren - .filter(it => it != null) - .map(it => WindowContainer.childrenFromProto(it, isActivityInTree, nextSeq)) - .filter(it => it != null); + const containerOrder = nextSeq(); + const children = protoChildren + .filter((it) => it != null) + .map((it) => WindowContainer.childrenFromProto(it, isActivityInTree, nextSeq)) + .filter((it) => it != null); - const identifier: any = identifierOverride ?? proto.identifier; - const name: string = nameOverride ?? identifier?.title ?? ""; - const token: string = tokenOverride?.toString(16) ?? identifier?.hashCode?.toString(16) ?? ""; + const identifier: any = identifierOverride ?? proto.identifier; + const name: string = nameOverride ?? identifier?.title ?? ''; + const token: string = tokenOverride?.toString(16) ?? identifier?.hashCode?.toString(16) ?? ''; - const config = createConfigurationContainer(proto.configurationContainer); - const entry = new WindowContainer( - name, - token, - proto.orientation, - proto.surfaceControl?.layerId ?? 0, - proto.visible, - config, - children, - containerOrder - ); + const config = createConfigurationContainer(proto.configurationContainer); + const entry = new WindowContainer( + name, + token, + proto.orientation, + proto.surfaceControl?.layerId ?? 0, + proto.visible, + config, + children, + containerOrder + ); - addAttributes(entry, proto); - return entry; -} + addAttributes(entry, proto); + return entry; +}; function addAttributes(entry: WindowContainer, proto: any) { - entry.proto = proto; - entry.kind = entry.constructor.name; - entry.shortName = shortenName(entry.name); + entry.proto = proto; + entry.kind = entry.constructor.name; + entry.shortName = shortenName(entry.name); } -type WindowContainerChildType = DisplayContent|DisplayArea|Task|TaskFragment|Activity|WindowToken|WindowState|WindowContainer; +type WindowContainerChildType = + | DisplayContent + | DisplayArea + | Task + | TaskFragment + | Activity + | WindowToken + | WindowState + | WindowContainer; -WindowContainer.childrenFromProto = function(proto: any, isActivityInTree: Boolean, nextSeq: () => number): WindowContainerChildType { - return DisplayContent.fromProto(proto.displayContent, isActivityInTree, nextSeq) ?? - DisplayArea.fromProto(proto.displayArea, isActivityInTree, nextSeq) ?? - Task.fromProto(proto.task, isActivityInTree, nextSeq) ?? - TaskFragment.fromProto(proto.taskFragment, isActivityInTree, nextSeq) ?? - Activity.fromProto(proto.activity, nextSeq) ?? - WindowToken.fromProto(proto.windowToken, isActivityInTree, nextSeq) ?? - WindowState.fromProto(proto.window, isActivityInTree, nextSeq) ?? - WindowContainer.fromProto(proto.windowContainer, nextSeq); -} +WindowContainer.childrenFromProto = function ( + proto: any, + isActivityInTree: Boolean, + nextSeq: () => number +): WindowContainerChildType { + return ( + DisplayContent.fromProto(proto.displayContent, isActivityInTree, nextSeq) ?? + DisplayArea.fromProto(proto.displayArea, isActivityInTree, nextSeq) ?? + Task.fromProto(proto.task, isActivityInTree, nextSeq) ?? + TaskFragment.fromProto(proto.taskFragment, isActivityInTree, nextSeq) ?? + Activity.fromProto(proto.activity, nextSeq) ?? + WindowToken.fromProto(proto.windowToken, isActivityInTree, nextSeq) ?? + WindowState.fromProto(proto.window, isActivityInTree, nextSeq) ?? + WindowContainer.fromProto(proto.windowContainer, nextSeq) + ); +}; function createConfigurationContainer(proto: any): ConfigurationContainer { - const entry = new ConfigurationContainer( - createConfiguration(proto?.overrideConfiguration ?? null), - createConfiguration(proto?.fullConfiguration ?? null), - createConfiguration(proto?.mergedOverrideConfiguration ?? null) - ); + const entry = new ConfigurationContainer( + createConfiguration(proto?.overrideConfiguration ?? null), + createConfiguration(proto?.fullConfiguration ?? null), + createConfiguration(proto?.mergedOverrideConfiguration ?? null) + ); - entry.obj = entry; - return entry; + entry.obj = entry; + return entry; } function createConfiguration(proto: any): Configuration { - if (proto == null) { - return null; - } - let windowConfiguration = null; + if (proto == null) { + return null; + } + let windowConfiguration = null; - if (proto != null && proto.windowConfiguration != null) { - windowConfiguration = createWindowConfiguration(proto.windowConfiguration); - } + if (proto != null && proto.windowConfiguration != null) { + windowConfiguration = createWindowConfiguration(proto.windowConfiguration); + } - return new Configuration( - windowConfiguration, - proto?.densityDpi ?? 0, - proto?.orientation ?? 0, - proto?.screenHeightDp ?? 0, - proto?.screenHeightDp ?? 0, - proto?.smallestScreenWidthDp ?? 0, - proto?.screenLayout ?? 0, - proto?.uiMode ?? 0 - ); + return new Configuration( + windowConfiguration, + proto?.densityDpi ?? 0, + proto?.orientation ?? 0, + proto?.screenHeightDp ?? 0, + proto?.screenHeightDp ?? 0, + proto?.smallestScreenWidthDp ?? 0, + proto?.screenLayout ?? 0, + proto?.uiMode ?? 0 + ); } function createWindowConfiguration(proto: any): WindowConfiguration { - return new WindowConfiguration( - toRect(proto.appBounds), - toRect(proto.bounds), - toRect(proto.maxBounds), - proto.windowingMode, - proto.activityType - ); + return new WindowConfiguration( + toRect(proto.appBounds), + toRect(proto.bounds), + toRect(proto.maxBounds), + proto.windowingMode, + proto.activityType + ); } export default WindowContainer; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts index d2fe02b8d..1fffac8be 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowManagerState.ts @@ -14,120 +14,124 @@ * limitations under the License. */ -import { ElapsedTimestamp, RealTimestamp } from "common/trace/timestamp"; -import { TimeUtils } from "common/utils/time_utils"; +import {ElapsedTimestamp, RealTimestamp} from 'common/trace/timestamp'; +import {TimeUtils} from 'common/utils/time_utils'; import { - KeyguardControllerState, - PlatformConsts, - RootWindowContainer, - WindowManagerPolicy, - WindowManagerState, - WindowManagerTraceEntryBuilder -} from "../common" + KeyguardControllerState, + PlatformConsts, + RootWindowContainer, + WindowManagerPolicy, + WindowManagerState, + WindowManagerTraceEntryBuilder, +} from '../common'; -import WindowContainer from "./WindowContainer" +import WindowContainer from './WindowContainer'; WindowManagerState.fromProto = function ( - proto: any, - elapsedTimestamp: bigint = 0n, - where: string = "", - realToElapsedTimeOffsetNs: bigint|undefined = undefined, - useElapsedTime = false, + proto: any, + elapsedTimestamp: bigint = 0n, + where: string = '', + realToElapsedTimeOffsetNs: bigint | undefined = undefined, + useElapsedTime = false ): WindowManagerState { - const inputMethodWIndowAppToken = ""; - if (proto.inputMethodWindow != null) { - proto.inputMethodWindow.hashCode.toString(16) - } + const inputMethodWIndowAppToken = ''; + if (proto.inputMethodWindow != null) { + proto.inputMethodWindow.hashCode.toString(16); + } - let parseOrder = 0; - const nextSeq = () => ++parseOrder; - const rootWindowContainer = createRootWindowContainer(proto.rootWindowContainer, nextSeq); - const keyguardControllerState = createKeyguardControllerState( - proto.rootWindowContainer.keyguardController); - const policy = createWindowManagerPolicy(proto.policy); + let parseOrder = 0; + const nextSeq = () => ++parseOrder; + const rootWindowContainer = createRootWindowContainer(proto.rootWindowContainer, nextSeq); + const keyguardControllerState = createKeyguardControllerState( + proto.rootWindowContainer.keyguardController + ); + const policy = createWindowManagerPolicy(proto.policy); - const entry = new WindowManagerTraceEntryBuilder( - `${elapsedTimestamp}`, - policy, - proto.focusedApp, - proto.focusedDisplayId, - proto.focusedWindow?.title ?? "", - inputMethodWIndowAppToken, - proto.rootWindowContainer.isHomeRecentsComponent, - proto.displayFrozen, - proto.rootWindowContainer.pendingActivities.map((it: any) => it.title), - rootWindowContainer, - keyguardControllerState, - where, - `${realToElapsedTimeOffsetNs ?? 0}`, - ).build(); + const entry = new WindowManagerTraceEntryBuilder( + `${elapsedTimestamp}`, + policy, + proto.focusedApp, + proto.focusedDisplayId, + proto.focusedWindow?.title ?? '', + inputMethodWIndowAppToken, + proto.rootWindowContainer.isHomeRecentsComponent, + proto.displayFrozen, + proto.rootWindowContainer.pendingActivities.map((it: any) => it.title), + rootWindowContainer, + keyguardControllerState, + where, + `${realToElapsedTimeOffsetNs ?? 0}` + ).build(); - addAttributes(entry, proto, realToElapsedTimeOffsetNs === undefined || useElapsedTime); - return entry -} + addAttributes(entry, proto, realToElapsedTimeOffsetNs === undefined || useElapsedTime); + return entry; +}; function addAttributes(entry: WindowManagerState, proto: any, useElapsedTime = false) { - entry.kind = entry.constructor.name; - if (!entry.isComplete()) { - entry.isIncompleteReason = entry.getIsIncompleteReason(); - } - entry.proto = proto; - if (useElapsedTime || entry.clockTimestamp == undefined) { - entry.name = TimeUtils.format(new ElapsedTimestamp(BigInt(entry.elapsedTimestamp))); - entry.shortName = entry.name; - } else { - entry.name = TimeUtils.format(new RealTimestamp(BigInt(entry.clockTimestamp))); - entry.shortName = entry.name; - } - entry.isVisible = true; + entry.kind = entry.constructor.name; + if (!entry.isComplete()) { + entry.isIncompleteReason = entry.getIsIncompleteReason(); + } + entry.proto = proto; + if (useElapsedTime || entry.clockTimestamp == undefined) { + entry.name = TimeUtils.format(new ElapsedTimestamp(BigInt(entry.elapsedTimestamp))); + entry.shortName = entry.name; + } else { + entry.name = TimeUtils.format(new RealTimestamp(BigInt(entry.clockTimestamp))); + entry.shortName = entry.name; + } + entry.isVisible = true; } function createWindowManagerPolicy(proto: any): WindowManagerPolicy { - return new WindowManagerPolicy( - proto.focusedAppToken ?? "", - proto.forceStatusBar, - proto.forceStatusBarFromKeyguard, - proto.keyguardDrawComplete, - proto.keyguardOccluded, - proto.keyguardOccludedChanged, - proto.keyguardOccludedPending, - proto.lastSystemUiFlags, - proto.orientation, - PlatformConsts.Rotation.Companion.getByValue(proto.rotation), - proto.rotationMode, - proto.screenOnFully, - proto.windowManagerDrawComplete - ); + return new WindowManagerPolicy( + proto.focusedAppToken ?? '', + proto.forceStatusBar, + proto.forceStatusBarFromKeyguard, + proto.keyguardDrawComplete, + proto.keyguardOccluded, + proto.keyguardOccludedChanged, + proto.keyguardOccludedPending, + proto.lastSystemUiFlags, + proto.orientation, + PlatformConsts.Rotation.Companion.getByValue(proto.rotation), + proto.rotationMode, + proto.screenOnFully, + proto.windowManagerDrawComplete + ); } function createRootWindowContainer(proto: any, nextSeq: () => number): RootWindowContainer { - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.windowContainer, - /* childrenProto */ proto.windowContainer?.children ?? [], - /* isActivityInTree */ false, - /* computedZ */ nextSeq - ); + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.windowContainer, + /* childrenProto */ proto.windowContainer?.children ?? [], + /* isActivityInTree */ false, + /* computedZ */ nextSeq + ); - if (windowContainer == null) { - throw new Error(`Window container should not be null.\n${JSON.stringify(proto)}`); - } - const entry = new RootWindowContainer(windowContainer); - return entry; + if (windowContainer == null) { + throw new Error(`Window container should not be null.\n${JSON.stringify(proto)}`); + } + const entry = new RootWindowContainer(windowContainer); + return entry; } function createKeyguardControllerState(proto: any): KeyguardControllerState { - const keyguardOccludedStates: any = {}; + const keyguardOccludedStates: any = {}; - if (proto) { - proto.keyguardOccludedStates.forEach((it: any) => - keyguardOccludedStates[it.displayId] = it.keyguardOccluded); - } - - return new KeyguardControllerState( - proto?.isAodShowing ?? false, - proto?.isKeyguardShowing ?? false, - keyguardOccludedStates + if (proto) { + proto.keyguardOccludedStates.forEach( + (it: any) => + (keyguardOccludedStates[it.displayId] = + it.keyguardOccluded) ); + } + + return new KeyguardControllerState( + proto?.isAodShowing ?? false, + proto?.isKeyguardShowing ?? false, + keyguardOccludedStates + ); } export {WindowManagerState}; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts index 8c626d586..ea5d4b944 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowState.ts @@ -14,123 +14,127 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { toRect, Size, WindowState, WindowLayoutParams } from "../common" -import WindowContainer from "./WindowContainer" +import {Size, toRect, WindowLayoutParams, WindowState} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; - WindowState.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): WindowState { - if (proto == null) { - return null; - } else { - const windowParams = createWindowLayoutParams(proto.attributes); - const identifierName = getIdentifier(proto); - const windowType = getWindowType(proto, identifierName); - const name = getName(identifierName); - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.windowContainer, - /* protoChildren */ proto.windowContainer?.children ?? [], - /* isActivityInTree */ isActivityInTree, - /* computedZ */ nextSeq, - /* nameOverride */ name, - /* identifierOverride */ proto.identifier - ); +WindowState.fromProto = function ( + proto: any, + isActivityInTree: Boolean, + nextSeq: () => number +): WindowState { + if (proto == null) { + return null; + } else { + const windowParams = createWindowLayoutParams(proto.attributes); + const identifierName = getIdentifier(proto); + const windowType = getWindowType(proto, identifierName); + const name = getName(identifierName); + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.windowContainer, + /* protoChildren */ proto.windowContainer?.children ?? [], + /* isActivityInTree */ isActivityInTree, + /* computedZ */ nextSeq, + /* nameOverride */ name, + /* identifierOverride */ proto.identifier + ); - const entry = new WindowState( - windowParams, - proto.displayId, - proto.stackId, - proto.animator?.surface?.layer ?? 0, - proto.animator?.surface?.shown ?? false, - windowType, - new Size(proto.requestedWidth, proto.requestedHeight), - toRect(proto.surfacePosition), - toRect(proto.windowFrames?.frame ?? null), - toRect(proto.windowFrames?.containingFrame ?? null), - toRect(proto.windowFrames?.parentFrame ?? null), - toRect(proto.windowFrames?.contentFrame ?? null), - toRect(proto.windowFrames?.contentInsets ?? null), - toRect(proto.surfaceInsets), - toRect(proto.givenContentInsets), - toRect(proto.animator?.lastClipRect ?? null), - windowContainer, - /* isAppWindow */ isActivityInTree - ); + const entry = new WindowState( + windowParams, + proto.displayId, + proto.stackId, + proto.animator?.surface?.layer ?? 0, + proto.animator?.surface?.shown ?? false, + windowType, + new Size(proto.requestedWidth, proto.requestedHeight), + toRect(proto.surfacePosition), + toRect(proto.windowFrames?.frame ?? null), + toRect(proto.windowFrames?.containingFrame ?? null), + toRect(proto.windowFrames?.parentFrame ?? null), + toRect(proto.windowFrames?.contentFrame ?? null), + toRect(proto.windowFrames?.contentInsets ?? null), + toRect(proto.surfaceInsets), + toRect(proto.givenContentInsets), + toRect(proto.animator?.lastClipRect ?? null), + windowContainer, + /* isAppWindow */ isActivityInTree + ); - addAttributes(entry, proto); - return entry; - } -} + addAttributes(entry, proto); + return entry; + } +}; function createWindowLayoutParams(proto: any): WindowLayoutParams { - return new WindowLayoutParams( - /* type */ proto?.type ?? 0, - /* x */ proto?.x ?? 0, - /* y */ proto?.y ?? 0, - /* width */ proto?.width ?? 0, - /* height */ proto?.height ?? 0, - /* horizontalMargin */ proto?.horizontalMargin ?? 0, - /* verticalMargin */ proto?.verticalMargin ?? 0, - /* gravity */ proto?.gravity ?? 0, - /* softInputMode */ proto?.softInputMode ?? 0, - /* format */ proto?.format ?? 0, - /* windowAnimations */ proto?.windowAnimations ?? 0, - /* alpha */ proto?.alpha ?? 0, - /* screenBrightness */ proto?.screenBrightness ?? 0, - /* buttonBrightness */ proto?.buttonBrightness ?? 0, - /* rotationAnimation */ proto?.rotationAnimation ?? 0, - /* preferredRefreshRate */ proto?.preferredRefreshRate ?? 0, - /* preferredDisplayModeId */ proto?.preferredDisplayModeId ?? 0, - /* hasSystemUiListeners */ proto?.hasSystemUiListeners ?? false, - /* inputFeatureFlags */ proto?.inputFeatureFlags ?? 0, - /* userActivityTimeout */ proto?.userActivityTimeout ?? 0, - /* colorMode */ proto?.colorMode ?? 0, - /* flags */ proto?.flags ?? 0, - /* privateFlags */ proto?.privateFlags ?? 0, - /* systemUiVisibilityFlags */ proto?.systemUiVisibilityFlags ?? 0, - /* subtreeSystemUiVisibilityFlags */ proto?.subtreeSystemUiVisibilityFlags ?? 0, - /* appearance */ proto?.appearance ?? 0, - /* behavior */ proto?.behavior ?? 0, - /* fitInsetsTypes */ proto?.fitInsetsTypes ?? 0, - /* fitInsetsSides */ proto?.fitInsetsSides ?? 0, - /* fitIgnoreVisibility */ proto?.fitIgnoreVisibility ?? false - ) + return new WindowLayoutParams( + /* type */ proto?.type ?? 0, + /* x */ proto?.x ?? 0, + /* y */ proto?.y ?? 0, + /* width */ proto?.width ?? 0, + /* height */ proto?.height ?? 0, + /* horizontalMargin */ proto?.horizontalMargin ?? 0, + /* verticalMargin */ proto?.verticalMargin ?? 0, + /* gravity */ proto?.gravity ?? 0, + /* softInputMode */ proto?.softInputMode ?? 0, + /* format */ proto?.format ?? 0, + /* windowAnimations */ proto?.windowAnimations ?? 0, + /* alpha */ proto?.alpha ?? 0, + /* screenBrightness */ proto?.screenBrightness ?? 0, + /* buttonBrightness */ proto?.buttonBrightness ?? 0, + /* rotationAnimation */ proto?.rotationAnimation ?? 0, + /* preferredRefreshRate */ proto?.preferredRefreshRate ?? 0, + /* preferredDisplayModeId */ proto?.preferredDisplayModeId ?? 0, + /* hasSystemUiListeners */ proto?.hasSystemUiListeners ?? false, + /* inputFeatureFlags */ proto?.inputFeatureFlags ?? 0, + /* userActivityTimeout */ proto?.userActivityTimeout ?? 0, + /* colorMode */ proto?.colorMode ?? 0, + /* flags */ proto?.flags ?? 0, + /* privateFlags */ proto?.privateFlags ?? 0, + /* systemUiVisibilityFlags */ proto?.systemUiVisibilityFlags ?? 0, + /* subtreeSystemUiVisibilityFlags */ proto?.subtreeSystemUiVisibilityFlags ?? 0, + /* appearance */ proto?.appearance ?? 0, + /* behavior */ proto?.behavior ?? 0, + /* fitInsetsTypes */ proto?.fitInsetsTypes ?? 0, + /* fitInsetsSides */ proto?.fitInsetsSides ?? 0, + /* fitIgnoreVisibility */ proto?.fitIgnoreVisibility ?? false + ); } function getWindowType(proto: any, identifierName: string): number { - if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) { - return WindowState.WINDOW_TYPE_STARTING; - } else if (proto.animatingExit) { - return WindowState.WINDOW_TYPE_EXITING; - } else if (identifierName.startsWith(WindowState.DEBUGGER_WINDOW_PREFIX)) { - return WindowState.WINDOW_TYPE_STARTING; - } + if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) { + return WindowState.WINDOW_TYPE_STARTING; + } else if (proto.animatingExit) { + return WindowState.WINDOW_TYPE_EXITING; + } else if (identifierName.startsWith(WindowState.DEBUGGER_WINDOW_PREFIX)) { + return WindowState.WINDOW_TYPE_STARTING; + } - return 0; + return 0; } function getName(identifierName: string): string { - let name = identifierName; + let name = identifierName; - if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) { - name = identifierName.substring(WindowState.STARTING_WINDOW_PREFIX.length); - } else if (identifierName.startsWith(WindowState.DEBUGGER_WINDOW_PREFIX)) { - name = identifierName.substring(WindowState.DEBUGGER_WINDOW_PREFIX.length); - } + if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) { + name = identifierName.substring(WindowState.STARTING_WINDOW_PREFIX.length); + } else if (identifierName.startsWith(WindowState.DEBUGGER_WINDOW_PREFIX)) { + name = identifierName.substring(WindowState.DEBUGGER_WINDOW_PREFIX.length); + } - return name; + return name; } function getIdentifier(proto: any): string { - return proto.windowContainer.identifier?.title ?? proto.identifier?.title ?? ""; + return proto.windowContainer.identifier?.title ?? proto.identifier?.title ?? ''; } function addAttributes(entry: WindowState, proto: any) { - entry.kind = entry.constructor.name; - entry.rect = entry.frame; - entry.rect.ref = entry; - entry.rect.label = entry.name; - entry.proto = proto; - entry.shortName = shortenName(entry.name); + entry.kind = entry.constructor.name; + entry.rect = entry.frame; + entry.rect.ref = entry; + entry.rect.label = entry.name; + entry.proto = proto; + entry.shortName = shortenName(entry.name); } -export default WindowState +export default WindowState; diff --git a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowToken.ts b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowToken.ts index d561783d9..c2c40c986 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowToken.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/windows/WindowToken.ts @@ -14,29 +14,33 @@ * limitations under the License. */ -import { shortenName } from '../mixin' -import { WindowToken } from "../common" -import WindowContainer from "./WindowContainer" +import {WindowToken} from '../common'; +import {shortenName} from '../mixin'; +import WindowContainer from './WindowContainer'; -WindowToken.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): WindowToken { - if (proto == null) { - return null; - } +WindowToken.fromProto = function ( + proto: any, + isActivityInTree: Boolean, + nextSeq: () => number +): WindowToken { + if (proto == null) { + return null; + } - const windowContainer = WindowContainer.fromProto( - /* proto */ proto.windowContainer, - /* protoChildren */ proto.windowContainer?.children ?? [], - /* isActivityInTree */ isActivityInTree, - /* computedZ */ nextSeq, - /* nameOverride */ null, - /* identifierOverride */ null, - /* tokenOverride */ proto.hashCode - ); - const entry = new WindowToken(windowContainer); - entry.kind = entry.constructor.name; - entry.proto = proto; - entry.shortName = shortenName(entry.name); - return entry; -} + const windowContainer = WindowContainer.fromProto( + /* proto */ proto.windowContainer, + /* protoChildren */ proto.windowContainer?.children ?? [], + /* isActivityInTree */ isActivityInTree, + /* computedZ */ nextSeq, + /* nameOverride */ null, + /* identifierOverride */ null, + /* tokenOverride */ proto.hashCode + ); + const entry = new WindowToken(windowContainer); + entry.kind = entry.constructor.name; + entry.proto = proto; + entry.shortName = shortenName(entry.name); + return entry; +}; export default WindowToken; diff --git a/tools/winscope-ng/src/common/trace/protolog.ts b/tools/winscope-ng/src/common/trace/protolog.ts index a701b0f4f..3b916d1da 100644 --- a/tools/winscope-ng/src/common/trace/protolog.ts +++ b/tools/winscope-ng/src/common/trace/protolog.ts @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TimeUtils} from "common/utils/time_utils"; -import configJson from "../../../../../../frameworks/base/data/etc/services.core.protolog.json"; -import { ElapsedTimestamp, RealTimestamp, TimestampType } from "./timestamp"; +import {TimeUtils} from 'common/utils/time_utils'; +import configJson from '../../../../../../frameworks/base/data/etc/services.core.protolog.json'; +import {ElapsedTimestamp, RealTimestamp, TimestampType} from './timestamp'; class ProtoLogTraceEntry { - constructor(public messages: LogMessage[], public currentMessageIndex: number) { - } + constructor(public messages: LogMessage[], public currentMessageIndex: number) {} } class LogMessage { @@ -30,7 +29,14 @@ class LogMessage { at: string; timestamp: bigint; - constructor(text: string, time: string, tag: string, level: string, at: string, timestamp: bigint) { + constructor( + text: string, + time: string, + tag: string, + level: string, + at: string, + timestamp: bigint + ) { this.text = text; this.time = time; this.tag = tag; @@ -41,18 +47,30 @@ class LogMessage { } class FormattedLogMessage extends LogMessage { - constructor(proto: any, timestampType: TimestampType, realToElapsedTimeOffsetNs: bigint|undefined) { - const text = ( + constructor( + proto: any, + timestampType: TimestampType, + realToElapsedTimeOffsetNs: bigint | undefined + ) { + const text = proto.messageHash.toString() + - " - [" + proto.strParams.toString() + - "] [" + proto.sint64Params.toString() + - "] [" + proto.doubleParams.toString() + - "] [" + proto.booleanParams.toString() + "]" - ); + ' - [' + + proto.strParams.toString() + + '] [' + + proto.sint64Params.toString() + + '] [' + + proto.doubleParams.toString() + + '] [' + + proto.booleanParams.toString() + + ']'; let time: string; let timestamp: bigint; - if (timestampType === TimestampType.REAL && realToElapsedTimeOffsetNs !== undefined && realToElapsedTimeOffsetNs != 0n) { + if ( + timestampType === TimestampType.REAL && + realToElapsedTimeOffsetNs !== undefined && + realToElapsedTimeOffsetNs != 0n + ) { timestamp = realToElapsedTimeOffsetNs + BigInt(proto.elapsedRealtimeNanos); time = TimeUtils.format(new RealTimestamp(timestamp)); } else { @@ -60,23 +78,28 @@ class FormattedLogMessage extends LogMessage { time = TimeUtils.format(new ElapsedTimestamp(timestamp)); } - super( - text, - time, - "INVALID", - "invalid", - "", - timestamp); + super(text, time, 'INVALID', 'invalid', '', timestamp); } } class UnformattedLogMessage extends LogMessage { - constructor(proto: any, timestampType: TimestampType, realToElapsedTimeOffsetNs: bigint|undefined, message: any) { + constructor( + proto: any, + timestampType: TimestampType, + realToElapsedTimeOffsetNs: bigint | undefined, + message: any + ) { let time: string; let timestamp: bigint; - if (timestampType === TimestampType.REAL && realToElapsedTimeOffsetNs !== undefined && realToElapsedTimeOffsetNs != 0n) { + if ( + timestampType === TimestampType.REAL && + realToElapsedTimeOffsetNs !== undefined && + realToElapsedTimeOffsetNs != 0n + ) { timestamp = realToElapsedTimeOffsetNs + BigInt(proto.elapsedRealtimeNanos); - time = TimeUtils.format(new RealTimestamp(realToElapsedTimeOffsetNs + BigInt(proto.elapsedRealtimeNanos))); + time = TimeUtils.format( + new RealTimestamp(realToElapsedTimeOffsetNs + BigInt(proto.elapsedRealtimeNanos)) + ); } else { timestamp = BigInt(proto.elapsedRealtimeNanos); time = TimeUtils.format(new ElapsedTimestamp(timestamp)); @@ -94,7 +117,7 @@ class UnformattedLogMessage extends LogMessage { } function formatText(messageFormat: any, data: any) { - let out = ""; + let out = ''; const strParams: string[] = data.strParams; let strParamsIdx = 0; @@ -105,44 +128,43 @@ function formatText(messageFormat: any, data: any) { const booleanParams: number[] = data.booleanParams; let booleanParamsIdx = 0; - for (let i = 0; i < messageFormat.length;) { - if (messageFormat[i] == "%") { + for (let i = 0; i < messageFormat.length; ) { + if (messageFormat[i] == '%') { if (i + 1 >= messageFormat.length) { // Should never happen - protologtool checks for that - throw new Error("Invalid format string"); + throw new Error('Invalid format string'); } switch (messageFormat[i + 1]) { - case "%": - out += "%"; - break; - case "d": - out += getParam(sint64Params, sint64ParamsIdx++).toString(10); - break; - case "o": - out += getParam(sint64Params, sint64ParamsIdx++).toString(8); - break; - case "x": - out += getParam(sint64Params, sint64ParamsIdx++).toString(16); - break; - case "f": - out += getParam(doubleParams, doubleParamsIdx++).toFixed(6); - break; - case "e": - out += getParam(doubleParams, doubleParamsIdx++).toExponential(); - break; - case "g": - out += getParam(doubleParams, doubleParamsIdx++).toString(); - break; - case "s": - out += getParam(strParams, strParamsIdx++); - break; - case "b": - out += getParam(booleanParams, booleanParamsIdx++).toString(); - break; - default: - // Should never happen - protologtool checks for that - throw new Error("Invalid format string conversion: " + - messageFormat[i + 1]); + case '%': + out += '%'; + break; + case 'd': + out += getParam(sint64Params, sint64ParamsIdx++).toString(10); + break; + case 'o': + out += getParam(sint64Params, sint64ParamsIdx++).toString(8); + break; + case 'x': + out += getParam(sint64Params, sint64ParamsIdx++).toString(16); + break; + case 'f': + out += getParam(doubleParams, doubleParamsIdx++).toFixed(6); + break; + case 'e': + out += getParam(doubleParams, doubleParamsIdx++).toExponential(); + break; + case 'g': + out += getParam(doubleParams, doubleParamsIdx++).toString(); + break; + case 's': + out += getParam(strParams, strParamsIdx++); + break; + case 'b': + out += getParam(booleanParams, booleanParamsIdx++).toString(); + break; + default: + // Should never happen - protologtool checks for that + throw new Error('Invalid format string conversion: ' + messageFormat[i + 1]); } i += 2; } else { @@ -155,7 +177,7 @@ function formatText(messageFormat: any, data: any) { function getParam(arr: T[], idx: number): T { if (arr.length <= idx) { - throw new Error("No param for format string conversion"); + throw new Error('No param for format string conversion'); } return arr[idx]; } diff --git a/tools/winscope-ng/src/common/trace/screen_recording.ts b/tools/winscope-ng/src/common/trace/screen_recording.ts index 2bc398069..342ab1ad3 100644 --- a/tools/winscope-ng/src/common/trace/screen_recording.ts +++ b/tools/winscope-ng/src/common/trace/screen_recording.ts @@ -15,9 +15,7 @@ */ class ScreenRecordingTraceEntry { - constructor(public videoTimeSeconds: number, - public videoData: Blob) { - } + constructor(public videoTimeSeconds: number, public videoData: Blob) {} } export {ScreenRecordingTraceEntry}; diff --git a/tools/winscope-ng/src/common/trace/screen_recording_utils.ts b/tools/winscope-ng/src/common/trace/screen_recording_utils.ts index 103e57c3a..c6bb2a924 100644 --- a/tools/winscope-ng/src/common/trace/screen_recording_utils.ts +++ b/tools/winscope-ng/src/common/trace/screen_recording_utils.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {Timestamp} from "./timestamp"; +import {Timestamp} from './timestamp'; class ScreenRecordingUtils { static timestampToVideoTimeSeconds(firstTimestamp: Timestamp, currentTimestamp: Timestamp) { if (firstTimestamp.getType() !== currentTimestamp.getType()) { - throw new Error("Attempted to use timestamps with different type"); + throw new Error('Attempted to use timestamps with different type'); } const videoTimeSeconds = Number(currentTimestamp.getValueNs() - firstTimestamp.getValueNs()) / 1000000000; diff --git a/tools/winscope-ng/src/common/trace/timestamp.spec.ts b/tools/winscope-ng/src/common/trace/timestamp.spec.ts index ef49f70c4..91a8b1a6d 100644 --- a/tools/winscope-ng/src/common/trace/timestamp.spec.ts +++ b/tools/winscope-ng/src/common/trace/timestamp.spec.ts @@ -14,23 +14,23 @@ * limitations under the License. */ -import { Timestamp, TimestampType } from "./timestamp"; +import {Timestamp, TimestampType} from './timestamp'; -describe("Timestamp", () => { - describe("from", () => { - it("throws when missing elapsed timestamp", () => { +describe('Timestamp', () => { + describe('from', () => { + it('throws when missing elapsed timestamp', () => { expect(() => { Timestamp.from(TimestampType.REAL, 100n); }).toThrow(); }); - it("can create real timestamp", () => { + it('can create real timestamp', () => { const timestamp = Timestamp.from(TimestampType.REAL, 100n, 500n); expect(timestamp.getType()).toBe(TimestampType.REAL); expect(timestamp.getValueNs()).toBe(600n); }); - it("can create elapsed timestamp", () => { + it('can create elapsed timestamp', () => { let timestamp = Timestamp.from(TimestampType.ELAPSED, 100n, 500n); expect(timestamp.getType()).toBe(TimestampType.ELAPSED); expect(timestamp.getValueNs()).toBe(100n); @@ -40,4 +40,4 @@ describe("Timestamp", () => { expect(timestamp.getValueNs()).toBe(100n); }); }); -}); \ No newline at end of file +}); diff --git a/tools/winscope-ng/src/common/trace/timestamp.ts b/tools/winscope-ng/src/common/trace/timestamp.ts index 69cde16ee..ee84f2bc4 100644 --- a/tools/winscope-ng/src/common/trace/timestamp.ts +++ b/tools/winscope-ng/src/common/trace/timestamp.ts @@ -15,8 +15,8 @@ */ export enum TimestampType { - ELAPSED = "ELAPSED", - REAL = "REAL", + ELAPSED = 'ELAPSED', + REAL = 'REAL', } export class Timestamp { @@ -25,17 +25,21 @@ export class Timestamp { this.valueNs = valueNs; } - static from(timestampType: TimestampType, elapsedTimestamp: bigint, realToElapsedTimeOffsetNs: bigint | undefined = undefined) { + static from( + timestampType: TimestampType, + elapsedTimestamp: bigint, + realToElapsedTimeOffsetNs: bigint | undefined = undefined + ) { switch (timestampType) { - case TimestampType.REAL: - if (realToElapsedTimeOffsetNs === undefined) { - throw new Error("realToElapsedTimeOffsetNs can't be undefined to use real timestamp"); - } - return new Timestamp(TimestampType.REAL, elapsedTimestamp + realToElapsedTimeOffsetNs); - case TimestampType.ELAPSED: - return new Timestamp(TimestampType.ELAPSED, elapsedTimestamp); - default: - throw new Error("Unhandled timestamp type"); + case TimestampType.REAL: + if (realToElapsedTimeOffsetNs === undefined) { + throw new Error("realToElapsedTimeOffsetNs can't be undefined to use real timestamp"); + } + return new Timestamp(TimestampType.REAL, elapsedTimestamp + realToElapsedTimeOffsetNs); + case TimestampType.ELAPSED: + return new Timestamp(TimestampType.ELAPSED, elapsedTimestamp); + default: + throw new Error('Unhandled timestamp type'); } } diff --git a/tools/winscope-ng/src/common/trace/trace.ts b/tools/winscope-ng/src/common/trace/trace.ts index 19f211395..1f24f254d 100644 --- a/tools/winscope-ng/src/common/trace/trace.ts +++ b/tools/winscope-ng/src/common/trace/trace.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {TraceType} from "./trace_type"; +import {TraceType} from './trace_type'; export interface Trace { type: TraceType; @@ -22,9 +22,5 @@ export interface Trace { } export class TraceFile { - constructor( - public file: File, - public parentArchive?: File - ) { - } + constructor(public file: File, public parentArchive?: File) {} } diff --git a/tools/winscope-ng/src/common/trace/trace_tree_node.ts b/tools/winscope-ng/src/common/trace/trace_tree_node.ts index cd8cefd6d..9116cf480 100644 --- a/tools/winscope-ng/src/common/trace/trace_tree_node.ts +++ b/tools/winscope-ng/src/common/trace/trace_tree_node.ts @@ -26,8 +26,8 @@ export interface TraceTreeNode { inputMethodService?: any; inputMethodManagerService?: any; where?: string; - elapsedRealtimeNanos?: number|bigint; - clockTimeNanos?: number|bigint; + elapsedRealtimeNanos?: number | bigint; + clockTimeNanos?: number | bigint; shortName?: string; type?: string; id?: string | number; diff --git a/tools/winscope-ng/src/common/trace/transactions.ts b/tools/winscope-ng/src/common/trace/transactions.ts index d259c5585..5fe2d2db2 100644 --- a/tools/winscope-ng/src/common/trace/transactions.ts +++ b/tools/winscope-ng/src/common/trace/transactions.ts @@ -14,16 +14,15 @@ * limitations under the License. */ -import { TimestampType } from "./timestamp"; +import {TimestampType} from './timestamp'; class TransactionsTraceEntry { constructor( public entriesProto: any[], public timestampType: TimestampType, - public realToElapsedTimeOffsetNs: bigint|undefined, - public currentEntryIndex: number, - ) { - } + public realToElapsedTimeOffsetNs: bigint | undefined, + public currentEntryIndex: number + ) {} } export {TransactionsTraceEntry}; diff --git a/tools/winscope-ng/src/common/utils/array_utils.spec.ts b/tools/winscope-ng/src/common/utils/array_utils.spec.ts index 634778486..e2bf97729 100644 --- a/tools/winscope-ng/src/common/utils/array_utils.spec.ts +++ b/tools/winscope-ng/src/common/utils/array_utils.spec.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ArrayUtils} from "./array_utils"; +import {ArrayUtils} from './array_utils'; -describe("ArrayUtils", () => { - it("equal", () => { +describe('ArrayUtils', () => { + it('equal', () => { expect(ArrayUtils.equal([], [1])).toBeFalse(); expect(ArrayUtils.equal([1], [])).toBeFalse(); @@ -38,7 +38,7 @@ describe("ArrayUtils", () => { expect(ArrayUtils.equal(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3]))).toBeTrue(); }); - it("searchSubarray", () => { + it('searchSubarray', () => { expect(ArrayUtils.searchSubarray([], [0])).toEqual(undefined); expect(ArrayUtils.searchSubarray([], [])).toEqual(0); expect(ArrayUtils.searchSubarray([0], [])).toEqual(0); @@ -53,10 +53,9 @@ describe("ArrayUtils", () => { expect(ArrayUtils.searchSubarray([0, 1, 2], [1, 2])).toEqual(1); expect(ArrayUtils.searchSubarray([0, 1, 2], [2])).toEqual(2); expect(ArrayUtils.searchSubarray([0, 1, 2], [2, 3])).toEqual(undefined); - }); - it("binarySearchLowerOrEqual", () => { + it('binarySearchLowerOrEqual', () => { // no match expect(ArrayUtils.binarySearchLowerOrEqual([], 5)).toBeUndefined(); expect(ArrayUtils.binarySearchLowerOrEqual([6], 5)).toBeUndefined(); @@ -87,7 +86,7 @@ describe("ArrayUtils", () => { expect(ArrayUtils.binarySearchLowerOrEqual([4, 4, 4, 5, 5, 5, 5, 6], 5)).toEqual(3); }); - it("toUintLittleEndian", () => { + it('toUintLittleEndian', () => { const buffer = new Uint8Array([0, 0, 1, 1]); expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff]), 0, -1)).toEqual(0n); @@ -103,18 +102,28 @@ describe("ArrayUtils", () => { expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x00, 0x01]), 0, 2)).toEqual(256n); expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff]), 0, 2)).toEqual(0xffffn); - expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff]), 0, 4)).toEqual(0xffffffffn); + expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff]), 0, 4)).toEqual( + 0xffffffffn + ); expect( - ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 8)) - .toEqual(0xffffffffffffffffn); + ArrayUtils.toUintLittleEndian( + new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), + 0, + 8 + ) + ).toEqual(0xffffffffffffffffn); expect( - ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 9)) - .toEqual(0xffffffffffffffffffn); + ArrayUtils.toUintLittleEndian( + new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), + 0, + 9 + ) + ).toEqual(0xffffffffffffffffffn); }); - it("toIntLittleEndian", () => { + it('toIntLittleEndian', () => { expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff]), 0, -1)).toEqual(0n); expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff]), 0, 0)).toEqual(0n); @@ -129,35 +138,75 @@ describe("ArrayUtils", () => { expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x80]), 0, 2)).toEqual(-32767n); expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff]), 0, 2)).toEqual(-1n); - expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0x7f]), 0, 4)).toEqual(0x7fffffffn); - expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x80]), 0, 4)).toEqual(-0x80000000n); - expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x80]), 0, 4)).toEqual(-0x7fffffffn); - expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff]), 0, 4)).toEqual(-1n); + expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0x7f]), 0, 4)).toEqual( + 0x7fffffffn + ); + expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x80]), 0, 4)).toEqual( + -0x80000000n + ); + expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x80]), 0, 4)).toEqual( + -0x7fffffffn + ); + expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff]), 0, 4)).toEqual( + -1n + ); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), 0, 8) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), + 0, + 8 + ) ).toEqual(0x7fffffffffffffffn); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 8) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), + 0, + 8 + ) ).toEqual(-0x8000000000000000n); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 8) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), + 0, + 8 + ) ).toEqual(-0x7fffffffffffffffn); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 8) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), + 0, + 8 + ) ).toEqual(-1n); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), 0, 9) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), + 0, + 9 + ) ).toEqual(0x7fffffffffffffffffn); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 9) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), + 0, + 9 + ) ).toEqual(-0x800000000000000000n); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 9) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), + 0, + 9 + ) ).toEqual(-0x7fffffffffffffffffn); expect( - ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 9) + ArrayUtils.toIntLittleEndian( + new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), + 0, + 9 + ) ).toEqual(-1n); }); }); diff --git a/tools/winscope-ng/src/common/utils/array_utils.ts b/tools/winscope-ng/src/common/utils/array_utils.ts index 194aa51dd..c602a17ef 100644 --- a/tools/winscope-ng/src/common/utils/array_utils.ts +++ b/tools/winscope-ng/src/common/utils/array_utils.ts @@ -39,7 +39,10 @@ class ArrayUtils { return true; } - static searchSubarray(array: T[] | TypedArray, subarray: T[] | TypedArray): number|undefined { + static searchSubarray( + array: T[] | TypedArray, + subarray: T[] | TypedArray + ): number | undefined { for (let i = 0; i + subarray.length <= array.length; ++i) { let match = true; @@ -58,7 +61,7 @@ class ArrayUtils { return undefined; } - static binarySearchLowerOrEqual(values: T[] | TypedArray, target: T): number|undefined { + static binarySearchLowerOrEqual(values: T[] | TypedArray, target: T): number | undefined { if (values.length == 0) { return undefined; } @@ -66,9 +69,9 @@ class ArrayUtils { let low = 0; let high = values.length - 1; - let result: number|undefined = undefined; + let result: number | undefined = undefined; - while(low <= high) { + while (low <= high) { const mid = (low + high) >> 1; if (values[mid] < target) { @@ -76,11 +79,9 @@ class ArrayUtils { result = mid; } low = mid + 1; - } - else if (values[mid] > target) { + } else if (values[mid] > target) { high = mid - 1; - } - else { + } else { result = mid; high = mid - 1; } @@ -91,7 +92,7 @@ class ArrayUtils { static toUintLittleEndian(buffer: Uint8Array, start: number, end: number): bigint { let result = 0n; - for (let i = end-1; i >= start; --i) { + for (let i = end - 1; i >= start; --i) { result *= 256n; result += BigInt(buffer[i]); } @@ -99,7 +100,7 @@ class ArrayUtils { } static toIntLittleEndian(buffer: Uint8Array, start: number, end: number): bigint { - const numOfBits = BigInt(Math.max(0, 8 * (end-start))); + const numOfBits = BigInt(Math.max(0, 8 * (end - start))); if (numOfBits <= 0n) { return 0n; } diff --git a/tools/winscope-ng/src/common/utils/file_utils.ts b/tools/winscope-ng/src/common/utils/file_utils.ts index 0a88a269b..3c5ab2546 100644 --- a/tools/winscope-ng/src/common/utils/file_utils.ts +++ b/tools/winscope-ng/src/common/utils/file_utils.ts @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import JSZip from "jszip"; -import {FunctionUtils, OnProgressUpdateType} from "./function_utils"; +import JSZip from 'jszip'; +import {FunctionUtils, OnProgressUpdateType} from './function_utils'; -export type OnFile = (file: File, parentArchive: File|undefined) => void; +export type OnFile = (file: File, parentArchive: File | undefined) => void; class FileUtils { static getFileExtension(file: File) { - const split = file.name.split("."); + const split = file.name.split('.'); if (split.length > 1) { return split.pop(); } @@ -28,8 +28,8 @@ class FileUtils { } static removeDirFromFileName(name: string) { - if (name.includes("/")) { - const startIndex = name.lastIndexOf("/") + 1; + if (name.includes('/')) { + const startIndex = name.lastIndexOf('/') + 1; return name.slice(startIndex); } else { return name; @@ -38,17 +38,18 @@ class FileUtils { static async createZipArchive(files: File[]): Promise { const zip = new JSZip(); - for (let i=0; i < files.length; i++) { + for (let i = 0; i < files.length; i++) { const file = files[i]; const blob = await file.arrayBuffer(); zip.file(file.name, blob); } - return await zip.generateAsync({type: "blob"}); + return await zip.generateAsync({type: 'blob'}); } static async unzipFile( file: File, - onProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING): Promise { + onProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING + ): Promise { const unzippedFiles: File[] = []; const zip = new JSZip(); const content = await zip.loadAsync(file); @@ -61,12 +62,12 @@ class FileUtils { continue; } else { const name = this.removeDirFromFileName(filename); - const fileBlob = await file.async("blob"); + const fileBlob = await file.async('blob'); const unzippedFile = new File([fileBlob], name); unzippedFiles.push(unzippedFile); } - onProgressUpdate(100 * (index + 1) / filenames.length); + onProgressUpdate((100 * (index + 1)) / filenames.length); } return unzippedFiles; @@ -75,19 +76,19 @@ class FileUtils { static async unzipFilesIfNeeded( files: File[], onFile: OnFile, - onProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING) { - for (let i=0; i { - const percentage = 100 * i / files.length - + subPercentage / files.length; + const percentage = (100 * i) / files.length + subPercentage / files.length; onProgressUpdate(percentage); }; if (FileUtils.isZipFile(file)) { const unzippedFile = await FileUtils.unzipFile(file, onSubprogressUpdate); - unzippedFile.forEach(unzippedFile => onFile(unzippedFile, file)); + unzippedFile.forEach((unzippedFile) => onFile(unzippedFile, file)); } else { onFile(file, undefined); } @@ -95,7 +96,7 @@ class FileUtils { } static isZipFile(file: File) { - return this.getFileExtension(file) === "zip"; + return this.getFileExtension(file) === 'zip'; } } diff --git a/tools/winscope-ng/src/common/utils/global_config.ts b/tools/winscope-ng/src/common/utils/global_config.ts index d196feadd..7325b34ea 100644 --- a/tools/winscope-ng/src/common/utils/global_config.ts +++ b/tools/winscope-ng/src/common/utils/global_config.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -export type Schema = Omit; +export type Schema = Omit; class GlobalConfig { - readonly MODE: "DEV"|"PROD" = "PROD" as const; + readonly MODE: 'DEV' | 'PROD' = 'PROD' as const; set(config: Schema) { Object.assign(this, config); diff --git a/tools/winscope-ng/src/common/utils/persistent_store_proxy.spec.ts b/tools/winscope-ng/src/common/utils/persistent_store_proxy.spec.ts index 25b1c8bb5..495f38fb3 100644 --- a/tools/winscope-ng/src/common/utils/persistent_store_proxy.spec.ts +++ b/tools/winscope-ng/src/common/utils/persistent_store_proxy.spec.ts @@ -14,125 +14,125 @@ * limitations under the License. */ -import { MockStorage } from "test/unit/mock_storage"; -import {PersistentStoreProxy, StoreObject} from "./persistent_store_proxy"; +import {MockStorage} from 'test/unit/mock_storage'; +import {PersistentStoreProxy, StoreObject} from './persistent_store_proxy'; -describe("PersistentStoreObject", () => { - it("uses defaults when no store is available", () => { +describe('PersistentStoreObject', () => { + it('uses defaults when no store is available', () => { const mockStorage = new MockStorage(); const defaultValues = { - "key1": "value", - "key2": true + key1: 'value', + key2: true, }; - const storeObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); + const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); - expect(storeObject["key1"]).toBe("value"); - expect(storeObject["key2"]).toBe(true); + expect(storeObject['key1']).toBe('value'); + expect(storeObject['key2']).toBe(true); }); - it("can update properties", () => { + it('can update properties', () => { const mockStorage = new MockStorage(); const defaultValues = { - "key1": "value", - "key2": true + key1: 'value', + key2: true, }; - const storeObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); + const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); - storeObject["key1"] = "someOtherValue"; - storeObject["key2"] = false; - expect(storeObject["key1"]).toBe("someOtherValue"); - expect(storeObject["key2"]).toBe(false); + storeObject['key1'] = 'someOtherValue'; + storeObject['key2'] = false; + expect(storeObject['key1']).toBe('someOtherValue'); + expect(storeObject['key2']).toBe(false); }); - it("uses explicitly set store data", () => { + it('uses explicitly set store data', () => { const mockStorage = new MockStorage(); const defaultValues = { - "key1": "value", - "key2": true + key1: 'value', + key2: true, }; - const storeObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); - storeObject["key1"] = "someOtherValue"; - storeObject["key2"] = false; + const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); + storeObject['key1'] = 'someOtherValue'; + storeObject['key2'] = false; - const newStoreObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); - expect(newStoreObject["key1"]).toBe("someOtherValue"); - expect(newStoreObject["key2"]).toBe(false); + const newStoreObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); + expect(newStoreObject['key1']).toBe('someOtherValue'); + expect(newStoreObject['key2']).toBe(false); }); - it("uses default values if not explicitly set", () => { + it('uses default values if not explicitly set', () => { const mockStorage = new MockStorage(); const defaultValues = { - "key1": "value", - "key2": true + key1: 'value', + key2: true, }; - const storeObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); - expect(storeObject["key1"]).toBe("value"); - expect(storeObject["key2"]).toBe(true); + const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); + expect(storeObject['key1']).toBe('value'); + expect(storeObject['key2']).toBe(true); const newDefaultValues = { - "key1": "someOtherValue", - "key2": false + key1: 'someOtherValue', + key2: false, }; - const newStoreObject = PersistentStoreProxy.new("storeKey", newDefaultValues, mockStorage); - expect(newStoreObject["key1"]).toBe("someOtherValue"); - expect(newStoreObject["key2"]).toBe(false); + const newStoreObject = PersistentStoreProxy.new('storeKey', newDefaultValues, mockStorage); + expect(newStoreObject['key1']).toBe('someOtherValue'); + expect(newStoreObject['key2']).toBe(false); }); it("can't update non leaf configs", () => { const mockStorage = new MockStorage(); const defaultValues: StoreObject = { - "key1": "value", - "key2": { - "key3": true - } + key1: 'value', + key2: { + key3: true, + }, }; - const storeObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); - expect(() => storeObject["key2"] = false).toThrow(); + const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); + expect(() => (storeObject['key2'] = false)).toThrow(); }); - it("can get nested configs", () => { + it('can get nested configs', () => { const mockStorage = new MockStorage(); const defaultValues = { - "key1": "value", - "key2": { - "key3": true - } + key1: 'value', + key2: { + key3: true, + }, }; - const storeObject = PersistentStoreProxy.new("storeKey", defaultValues, mockStorage); - expect(storeObject["key2"]["key3"]).toBe(true); + const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage); + expect(storeObject['key2']['key3']).toBe(true); }); - it("can update schema", () => { + it('can update schema', () => { const mockStorage = new MockStorage(); const schema1 = { - "key1": "value1", - "key2": { - "key3": true - } + key1: 'value1', + key2: { + key3: true, + }, }; - const storeObject1 = PersistentStoreProxy.new("storeKey", schema1, mockStorage); - expect(storeObject1["key1"]).toBe("value1"); - expect(storeObject1["key2"]["key3"]).toBe(true); + const storeObject1 = PersistentStoreProxy.new('storeKey', schema1, mockStorage); + expect(storeObject1['key1']).toBe('value1'); + expect(storeObject1['key2']['key3']).toBe(true); // Change from default value to ensure we update the storage - storeObject1["key1"] = "someOtherValue"; - storeObject1["key2"]["key3"] = false; + storeObject1['key1'] = 'someOtherValue'; + storeObject1['key2']['key3'] = false; const schema2 = { - "key1": { - "key3": "value2" + key1: { + key3: 'value2', }, - "key2": true + key2: true, }; - const storeObject2 = PersistentStoreProxy.new("storeKey", schema2, mockStorage); - expect(storeObject2["key1"]["key3"]).toBe("value2"); - expect(storeObject2["key2"]).toBe(true); + const storeObject2 = PersistentStoreProxy.new('storeKey', schema2, mockStorage); + expect(storeObject2['key1']['key3']).toBe('value2'); + expect(storeObject2['key2']).toBe(true); }); -}); \ No newline at end of file +}); diff --git a/tools/winscope-ng/src/common/utils/persistent_store_proxy.ts b/tools/winscope-ng/src/common/utils/persistent_store_proxy.ts index 34960548a..dc11adc0f 100644 --- a/tools/winscope-ng/src/common/utils/persistent_store_proxy.ts +++ b/tools/winscope-ng/src/common/utils/persistent_store_proxy.ts @@ -14,24 +14,33 @@ * limitations under the License. */ -export type StoreObject = { [key: string|number]: StoreObject|string|boolean|undefined } | StoreObject[] | string[] | boolean[] +export type StoreObject = + | {[key: string | number]: StoreObject | string | boolean | undefined} + | StoreObject[] + | string[] + | boolean[]; export class PersistentStoreProxy { public static new(key: string, defaultState: T, storage: Storage): T { - const storedState = JSON.parse(storage.getItem(key) ?? "{}"); + const storedState = JSON.parse(storage.getItem(key) ?? '{}'); const currentState = mergeDeep({}, deepClone(defaultState)); mergeDeepKeepingStructure(currentState, storedState); return wrapWithPersistentStoreProxy(key, currentState, storage); } } -function wrapWithPersistentStoreProxy(storeKey: string, object: T, storage: Storage, baseObject: T = object): T { +function wrapWithPersistentStoreProxy( + storeKey: string, + object: T, + storage: Storage, + baseObject: T = object +): T { const updatableProps: string[] = []; - let key: number|string; + let key: number | string; for (key in object) { const value = object[key]; - if (typeof value === "string" || typeof value === "boolean" || value === undefined) { + if (typeof value === 'string' || typeof value === 'boolean' || value === undefined) { if (!Array.isArray(object)) { updatableProps.push(key); } @@ -42,10 +51,10 @@ function wrapWithPersistentStoreProxy(storeKey: string, o const proxyObj = new Proxy(object, { set: (target, prop, newValue) => { - if (typeof prop === "symbol") { + if (typeof prop === 'symbol') { throw Error("Can't use symbol keys only strings"); } - if (Array.isArray(target) && typeof prop === "number") { + if (Array.isArray(target) && typeof prop === 'number') { target[prop] = newValue; storage.setItem(storeKey, JSON.stringify(baseObject)); return true; @@ -55,15 +64,17 @@ function wrapWithPersistentStoreProxy(storeKey: string, o storage.setItem(storeKey, JSON.stringify(baseObject)); return true; } - throw Error(`Object property '${prop}' is not updatable. Can only update leaf keys: [${updatableProps}]`); - } + throw Error( + `Object property '${prop}' is not updatable. Can only update leaf keys: [${updatableProps}]` + ); + }, }); return proxyObj; } function isObject(item: any): boolean { - return (item && typeof item === "object" && !Array.isArray(item)); + return item && typeof item === 'object' && !Array.isArray(item); } /** @@ -85,7 +96,7 @@ function mergeDeepKeepingStructure(target: any, source: any): any { } if (!isObject(target[key]) && !isObject(source[key])) { - Object.assign(target, { [key]: source[key] }); + Object.assign(target, {[key]: source[key]}); continue; } } @@ -101,10 +112,10 @@ function mergeDeep(target: any, ...sources: any): any { if (isObject(target) && isObject(source)) { for (const key in source) { if (isObject(source[key])) { - if (!target[key]) Object.assign(target, { [key]: {} }); + if (!target[key]) Object.assign(target, {[key]: {}}); mergeDeep(target[key], source[key]); } else { - Object.assign(target, { [key]: source[key] }); + Object.assign(target, {[key]: source[key]}); } } } @@ -114,4 +125,4 @@ function mergeDeep(target: any, ...sources: any): any { function deepClone(obj: StoreObject): StoreObject { return JSON.parse(JSON.stringify(obj)); -} \ No newline at end of file +} diff --git a/tools/winscope-ng/src/common/utils/time_utils.spec.ts b/tools/winscope-ng/src/common/utils/time_utils.spec.ts index 6917ff17b..c2a800444 100644 --- a/tools/winscope-ng/src/common/utils/time_utils.spec.ts +++ b/tools/winscope-ng/src/common/utils/time_utils.spec.ts @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from "common/trace/timestamp"; -import {TimeUtils} from "./time_utils"; +import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TimeUtils} from './time_utils'; -describe("TimeUtils", () => { +describe('TimeUtils', () => { const MILLISECOND = BigInt(1000000); const SECOND = BigInt(1000) * MILLISECOND; const MINUTE = BigInt(60) * SECOND; const HOUR = BigInt(60) * MINUTE; const DAY = BigInt(24) * HOUR; - describe("compareFn", () => { - it("throws if timestamps have different type", () => { + describe('compareFn', () => { + it('throws if timestamps have different type', () => { const real = new RealTimestamp(10n); const elapsed = new ElapsedTimestamp(10n); @@ -33,7 +33,7 @@ describe("TimeUtils", () => { }).toThrow(); }); - it("allows to sort arrays", () => { + it('allows to sort arrays', () => { const array = [ new RealTimestamp(100n), new RealTimestamp(10n), @@ -54,109 +54,146 @@ describe("TimeUtils", () => { }); }); - it("nanosecondsToHuman", () => { - expect(TimeUtils.format(new ElapsedTimestamp(0n), true)) .toEqual("0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(0n), false)) .toEqual("0ns"); - expect(TimeUtils.format(new ElapsedTimestamp(1000n), true)) .toEqual("0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(1000n), false)) .toEqual("1000ns"); - expect(TimeUtils.format(new ElapsedTimestamp(MILLISECOND-1n), true)).toEqual("0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(MILLISECOND), true)).toEqual("1ms"); - expect(TimeUtils.format(new ElapsedTimestamp(10n * MILLISECOND), true)).toEqual("10ms"); + it('nanosecondsToHuman', () => { + expect(TimeUtils.format(new ElapsedTimestamp(0n), true)).toEqual('0ms'); + expect(TimeUtils.format(new ElapsedTimestamp(0n), false)).toEqual('0ns'); + expect(TimeUtils.format(new ElapsedTimestamp(1000n), true)).toEqual('0ms'); + expect(TimeUtils.format(new ElapsedTimestamp(1000n), false)).toEqual('1000ns'); + expect(TimeUtils.format(new ElapsedTimestamp(MILLISECOND - 1n), true)).toEqual('0ms'); + expect(TimeUtils.format(new ElapsedTimestamp(MILLISECOND), true)).toEqual('1ms'); + expect(TimeUtils.format(new ElapsedTimestamp(10n * MILLISECOND), true)).toEqual('10ms'); - expect(TimeUtils.format(new ElapsedTimestamp(SECOND-1n), true)).toEqual("999ms"); - expect(TimeUtils.format(new ElapsedTimestamp(SECOND), true)).toEqual("1s0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(SECOND + MILLISECOND), true)).toEqual("1s1ms"); - expect(TimeUtils.format(new ElapsedTimestamp(SECOND + MILLISECOND), false)).toEqual("1s1ms0ns"); + expect(TimeUtils.format(new ElapsedTimestamp(SECOND - 1n), true)).toEqual('999ms'); + expect(TimeUtils.format(new ElapsedTimestamp(SECOND), true)).toEqual('1s0ms'); + expect(TimeUtils.format(new ElapsedTimestamp(SECOND + MILLISECOND), true)).toEqual('1s1ms'); + expect(TimeUtils.format(new ElapsedTimestamp(SECOND + MILLISECOND), false)).toEqual('1s1ms0ns'); - expect(TimeUtils.format(new ElapsedTimestamp(MINUTE-1n), true)).toEqual("59s999ms"); - expect(TimeUtils.format(new ElapsedTimestamp(MINUTE), true)).toEqual("1m0s0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND), true)).toEqual("1m1s1ms"); - expect(TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND + 1n), true)).toEqual("1m1s1ms"); - expect(TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND + 1n), false)).toEqual("1m1s1ms1ns"); + expect(TimeUtils.format(new ElapsedTimestamp(MINUTE - 1n), true)).toEqual('59s999ms'); + expect(TimeUtils.format(new ElapsedTimestamp(MINUTE), true)).toEqual('1m0s0ms'); + expect(TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND), true)).toEqual( + '1m1s1ms' + ); + expect( + TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND + 1n), true) + ).toEqual('1m1s1ms'); + expect( + TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND + 1n), false) + ).toEqual('1m1s1ms1ns'); - expect(TimeUtils.format(new ElapsedTimestamp(HOUR-1n), true)).toEqual("59m59s999ms"); - expect(TimeUtils.format(new ElapsedTimestamp(HOUR-1n), false)).toEqual("59m59s999ms999999ns"); - expect(TimeUtils.format(new ElapsedTimestamp(HOUR), true)).toEqual("1h0m0s0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(HOUR + MINUTE + SECOND + MILLISECOND), true)).toEqual("1h1m1s1ms"); + expect(TimeUtils.format(new ElapsedTimestamp(HOUR - 1n), true)).toEqual('59m59s999ms'); + expect(TimeUtils.format(new ElapsedTimestamp(HOUR - 1n), false)).toEqual('59m59s999ms999999ns'); + expect(TimeUtils.format(new ElapsedTimestamp(HOUR), true)).toEqual('1h0m0s0ms'); + expect( + TimeUtils.format(new ElapsedTimestamp(HOUR + MINUTE + SECOND + MILLISECOND), true) + ).toEqual('1h1m1s1ms'); - expect(TimeUtils.format(new ElapsedTimestamp(DAY-1n), true)).toEqual("23h59m59s999ms"); - expect(TimeUtils.format(new ElapsedTimestamp(DAY), true)).toEqual("1d0h0m0s0ms"); - expect(TimeUtils.format(new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND), true)).toEqual("1d1h1m1s1ms"); + expect(TimeUtils.format(new ElapsedTimestamp(DAY - 1n), true)).toEqual('23h59m59s999ms'); + expect(TimeUtils.format(new ElapsedTimestamp(DAY), true)).toEqual('1d0h0m0s0ms'); + expect( + TimeUtils.format(new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND), true) + ).toEqual('1d1h1m1s1ms'); }); - it("humanElapsedToNanoseconds", () => { - expect(TimeUtils.parseHumanElapsed("0ns")).toEqual(new ElapsedTimestamp(0n)); - expect(TimeUtils.parseHumanElapsed("1000ns")).toEqual(new ElapsedTimestamp(1000n)); - expect(TimeUtils.parseHumanElapsed("0ms")).toEqual(new ElapsedTimestamp(0n)); - expect(TimeUtils.parseHumanElapsed("1ms")).toEqual(new ElapsedTimestamp(MILLISECOND)); - expect(TimeUtils.parseHumanElapsed("10ms")).toEqual(new ElapsedTimestamp(10n * MILLISECOND)); + it('humanElapsedToNanoseconds', () => { + expect(TimeUtils.parseHumanElapsed('0ns')).toEqual(new ElapsedTimestamp(0n)); + expect(TimeUtils.parseHumanElapsed('1000ns')).toEqual(new ElapsedTimestamp(1000n)); + expect(TimeUtils.parseHumanElapsed('0ms')).toEqual(new ElapsedTimestamp(0n)); + expect(TimeUtils.parseHumanElapsed('1ms')).toEqual(new ElapsedTimestamp(MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('10ms')).toEqual(new ElapsedTimestamp(10n * MILLISECOND)); - expect(TimeUtils.parseHumanElapsed("999ms")).toEqual(new ElapsedTimestamp(999n * MILLISECOND)); - expect(TimeUtils.parseHumanElapsed("1s")).toEqual(new ElapsedTimestamp(SECOND)); - expect(TimeUtils.parseHumanElapsed("1s0ms")).toEqual(new ElapsedTimestamp(SECOND)); - expect(TimeUtils.parseHumanElapsed("1s0ms0ns")).toEqual(new ElapsedTimestamp(SECOND)); - expect(TimeUtils.parseHumanElapsed("1s0ms1ns")).toEqual(new ElapsedTimestamp(SECOND + 1n)); - expect(TimeUtils.parseHumanElapsed("0d1s1ms")).toEqual(new ElapsedTimestamp(SECOND + MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('999ms')).toEqual(new ElapsedTimestamp(999n * MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('1s')).toEqual(new ElapsedTimestamp(SECOND)); + expect(TimeUtils.parseHumanElapsed('1s0ms')).toEqual(new ElapsedTimestamp(SECOND)); + expect(TimeUtils.parseHumanElapsed('1s0ms0ns')).toEqual(new ElapsedTimestamp(SECOND)); + expect(TimeUtils.parseHumanElapsed('1s0ms1ns')).toEqual(new ElapsedTimestamp(SECOND + 1n)); + expect(TimeUtils.parseHumanElapsed('0d1s1ms')).toEqual( + new ElapsedTimestamp(SECOND + MILLISECOND) + ); - expect(TimeUtils.parseHumanElapsed("1m0s0ms")).toEqual(new ElapsedTimestamp(MINUTE)); - expect(TimeUtils.parseHumanElapsed("1m1s1ms")).toEqual(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('1m0s0ms')).toEqual(new ElapsedTimestamp(MINUTE)); + expect(TimeUtils.parseHumanElapsed('1m1s1ms')).toEqual( + new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND) + ); - expect(TimeUtils.parseHumanElapsed("1h0m")).toEqual(new ElapsedTimestamp(HOUR)); - expect(TimeUtils.parseHumanElapsed("1h1m1s1ms")).toEqual(new ElapsedTimestamp(HOUR + MINUTE + SECOND + MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('1h0m')).toEqual(new ElapsedTimestamp(HOUR)); + expect(TimeUtils.parseHumanElapsed('1h1m1s1ms')).toEqual( + new ElapsedTimestamp(HOUR + MINUTE + SECOND + MILLISECOND) + ); - expect(TimeUtils.parseHumanElapsed("1d0s1ms")).toEqual(new ElapsedTimestamp(DAY + MILLISECOND)); - expect(TimeUtils.parseHumanElapsed("1d1h1m1s1ms")).toEqual(new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('1d0s1ms')).toEqual(new ElapsedTimestamp(DAY + MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('1d1h1m1s1ms')).toEqual( + new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND) + ); - expect(TimeUtils.parseHumanElapsed("1d")).toEqual(new ElapsedTimestamp(DAY)); - expect(TimeUtils.parseHumanElapsed("1d1ms")).toEqual(new ElapsedTimestamp(DAY + MILLISECOND)); + expect(TimeUtils.parseHumanElapsed('1d')).toEqual(new ElapsedTimestamp(DAY)); + expect(TimeUtils.parseHumanElapsed('1d1ms')).toEqual(new ElapsedTimestamp(DAY + MILLISECOND)); }); - it("humanToNanoseconds throws on invalid input format", () => { - const invalidFormatError = new Error("Invalid elapsed timestamp format"); - expect(() => TimeUtils.parseHumanElapsed("1d1h1m1s0ns1ms") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanElapsed("1dns") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanElapsed("100") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanElapsed("") ) - .toThrow(invalidFormatError); + it('humanToNanoseconds throws on invalid input format', () => { + const invalidFormatError = new Error('Invalid elapsed timestamp format'); + expect(() => TimeUtils.parseHumanElapsed('1d1h1m1s0ns1ms')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanElapsed('1dns')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanElapsed('100')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanElapsed('')).toThrow(invalidFormatError); }); - it("nanosecondsToHumanReal", () => { + it('nanosecondsToHumanReal', () => { const NOV_10_2022 = 1668038400000n * MILLISECOND; - expect(TimeUtils.format(new RealTimestamp(0n), true)) - .toEqual("1970-01-01T00:00:00.000"); - expect(TimeUtils.format(new RealTimestamp( - NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n), true)) - .toEqual("2022-11-10T22:04:54.186"); - expect(TimeUtils.format(new RealTimestamp(NOV_10_2022), true)) - .toEqual("2022-11-10T00:00:00.000"); - expect(TimeUtils.format(new RealTimestamp(NOV_10_2022 + 1n), true)) - .toEqual("2022-11-10T00:00:00.000"); + expect(TimeUtils.format(new RealTimestamp(0n), true)).toEqual('1970-01-01T00:00:00.000'); + expect( + TimeUtils.format( + new RealTimestamp( + NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n + ), + true + ) + ).toEqual('2022-11-10T22:04:54.186'); + expect(TimeUtils.format(new RealTimestamp(NOV_10_2022), true)).toEqual( + '2022-11-10T00:00:00.000' + ); + expect(TimeUtils.format(new RealTimestamp(NOV_10_2022 + 1n), true)).toEqual( + '2022-11-10T00:00:00.000' + ); - expect(TimeUtils.format(new RealTimestamp(0n), false)) - .toEqual("1970-01-01T00:00:00.000000000"); - expect(TimeUtils.format(new RealTimestamp( - NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n), false)) - .toEqual("2022-11-10T22:04:54.186123212"); - expect(TimeUtils.format(new RealTimestamp(NOV_10_2022), false)) - .toEqual("2022-11-10T00:00:00.000000000"); - expect(TimeUtils.format(new RealTimestamp(NOV_10_2022 + 1n), false)) - .toEqual("2022-11-10T00:00:00.000000001"); + expect(TimeUtils.format(new RealTimestamp(0n), false)).toEqual('1970-01-01T00:00:00.000000000'); + expect( + TimeUtils.format( + new RealTimestamp( + NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n + ), + false + ) + ).toEqual('2022-11-10T22:04:54.186123212'); + expect(TimeUtils.format(new RealTimestamp(NOV_10_2022), false)).toEqual( + '2022-11-10T00:00:00.000000000' + ); + expect(TimeUtils.format(new RealTimestamp(NOV_10_2022 + 1n), false)).toEqual( + '2022-11-10T00:00:00.000000001' + ); }); - it("humanRealToNanoseconds", () => { + it('humanRealToNanoseconds', () => { const NOV_10_2022 = 1668038400000n * MILLISECOND; - expect(TimeUtils.parseHumanReal("2022-11-10T22:04:54.186123212")) - .toEqual(new RealTimestamp(NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n)); - expect(TimeUtils.parseHumanReal("2022-11-10T22:04:54.186123212Z")).toEqual(new RealTimestamp(1668117894186123212n)); - expect(TimeUtils.parseHumanReal("2022-11-10T22:04:54.186000212")).toEqual(new RealTimestamp(1668117894186000212n)); - expect(TimeUtils.parseHumanReal("2022-11-10T22:04:54.006000002")).toEqual(new RealTimestamp(1668117894006000002n)); - expect(TimeUtils.parseHumanReal("2022-11-10T06:04:54.006000002")).toEqual(new RealTimestamp(1668060294006000002n)); + expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.186123212')).toEqual( + new RealTimestamp( + NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n + ) + ); + expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.186123212Z')).toEqual( + new RealTimestamp(1668117894186123212n) + ); + expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.186000212')).toEqual( + new RealTimestamp(1668117894186000212n) + ); + expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.006000002')).toEqual( + new RealTimestamp(1668117894006000002n) + ); + expect(TimeUtils.parseHumanReal('2022-11-10T06:04:54.006000002')).toEqual( + new RealTimestamp(1668060294006000002n) + ); }); - it("canReverseDateFormatting", () => { + it('canReverseDateFormatting', () => { let timestamp = new RealTimestamp(1668117894186123212n); expect(TimeUtils.parseHumanReal(TimeUtils.format(timestamp))).toEqual(timestamp); @@ -164,41 +201,48 @@ describe("TimeUtils", () => { expect(TimeUtils.parseHumanElapsed(TimeUtils.format(timestamp))).toEqual(timestamp); }); - it("humanToNanoseconds throws on invalid input format", () => { - const invalidFormatError = new Error("Invalid real timestamp format"); - expect(() => TimeUtils.parseHumanReal("23h59m59s999ms5ns") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanReal("1d") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanReal("100") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanReal("06h4m54s, 10 Nov 2022") ) - .toThrow(invalidFormatError); - expect(() => TimeUtils.parseHumanReal("") ) - .toThrow(invalidFormatError); + it('humanToNanoseconds throws on invalid input format', () => { + const invalidFormatError = new Error('Invalid real timestamp format'); + expect(() => TimeUtils.parseHumanReal('23h59m59s999ms5ns')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanReal('1d')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanReal('100')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanReal('06h4m54s, 10 Nov 2022')).toThrow(invalidFormatError); + expect(() => TimeUtils.parseHumanReal('')).toThrow(invalidFormatError); }); - it("nano second regex accept all expected inputs", () => { - expect(TimeUtils.NS_TIMESTAMP_REGEX.test("123")).toBeTrue(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test("123ns")).toBeTrue(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test("123 ns")).toBeTrue(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test(" 123 ns ")).toBeTrue(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test(" 123 ")).toBeTrue(); + it('nano second regex accept all expected inputs', () => { + expect(TimeUtils.NS_TIMESTAMP_REGEX.test('123')).toBeTrue(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test('123ns')).toBeTrue(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test('123 ns')).toBeTrue(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test(' 123 ns ')).toBeTrue(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test(' 123 ')).toBeTrue(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test("1a23")).toBeFalse(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test("a123 ns")).toBeFalse(); - expect(TimeUtils.NS_TIMESTAMP_REGEX.test("")).toBeFalse(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test('1a23')).toBeFalse(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test('a123 ns')).toBeFalse(); + expect(TimeUtils.NS_TIMESTAMP_REGEX.test('')).toBeFalse(); }); - it("format real", () => { - expect(TimeUtils.format(Timestamp.from(TimestampType.REAL, 100n, 500n))).toEqual("1970-01-01T00:00:00.000000600"); - expect(TimeUtils.format(Timestamp.from(TimestampType.REAL, 100n * MILLISECOND, 500n), true)).toEqual("1970-01-01T00:00:00.100"); + it('format real', () => { + expect(TimeUtils.format(Timestamp.from(TimestampType.REAL, 100n, 500n))).toEqual( + '1970-01-01T00:00:00.000000600' + ); + expect( + TimeUtils.format(Timestamp.from(TimestampType.REAL, 100n * MILLISECOND, 500n), true) + ).toEqual('1970-01-01T00:00:00.100'); }); - it("format elapsed", () => { - expect(TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND, 500n), true)).toEqual("100ms"); - expect(TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND), true)).toEqual("100ms"); - expect(TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND, 500n))).toEqual("100ms0ns"); - expect(TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND))).toEqual("100ms0ns"); + it('format elapsed', () => { + expect( + TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND, 500n), true) + ).toEqual('100ms'); + expect( + TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND), true) + ).toEqual('100ms'); + expect( + TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND, 500n)) + ).toEqual('100ms0ns'); + expect(TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND))).toEqual( + '100ms0ns' + ); }); }); diff --git a/tools/winscope-ng/src/common/utils/time_utils.ts b/tools/winscope-ng/src/common/utils/time_utils.ts index 57a2644b6..0469d349b 100644 --- a/tools/winscope-ng/src/common/utils/time_utils.ts +++ b/tools/winscope-ng/src/common/utils/time_utils.ts @@ -14,43 +14,46 @@ * limitations under the License. */ -import { ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType } from "common/trace/timestamp"; +import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'common/trace/timestamp'; export class TimeUtils { static compareFn(a: Timestamp, b: Timestamp): number { if (a.getType() !== b.getType()) { - throw new Error("Attempted to compare two timestamps with different type"); + throw new Error('Attempted to compare two timestamps with different type'); } return Number(a.getValueNs() - b.getValueNs()); } static format(timestamp: Timestamp, hideNs = false): string { switch (timestamp.getType()) { - case TimestampType.ELAPSED: { - return TimeUtils.nanosecondsToHumanElapsed(timestamp.getValueNs(), hideNs); - } - case TimestampType.REAL: { - return TimeUtils.nanosecondsToHumanReal(timestamp.getValueNs(), hideNs); - } - default: { - throw Error("Unhandled timestamp type"); - } + case TimestampType.ELAPSED: { + return TimeUtils.nanosecondsToHumanElapsed(timestamp.getValueNs(), hideNs); + } + case TimestampType.REAL: { + return TimeUtils.nanosecondsToHumanReal(timestamp.getValueNs(), hideNs); + } + default: { + throw Error('Unhandled timestamp type'); + } } } - private static nanosecondsToHumanElapsed(timestampNanos: number|bigint, hideNs = true): string { + private static nanosecondsToHumanElapsed(timestampNanos: number | bigint, hideNs = true): string { timestampNanos = BigInt(timestampNanos); const units = TimeUtils.units; let leftNanos = timestampNanos; - const parts = units.slice().reverse().map(({nanosInUnit, unit}) => { - let amountOfUnit = BigInt(0); - if (leftNanos >= nanosInUnit) { - amountOfUnit = leftNanos / BigInt(nanosInUnit); - } - leftNanos = leftNanos % BigInt(nanosInUnit); - return `${amountOfUnit}${unit}`; - }); + const parts = units + .slice() + .reverse() + .map(({nanosInUnit, unit}) => { + let amountOfUnit = BigInt(0); + if (leftNanos >= nanosInUnit) { + amountOfUnit = leftNanos / BigInt(nanosInUnit); + } + leftNanos = leftNanos % BigInt(nanosInUnit); + return `${amountOfUnit}${unit}`; + }); if (hideNs) { parts.pop(); @@ -61,38 +64,41 @@ export class TimeUtils { parts.shift(); } - return parts.join(""); + return parts.join(''); } - private static nanosecondsToHumanReal(timestampNanos: number|bigint, hideNs = true): string { + private static nanosecondsToHumanReal(timestampNanos: number | bigint, hideNs = true): string { timestampNanos = BigInt(timestampNanos); const ms = timestampNanos / 1000000n; const extraNanos = timestampNanos % 1000000n; - const formattedTimestamp = new Date(Number(ms)).toISOString().replace("Z", ""); + const formattedTimestamp = new Date(Number(ms)).toISOString().replace('Z', ''); if (hideNs) { return formattedTimestamp; } else { - return `${formattedTimestamp}${extraNanos.toString().padStart(6, "0")}`; + return `${formattedTimestamp}${extraNanos.toString().padStart(6, '0')}`; } } static parseHumanElapsed(timestampHuman: string): Timestamp { if (!TimeUtils.HUMAN_ELAPSED_TIMESTAMP_REGEX.test(timestampHuman)) { - throw Error("Invalid elapsed timestamp format"); + throw Error('Invalid elapsed timestamp format'); } const units = TimeUtils.units; - const usedUnits = timestampHuman.split(/[0-9]+/).filter(it => it !== ""); - const usedValues = timestampHuman.split(/[a-z]+/).filter(it => it !== "").map(it => parseInt(it)); + const usedUnits = timestampHuman.split(/[0-9]+/).filter((it) => it !== ''); + const usedValues = timestampHuman + .split(/[a-z]+/) + .filter((it) => it !== '') + .map((it) => parseInt(it)); let ns = BigInt(0); for (let i = 0; i < usedUnits.length; i++) { const unit = usedUnits[i]; const value = usedValues[i]; - const unitData = units.find(it => it.unit == unit)!; + const unitData = units.find((it) => it.unit == unit)!; ns += BigInt(unitData.nanosInUnit) * BigInt(value); } @@ -101,44 +107,48 @@ export class TimeUtils { static parseHumanReal(timestampHuman: string): Timestamp { if (!TimeUtils.HUMAN_REAL_TIMESTAMP_REGEX.test(timestampHuman)) { - throw Error("Invalid real timestamp format"); + throw Error('Invalid real timestamp format'); } // Add trailing Z if it isn't there yet - if (timestampHuman[timestampHuman.length - 1] != "Z") { - timestampHuman += "Z"; + if (timestampHuman[timestampHuman.length - 1] != 'Z') { + timestampHuman += 'Z'; } // Date.parse only considers up to millisecond precision let nanoSeconds = 0; - if (timestampHuman.includes(".")) { - const milliseconds = timestampHuman.split(".")[1].replace("Z", ""); - nanoSeconds = parseInt(milliseconds.padEnd(9, "0").slice(3)); + if (timestampHuman.includes('.')) { + const milliseconds = timestampHuman.split('.')[1].replace('Z', ''); + nanoSeconds = parseInt(milliseconds.padEnd(9, '0').slice(3)); } - return new RealTimestamp(BigInt(Date.parse(timestampHuman)) * BigInt(TimeUtils.TO_NANO["ms"]) + BigInt(nanoSeconds)); + return new RealTimestamp( + BigInt(Date.parse(timestampHuman)) * BigInt(TimeUtils.TO_NANO['ms']) + BigInt(nanoSeconds) + ); } static TO_NANO = { - "ns": 1, - "ms": 1000000, - "s": 1000000 * 1000, - "m": 1000000 * 1000 * 60, - "h": 1000000 * 1000 * 60 * 60, - "d": 1000000 * 1000 * 60 * 60 * 24 + ns: 1, + ms: 1000000, + s: 1000000 * 1000, + m: 1000000 * 1000 * 60, + h: 1000000 * 1000 * 60 * 60, + d: 1000000 * 1000 * 60 * 60 * 24, }; static units = [ - {nanosInUnit: TimeUtils.TO_NANO["ns"], unit: "ns"}, - {nanosInUnit: TimeUtils.TO_NANO["ms"], unit: "ms"}, - {nanosInUnit: TimeUtils.TO_NANO["s"], unit: "s"}, - {nanosInUnit: TimeUtils.TO_NANO["m"], unit: "m"}, - {nanosInUnit: TimeUtils.TO_NANO["h"], unit: "h"}, - {nanosInUnit: TimeUtils.TO_NANO["d"], unit: "d"}, + {nanosInUnit: TimeUtils.TO_NANO['ns'], unit: 'ns'}, + {nanosInUnit: TimeUtils.TO_NANO['ms'], unit: 'ms'}, + {nanosInUnit: TimeUtils.TO_NANO['s'], unit: 's'}, + {nanosInUnit: TimeUtils.TO_NANO['m'], unit: 'm'}, + {nanosInUnit: TimeUtils.TO_NANO['h'], unit: 'h'}, + {nanosInUnit: TimeUtils.TO_NANO['d'], unit: 'd'}, ]; // (?=.) checks there is at least one character with a lookahead match - static readonly HUMAN_ELAPSED_TIMESTAMP_REGEX = /^(?=.)([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?([0-9]+ns)?$/; - static readonly HUMAN_REAL_TIMESTAMP_REGEX = /^[0-9]{4}-((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[469]|11)-(0[1-9]|[12][0-9]|30)|(02)-(0[1-9]|[12][0-9]))T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])\.[0-9]{3}([0-9]{6})?Z?$/; + static readonly HUMAN_ELAPSED_TIMESTAMP_REGEX = + /^(?=.)([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?([0-9]+ns)?$/; + static readonly HUMAN_REAL_TIMESTAMP_REGEX = + /^[0-9]{4}-((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[469]|11)-(0[1-9]|[12][0-9]|30)|(02)-(0[1-9]|[12][0-9]))T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])\.[0-9]{3}([0-9]{6})?Z?$/; static readonly NS_TIMESTAMP_REGEX = /^\s*[0-9]+(\s?ns)?\s*$/; } diff --git a/tools/winscope-ng/src/common/utils/tree_utils.ts b/tools/winscope-ng/src/common/utils/tree_utils.ts index 28d3be518..54eb09dac 100644 --- a/tools/winscope-ng/src/common/utils/tree_utils.ts +++ b/tools/winscope-ng/src/common/utils/tree_utils.ts @@ -22,9 +22,8 @@ interface TreeNode { type FilterType = (node: TreeNode | undefined | null) => boolean; -class TreeUtils -{ - public static findDescendantNode(node: TreeNode, isTargetNode: FilterType): TreeNode|undefined { +class TreeUtils { + public static findDescendantNode(node: TreeNode, isTargetNode: FilterType): TreeNode | undefined { if (isTargetNode(node)) { return node; } @@ -43,7 +42,7 @@ class TreeUtils return undefined; } - public static findAncestorNode(node: TreeNode, isTargetNode: FilterType): TreeNode|undefined { + public static findAncestorNode(node: TreeNode, isTargetNode: FilterType): TreeNode | undefined { let ancestor = node.parent; while (ancestor && !isTargetNode(ancestor)) { @@ -54,24 +53,26 @@ class TreeUtils } public static makeNodeFilter(filterString: string): FilterType { - const filterStrings = filterString.split(","); + const filterStrings = filterString.split(','); const positive: any[] = []; const negative: any[] = []; filterStrings.forEach((f) => { f = f.trim(); - if (f.startsWith("!")) { - const regex = new RegExp(f.substring(1), "i"); + if (f.startsWith('!')) { + const regex = new RegExp(f.substring(1), 'i'); negative.push((s: any) => !regex.test(s)); } else { - const regex = new RegExp(f, "i"); + const regex = new RegExp(f, 'i'); positive.push((s: any) => regex.test(s)); } }); const filter = (item: TreeNode | undefined | null) => { if (item) { const apply = (f: any) => f(`${item.name}`); - return (positive.length === 0 || positive.some(apply)) && - (negative.length === 0 || negative.every(apply)); + return ( + (positive.length === 0 || positive.some(apply)) && + (negative.length === 0 || negative.every(apply)) + ); } return false; }; diff --git a/tools/winscope-ng/src/cross_tool/cross_tool_protocol.ts b/tools/winscope-ng/src/cross_tool/cross_tool_protocol.ts index 3756ff052..b59244bf9 100644 --- a/tools/winscope-ng/src/cross_tool/cross_tool_protocol.ts +++ b/tools/winscope-ng/src/cross_tool/cross_tool_protocol.ts @@ -14,31 +14,27 @@ * limitations under the License. */ -import {Message, MessageBugReport, MessagePong, MessageTimestamp, MessageType} from "./messages"; -import {OriginAllowList} from "./origin_allow_list"; -import {RealTimestamp} from "common/trace/timestamp"; -import {FunctionUtils} from "common/utils/function_utils"; -import {RemoteBugreportReceiver, OnBugreportReceived} from "interfaces/remote_bugreport_receiver"; -import {RemoteTimestampReceiver, OnTimestampReceived} from "interfaces/remote_timestamp_receiver"; -import {RemoteTimestampSender} from "interfaces/remote_timestamp_sender"; +import {RealTimestamp} from 'common/trace/timestamp'; +import {FunctionUtils} from 'common/utils/function_utils'; +import {OnBugreportReceived, RemoteBugreportReceiver} from 'interfaces/remote_bugreport_receiver'; +import {OnTimestampReceived, RemoteTimestampReceiver} from 'interfaces/remote_timestamp_receiver'; +import {RemoteTimestampSender} from 'interfaces/remote_timestamp_sender'; +import {Message, MessageBugReport, MessagePong, MessageTimestamp, MessageType} from './messages'; +import {OriginAllowList} from './origin_allow_list'; class RemoteTool { - constructor( - public readonly window: Window, - public readonly origin: string) { - } + constructor(public readonly window: Window, public readonly origin: string) {} } -export class CrossToolProtocol implements - RemoteBugreportReceiver, - RemoteTimestampReceiver, - RemoteTimestampSender { +export class CrossToolProtocol + implements RemoteBugreportReceiver, RemoteTimestampReceiver, RemoteTimestampSender +{ private remoteTool?: RemoteTool; private onBugreportReceived: OnBugreportReceived = FunctionUtils.DO_NOTHING_ASYNC; private onTimestampReceived: OnTimestampReceived = FunctionUtils.DO_NOTHING; constructor() { - window.addEventListener("message", async (event) => { + window.addEventListener('message', async (event) => { await this.onMessageReceived(event); }); } @@ -58,13 +54,18 @@ export class CrossToolProtocol implements const message = new MessageTimestamp(timestamp.getValueNs()); this.remoteTool.window.postMessage(message, this.remoteTool.origin); - console.log("Cross-tool protocol sent timestamp message:", message); + console.log('Cross-tool protocol sent timestamp message:', message); } private async onMessageReceived(event: MessageEvent) { if (!OriginAllowList.isAllowed(event.origin)) { - console.log("Cross-tool protocol ignoring message from non-allowed origin.", - "Origin:", event.origin, "Message:", event.data); + console.log( + 'Cross-tool protocol ignoring message from non-allowed origin.', + 'Origin:', + event.origin, + 'Message:', + event.data + ); return; } @@ -77,35 +78,34 @@ export class CrossToolProtocol implements this.remoteTool = new RemoteTool(event.source as Window, event.origin); } - switch(message.type) { - case MessageType.PING: - console.log("Cross-tool protocol received ping message:", message); - (event.source as Window).postMessage(new MessagePong(), event.origin); - break; - case MessageType.PONG: - console.log("Cross-tool protocol received unexpected pong message:", message); - break; - case MessageType.BUGREPORT: - console.log("Cross-tool protocol received bugreport message:", message); - await this.onMessageBugreportReceived(message as MessageBugReport); - break; - case MessageType.TIMESTAMP: - console.log("Cross-tool protocol received timestamp message:", message); - this.onMessageTimestampReceived(message as MessageTimestamp); - break; - case MessageType.FILES: - console.log("Cross-tool protocol received unexpected files message", message); - break; - default: - console.log("Cross-tool protocol received unsupported message type:", message); - break; + switch (message.type) { + case MessageType.PING: + console.log('Cross-tool protocol received ping message:', message); + (event.source as Window).postMessage(new MessagePong(), event.origin); + break; + case MessageType.PONG: + console.log('Cross-tool protocol received unexpected pong message:', message); + break; + case MessageType.BUGREPORT: + console.log('Cross-tool protocol received bugreport message:', message); + await this.onMessageBugreportReceived(message as MessageBugReport); + break; + case MessageType.TIMESTAMP: + console.log('Cross-tool protocol received timestamp message:', message); + this.onMessageTimestampReceived(message as MessageTimestamp); + break; + case MessageType.FILES: + console.log('Cross-tool protocol received unexpected files message', message); + break; + default: + console.log('Cross-tool protocol received unsupported message type:', message); + break; } } private async onMessageBugreportReceived(message: MessageBugReport) { - const timestamp = message.timestampNs !== undefined - ? new RealTimestamp(message.timestampNs) - : undefined; + const timestamp = + message.timestampNs !== undefined ? new RealTimestamp(message.timestampNs) : undefined; this.onBugreportReceived(message.file, timestamp); } diff --git a/tools/winscope-ng/src/cross_tool/cross_tool_protocol_stub.ts b/tools/winscope-ng/src/cross_tool/cross_tool_protocol_stub.ts index 405ca3346..2f195d352 100644 --- a/tools/winscope-ng/src/cross_tool/cross_tool_protocol_stub.ts +++ b/tools/winscope-ng/src/cross_tool/cross_tool_protocol_stub.ts @@ -14,16 +14,15 @@ * limitations under the License. */ -import {RealTimestamp} from "common/trace/timestamp"; -import {FunctionUtils} from "common/utils/function_utils"; -import {RemoteBugreportReceiver, OnBugreportReceived} from "interfaces/remote_bugreport_receiver"; -import {RemoteTimestampReceiver, OnTimestampReceived} from "interfaces/remote_timestamp_receiver"; -import {RemoteTimestampSender} from "interfaces/remote_timestamp_sender"; +import {RealTimestamp} from 'common/trace/timestamp'; +import {FunctionUtils} from 'common/utils/function_utils'; +import {OnBugreportReceived, RemoteBugreportReceiver} from 'interfaces/remote_bugreport_receiver'; +import {OnTimestampReceived, RemoteTimestampReceiver} from 'interfaces/remote_timestamp_receiver'; +import {RemoteTimestampSender} from 'interfaces/remote_timestamp_sender'; -export class CrossToolProtocolStub implements - RemoteBugreportReceiver, - RemoteTimestampReceiver, - RemoteTimestampSender { +export class CrossToolProtocolStub + implements RemoteBugreportReceiver, RemoteTimestampReceiver, RemoteTimestampSender +{ onBugreportReceived: OnBugreportReceived = FunctionUtils.DO_NOTHING_ASYNC; onTimestampReceived: OnTimestampReceived = FunctionUtils.DO_NOTHING; diff --git a/tools/winscope-ng/src/cross_tool/messages.ts b/tools/winscope-ng/src/cross_tool/messages.ts index b02ca7c38..3e1e4bdde 100644 --- a/tools/winscope-ng/src/cross_tool/messages.ts +++ b/tools/winscope-ng/src/cross_tool/messages.ts @@ -38,28 +38,17 @@ export class MessagePong implements Message { export class MessageBugReport implements Message { type = MessageType.BUGREPORT; - constructor( - public file: File, - public timestampNs?: bigint, - public issueId?: string - ) {} + constructor(public file: File, public timestampNs?: bigint, public issueId?: string) {} } export class MessageTimestamp implements Message { type = MessageType.TIMESTAMP; - constructor( - public timestampNs: bigint, - public sections?: string[] - ) {} + constructor(public timestampNs: bigint, public sections?: string[]) {} } export class MessageFiles implements Message { type = MessageType.FILES; - constructor( - public files: File[], - public timestampNs?: bigint, - public issueId?: string - ) {} + constructor(public files: File[], public timestampNs?: bigint, public issueId?: string) {} } diff --git a/tools/winscope-ng/src/cross_tool/origin_allow_list.spec.ts b/tools/winscope-ng/src/cross_tool/origin_allow_list.spec.ts index 97432d662..88d02ebf1 100644 --- a/tools/winscope-ng/src/cross_tool/origin_allow_list.spec.ts +++ b/tools/winscope-ng/src/cross_tool/origin_allow_list.spec.ts @@ -14,41 +14,41 @@ * limitations under the License. */ -import {OriginAllowList} from "./origin_allow_list"; +import {OriginAllowList} from './origin_allow_list'; -describe("OriginAllowList", () => { - describe("dev mode", () => { - const mode = "DEV" as const; +describe('OriginAllowList', () => { + describe('dev mode', () => { + const mode = 'DEV' as const; - it("allows localhost", () => { - expect(OriginAllowList.isAllowed("http://localhost:8081", mode)).toBeTrue(); - expect(OriginAllowList.isAllowed("https://localhost:8081", mode)).toBeTrue(); + it('allows localhost', () => { + expect(OriginAllowList.isAllowed('http://localhost:8081', mode)).toBeTrue(); + expect(OriginAllowList.isAllowed('https://localhost:8081', mode)).toBeTrue(); }); }); - describe("prod mode", () => { - const mode = "PROD" as const; + describe('prod mode', () => { + const mode = 'PROD' as const; - it("allows google.com", () => { - expect(OriginAllowList.isAllowed("https://google.com", mode)).toBeTrue(); - expect(OriginAllowList.isAllowed("https://subdomain.google.com", mode)).toBeTrue(); + it('allows google.com', () => { + expect(OriginAllowList.isAllowed('https://google.com', mode)).toBeTrue(); + expect(OriginAllowList.isAllowed('https://subdomain.google.com', mode)).toBeTrue(); }); - it("denies pseudo google.com", () => { - expect(OriginAllowList.isAllowed("https://evilgoogle.com", mode)).toBeFalse(); - expect(OriginAllowList.isAllowed("https://evil.com/google.com", mode)).toBeFalse(); + it('denies pseudo google.com', () => { + expect(OriginAllowList.isAllowed('https://evilgoogle.com', mode)).toBeFalse(); + expect(OriginAllowList.isAllowed('https://evil.com/google.com', mode)).toBeFalse(); }); - it("allows googleplex.com", () => { - expect(OriginAllowList.isAllowed("https://googleplex.com", mode)).toBeTrue(); - expect(OriginAllowList.isAllowed("https://subdomain.googleplex.com", mode)) - .toBeTrue(); + it('allows googleplex.com', () => { + expect(OriginAllowList.isAllowed('https://googleplex.com', mode)).toBeTrue(); + expect(OriginAllowList.isAllowed('https://subdomain.googleplex.com', mode)).toBeTrue(); }); - it("denies pseudo googleplex.com", () => { - expect(OriginAllowList.isAllowed("https://evilgoogleplex.com", mode)).toBeFalse(); - expect(OriginAllowList.isAllowed("https://evil.com/subdomain.googleplex.com", mode)) - .toBeFalse(); + it('denies pseudo googleplex.com', () => { + expect(OriginAllowList.isAllowed('https://evilgoogleplex.com', mode)).toBeFalse(); + expect( + OriginAllowList.isAllowed('https://evil.com/subdomain.googleplex.com', mode) + ).toBeFalse(); }); }); }); diff --git a/tools/winscope-ng/src/cross_tool/origin_allow_list.ts b/tools/winscope-ng/src/cross_tool/origin_allow_list.ts index f58cbd536..ad80ec860 100644 --- a/tools/winscope-ng/src/cross_tool/origin_allow_list.ts +++ b/tools/winscope-ng/src/cross_tool/origin_allow_list.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import {globalConfig} from "common/utils/global_config"; +import {globalConfig} from 'common/utils/global_config'; export class OriginAllowList { private static readonly ALLOW_LIST_PROD = [ - new RegExp("^https://([^\\/]*\\.)*googleplex\\.com$"), - new RegExp("^https://([^\\/]*\\.)*google\\.com$"), + new RegExp('^https://([^\\/]*\\.)*googleplex\\.com$'), + new RegExp('^https://([^\\/]*\\.)*google\\.com$'), ]; private static readonly ALLOW_LIST_DEV = [ ...OriginAllowList.ALLOW_LIST_PROD, - new RegExp("^(http|https)://localhost:8081$"), // remote tool mock + new RegExp('^(http|https)://localhost:8081$'), // remote tool mock ]; static isAllowed(originUrl: string, mode = globalConfig.MODE): boolean { @@ -40,13 +40,13 @@ export class OriginAllowList { } private static getList(mode: typeof globalConfig.MODE): RegExp[] { - switch(mode) { - case "DEV": - return OriginAllowList.ALLOW_LIST_DEV; - case "PROD": - return OriginAllowList.ALLOW_LIST_PROD; - default: - throw new Error(`Unhandled mode: ${globalConfig.MODE}`); + switch (mode) { + case 'DEV': + return OriginAllowList.ALLOW_LIST_DEV; + case 'PROD': + return OriginAllowList.ALLOW_LIST_PROD; + default: + throw new Error(`Unhandled mode: ${globalConfig.MODE}`); } } } diff --git a/tools/winscope-ng/src/interfaces/remote_bugreport_receiver.ts b/tools/winscope-ng/src/interfaces/remote_bugreport_receiver.ts index cca7cb936..9b0d546f1 100644 --- a/tools/winscope-ng/src/interfaces/remote_bugreport_receiver.ts +++ b/tools/winscope-ng/src/interfaces/remote_bugreport_receiver.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {RealTimestamp} from "common/trace/timestamp"; +import {RealTimestamp} from 'common/trace/timestamp'; export type OnBugreportReceived = (bugreport: File, timestamp?: RealTimestamp) => Promise; diff --git a/tools/winscope-ng/src/interfaces/remote_timestamp_receiver.ts b/tools/winscope-ng/src/interfaces/remote_timestamp_receiver.ts index 1d480d83a..304052b0d 100644 --- a/tools/winscope-ng/src/interfaces/remote_timestamp_receiver.ts +++ b/tools/winscope-ng/src/interfaces/remote_timestamp_receiver.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {RealTimestamp} from "common/trace/timestamp"; +import {RealTimestamp} from 'common/trace/timestamp'; export type OnTimestampReceived = (timestamp: RealTimestamp) => void; diff --git a/tools/winscope-ng/src/interfaces/remote_timestamp_sender.ts b/tools/winscope-ng/src/interfaces/remote_timestamp_sender.ts index 80c922c75..35042bd1c 100644 --- a/tools/winscope-ng/src/interfaces/remote_timestamp_sender.ts +++ b/tools/winscope-ng/src/interfaces/remote_timestamp_sender.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {RealTimestamp} from "common/trace/timestamp"; +import {RealTimestamp} from 'common/trace/timestamp'; export interface RemoteTimestampSender { sendTimestamp(timestamp: RealTimestamp): void; diff --git a/tools/winscope-ng/src/interfaces/timestamp_change_listener.ts b/tools/winscope-ng/src/interfaces/timestamp_change_listener.ts index 137ec5979..cb0195540 100644 --- a/tools/winscope-ng/src/interfaces/timestamp_change_listener.ts +++ b/tools/winscope-ng/src/interfaces/timestamp_change_listener.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import {Timestamp} from "common/trace/timestamp"; +import {Timestamp} from 'common/trace/timestamp'; export interface TimestampChangeListener { - onCurrentTimestampChanged(timestamp: Timestamp|undefined): void; + onCurrentTimestampChanged(timestamp: Timestamp | undefined): void; } diff --git a/tools/winscope-ng/src/interfaces/trace_data_listener.ts b/tools/winscope-ng/src/interfaces/trace_data_listener.ts index 19b8b9836..3efc14be4 100644 --- a/tools/winscope-ng/src/interfaces/trace_data_listener.ts +++ b/tools/winscope-ng/src/interfaces/trace_data_listener.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {Viewer} from "viewers/viewer"; +import {Viewer} from 'viewers/viewer'; export interface TraceDataListener { onTraceDataUnloaded(): void; diff --git a/tools/winscope-ng/src/main.component.spec.ts b/tools/winscope-ng/src/main.component.spec.ts index da4fda2b3..38f4c870b 100644 --- a/tools/winscope-ng/src/main.component.spec.ts +++ b/tools/winscope-ng/src/main.component.spec.ts @@ -13,23 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import "zone.js"; -import "zone.js/testing"; -import {TestBed} from "@angular/core/testing"; -import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from "@angular/platform-browser-dynamic/testing"; + +// organize-imports-ignore +import 'zone.js'; +import 'zone.js/testing'; +import {TestBed} from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; declare const require: { - context(path: string, deep?: boolean, filter?: RegExp): { + context( + path: string, + deep?: boolean, + filter?: RegExp + ): { (id: string): T; keys(): string[]; }; }; -TestBed.initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), -); +TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); // load all tests of Angular components -const context = require.context("./", true, /\.component\.spec\.ts$/); +const context = require.context('./', true, /\.component\.spec\.ts$/); context.keys().forEach(context); diff --git a/tools/winscope-ng/src/main.dev.ts b/tools/winscope-ng/src/main.dev.ts index d942cfa72..1360068fb 100644 --- a/tools/winscope-ng/src/main.dev.ts +++ b/tools/winscope-ng/src/main.dev.ts @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {platformBrowserDynamic} from "@angular/platform-browser-dynamic"; -import {AppModule} from "./app/app.module"; -import {globalConfig} from "common/utils/global_config"; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; +import {globalConfig} from 'common/utils/global_config'; +import {AppModule} from './app/app.module'; globalConfig.set({ - MODE: "DEV", + MODE: 'DEV', }); -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/tools/winscope-ng/src/main.prod.ts b/tools/winscope-ng/src/main.prod.ts index d418def2a..d66c60591 100644 --- a/tools/winscope-ng/src/main.prod.ts +++ b/tools/winscope-ng/src/main.prod.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {enableProdMode} from "@angular/core"; -import {platformBrowserDynamic} from "@angular/platform-browser-dynamic"; -import {AppModule} from "./app/app.module"; +import {enableProdMode} from '@angular/core'; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; +import {AppModule} from './app/app.module'; enableProdMode(); -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/tools/winscope-ng/src/parsers/parser.ts b/tools/winscope-ng/src/parsers/parser.ts index aa1852617..d597e33c9 100644 --- a/tools/winscope-ng/src/parsers/parser.ts +++ b/tools/winscope-ng/src/parsers/parser.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import {ArrayUtils} from "common/utils/array_utils"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {Trace, TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {Trace, TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {ArrayUtils} from 'common/utils/array_utils'; abstract class Parser { protected trace: TraceFile; @@ -32,9 +32,11 @@ abstract class Parser { const traceBuffer = new Uint8Array(await this.trace.file.arrayBuffer()); const magicNumber = this.getMagicNumber(); - if (magicNumber !== undefined) - { - const bufferContainsMagicNumber = ArrayUtils.equal(magicNumber, traceBuffer.slice(0, magicNumber.length)); + if (magicNumber !== undefined) { + const bufferContainsMagicNumber = ArrayUtils.equal( + magicNumber, + traceBuffer.slice(0, magicNumber.length) + ); if (!bufferContainsMagicNumber) { throw TypeError("buffer doesn't contain expected magic number"); } @@ -84,7 +86,8 @@ abstract class Parser { } if (fieldProperties.resolvedType && fieldProperties.resolvedType.valuesById) { - protoObj[fieldName] = fieldProperties.resolvedType.valuesById[protoObj[fieldProperties.name]]; + protoObj[fieldName] = + fieldProperties.resolvedType.valuesById[protoObj[fieldProperties.name]]; continue; } this.addDefaultProtoFields(protoObj[fieldName]); @@ -99,11 +102,11 @@ abstract class Parser { public getTrace(): Trace { return { type: this.getTraceType(), - traceFile: this.trace + traceFile: this.trace, }; } - public getTimestamps(type: TimestampType): undefined|Timestamp[] { + public getTimestamps(type: TimestampType): undefined | Timestamp[] { return this.timestamps.get(type); } @@ -115,7 +118,7 @@ abstract class Parser { //TODO (b/256564627): // - factor out timestamp search policy. Receive index parameter instead. // - make async for possible lazy disk reads in the future - public getTraceEntry(timestamp: Timestamp): undefined|any { + public getTraceEntry(timestamp: Timestamp): undefined | any { const timestamps = this.getTimestamps(timestamp.getType()); if (timestamps === undefined) { throw TypeError(`Timestamps with type "${timestamp.getType()}" not available`); @@ -128,10 +131,14 @@ abstract class Parser { return this.processDecodedEntry(index, timestamp.getType(), this.decodedEntries[index]); } - protected abstract getMagicNumber(): undefined|number[]; + protected abstract getMagicNumber(): undefined | number[]; protected abstract decodeTrace(trace: Uint8Array): any[]; - protected abstract getTimestamp(type: TimestampType, decodedEntry: any): undefined|Timestamp; - protected abstract processDecodedEntry(index: number, timestampType: TimestampType, decodedEntry: any): any; + protected abstract getTimestamp(type: TimestampType, decodedEntry: any): undefined | Timestamp; + protected abstract processDecodedEntry( + index: number, + timestampType: TimestampType, + decodedEntry: any + ): any; } export {Parser}; diff --git a/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts b/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts index 5965cd5ed..4b5f651b5 100644 --- a/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts @@ -13,75 +13,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserAccessibility", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserAccessibility', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/Accessibility.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/Accessibility.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.ACCESSIBILITY); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const expected = [ new Timestamp(TimestampType.ELAPSED, 14499089524n), new Timestamp(TimestampType.ELAPSED, 14499599656n), new Timestamp(TimestampType.ELAPSED, 14953120693n), ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const expected = [ new Timestamp(TimestampType.REAL, 1659107089100052652n), new Timestamp(TimestampType.REAL, 1659107089100562784n), new Timestamp(TimestampType.REAL, 1659107089554083821n), ]; - expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 14499599656n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(14499599656n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(14499599656n); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089100562784n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(14499599656n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(14499599656n); }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/Accessibility.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/Accessibility.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.ACCESSIBILITY); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) - .toEqual(new Timestamp(TimestampType.ELAPSED, 850297444302n)); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]).toEqual( + new Timestamp(TimestampType.ELAPSED, 850297444302n) + ); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_accessibility.ts b/tools/winscope-ng/src/parsers/parser_accessibility.ts index 7b81d9c60..b4cd41416 100644 --- a/tools/winscope-ng/src/parsers/parser_accessibility.ts +++ b/tools/winscope-ng/src/parsers/parser_accessibility.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {AccessibilityTraceFileProto} from "./proto_types"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {Parser} from './parser'; +import {AccessibilityTraceFileProto} from './proto_types'; class ParserAccessibility extends Parser { constructor(trace: TraceFile) { @@ -36,21 +36,22 @@ class ParserAccessibility extends Parser { override decodeTrace(buffer: Uint8Array): any[] { const decoded = AccessibilityTraceFileProto.decode(buffer); - if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); - } - else { + } else { this.realToElapsedTimeOffsetNs = undefined; } return decoded.entry; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type === TimestampType.ELAPSED) { return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp( + type, + this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos) + ); } return undefined; } @@ -59,7 +60,7 @@ class ParserAccessibility extends Parser { return entryProto; } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x41, 0x31, 0x31, 0x59, 0x54, 0x52, 0x41, 0x43]; // .A11YTRAC } diff --git a/tools/winscope-ng/src/parsers/parser_common.spec.ts b/tools/winscope-ng/src/parsers/parser_common.spec.ts index b4e12524e..5282315f0 100644 --- a/tools/winscope-ng/src/parsers/parser_common.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_common.spec.ts @@ -13,26 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {Parser} from "./parser"; -import {CommonTestUtils} from "test/common/utils"; -import {UnitTestUtils} from "test/unit/utils"; -import {ParserFactory} from "./parser_factory"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {CommonTestUtils} from 'test/common/utils'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; +import {ParserFactory} from './parser_factory'; -describe("Parser", () => { - it("is robust to empty trace file", async () => { - const trace = new TraceFile( - await CommonTestUtils.getFixtureFile("traces/empty.pb"), - undefined - ); +describe('Parser', () => { + it('is robust to empty trace file', async () => { + const trace = new TraceFile(await CommonTestUtils.getFixtureFile('traces/empty.pb'), undefined); const [parsers, errors] = await new ParserFactory().createParsers([trace]); expect(parsers.length).toEqual(0); }); - it("is robust to trace with no entries", async () => { - const parser = await UnitTestUtils.getParser("traces/no_entries_InputMethodClients.pb"); + it('is robust to trace with no entries', async () => { + const parser = await UnitTestUtils.getParser('traces/no_entries_InputMethodClients.pb'); expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS); expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual([]); @@ -45,93 +42,96 @@ describe("Parser", () => { expect(parser.getTraceEntry(timestampReal)).toBeUndefined(); }); - describe("real timestamp", () => { + describe('real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/WindowManager.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/WindowManager.pb'); }); - it("provides timestamps", () => { + it('provides timestamps', () => { const expected = [ new Timestamp(TimestampType.REAL, 1659107089075566202n), new Timestamp(TimestampType.REAL, 1659107089999048990n), - new Timestamp(TimestampType.REAL, 1659107090010194213n) + new Timestamp(TimestampType.REAL, 1659107090010194213n), ]; - expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry (no timestamp matches)", () => { + it('retrieves trace entry (no timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089075566201n); - expect(parser.getTraceEntry(timestamp)) - .toEqual(undefined); + expect(parser.getTraceEntry(timestamp)).toEqual(undefined); }); - it("retrieves trace entry (equal timestamp matches)", () => { + it('retrieves trace entry (equal timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089075566202n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.unixNanos.toString())) - .toEqual(1659107089075566202n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.unixNanos.toString())).toEqual( + 1659107089075566202n + ); }); - it("retrieves trace entry (equal timestamp matches)", () => { + it('retrieves trace entry (equal timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048990n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.unixNanos.toString())) - .toEqual(1659107089999048990n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.unixNanos.toString())).toEqual( + 1659107089999048990n + ); }); - it("retrieves trace entry (lower timestamp matches)", () => { + it('retrieves trace entry (lower timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048991n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.unixNanos.toString())) - .toEqual(1659107089999048990n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.unixNanos.toString())).toEqual( + 1659107089999048990n + ); }); }); - describe("elapsed timestamp", () => { + describe('elapsed timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/WindowManager.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/WindowManager.pb'); }); - it("provides timestamps", () => { + it('provides timestamps', () => { const expected = [ new Timestamp(TimestampType.ELAPSED, 850254319343n), new Timestamp(TimestampType.ELAPSED, 850763506110n), - new Timestamp(TimestampType.ELAPSED, 850782750048n) + new Timestamp(TimestampType.ELAPSED, 850782750048n), ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); }); - it("retrieves trace entry (no timestamp matches)", () => { + it('retrieves trace entry (no timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319342n); - expect(parser.getTraceEntry(timestamp)) - .toEqual(undefined); + expect(parser.getTraceEntry(timestamp)).toEqual(undefined); }); - it("retrieves trace entry (equal timestamp matches)", () => { + it('retrieves trace entry (equal timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())) - .toEqual(850254319343n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())).toEqual( + 850254319343n + ); }); - it("retrieves trace entry (equal timestamp matches)", () => { + it('retrieves trace entry (equal timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506110n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())) - .toEqual(850763506110n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())).toEqual( + 850763506110n + ); }); - it("retrieves trace entry (lower timestamp matches)", () => { + it('retrieves trace entry (lower timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319344n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())) - .toEqual(850254319343n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())).toEqual( + 850254319343n + ); }); - it("retrieves trace entry (equal timestamp matches)", () => { + it('retrieves trace entry (equal timestamp matches)', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506111n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())) - .toEqual(850763506110n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestamp.elapsedNanos.toString())).toEqual( + 850763506110n + ); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_factory.ts b/tools/winscope-ng/src/parsers/parser_factory.ts index 1ebfdb576..0140770a1 100644 --- a/tools/winscope-ng/src/parsers/parser_factory.ts +++ b/tools/winscope-ng/src/parsers/parser_factory.ts @@ -14,21 +14,21 @@ * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {TraceFile} from "common/trace/trace"; -import {FunctionUtils, OnProgressUpdateType} from "common/utils/function_utils"; -import {Parser} from "./parser"; -import {ParserAccessibility} from "./parser_accessibility"; -import {ParserInputMethodClients} from "./parser_input_method_clients"; -import {ParserInputMethodManagerService} from "./parser_input_method_manager_service"; -import {ParserInputMethodService} from "./parser_input_method_service"; -import {ParserProtoLog} from "./parser_protolog"; -import {ParserScreenRecording} from "./parser_screen_recording"; -import {ParserScreenRecordingLegacy} from "./parser_screen_recording_legacy"; -import {ParserSurfaceFlinger} from "./parser_surface_flinger"; -import {ParserTransactions} from "./parser_transactions"; -import {ParserWindowManager} from "./parser_window_manager"; -import {ParserWindowManagerDump} from "./parser_window_manager_dump"; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {FunctionUtils, OnProgressUpdateType} from 'common/utils/function_utils'; +import {Parser} from './parser'; +import {ParserAccessibility} from './parser_accessibility'; +import {ParserInputMethodClients} from './parser_input_method_clients'; +import {ParserInputMethodManagerService} from './parser_input_method_manager_service'; +import {ParserInputMethodService} from './parser_input_method_service'; +import {ParserProtoLog} from './parser_protolog'; +import {ParserScreenRecording} from './parser_screen_recording'; +import {ParserScreenRecordingLegacy} from './parser_screen_recording_legacy'; +import {ParserSurfaceFlinger} from './parser_surface_flinger'; +import {ParserTransactions} from './parser_transactions'; +import {ParserWindowManager} from './parser_window_manager'; +import {ParserWindowManagerDump} from './parser_window_manager_dump'; export class ParserFactory { static readonly PARSERS = [ @@ -49,8 +49,8 @@ export class ParserFactory { async createParsers( traceFiles: TraceFile[], - onProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING): - Promise<[Parser[], ParserError[]]> { + onProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING + ): Promise<[Parser[], ParserError[]]> { const errors: ParserError[] = []; if (traceFiles.length === 0) { @@ -69,8 +69,7 @@ export class ParserFactory { this.parsers.set(parser.getTraceType(), parser); } break; - } - catch(error) { + } catch (error) { // skip current parser } } @@ -80,7 +79,7 @@ export class ParserFactory { errors.push(new ParserError(ParserErrorType.UNSUPPORTED_FORMAT, traceFile.file)); } - onProgressUpdate(100 * (index + 1) / traceFiles.length); + onProgressUpdate((100 * (index + 1)) / traceFiles.length); } return [Array.from(this.parsers.values()), errors]; @@ -89,30 +88,42 @@ export class ParserFactory { private shouldUseParser(newParser: Parser, errors: ParserError[]): boolean { const oldParser = this.parsers.get(newParser.getTraceType()); if (!oldParser) { - console.log(`Loaded trace ${newParser.getTrace().traceFile.file.name} (trace type: ${newParser.getTraceType()})`); + console.log( + `Loaded trace ${ + newParser.getTrace().traceFile.file.name + } (trace type: ${newParser.getTraceType()})` + ); return true; } if (newParser.getEntriesLength() > oldParser.getEntriesLength()) { console.log( - `Loaded trace ${newParser.getTrace().traceFile.file.name} (trace type: ${newParser.getTraceType()}).` + - ` Replace trace ${oldParser.getTrace().traceFile.file.name}` + `Loaded trace ${ + newParser.getTrace().traceFile.file.name + } (trace type: ${newParser.getTraceType()}).` + + ` Replace trace ${oldParser.getTrace().traceFile.file.name}` ); errors.push( new ParserError( - ParserErrorType.OVERRIDE, oldParser.getTrace().traceFile.file, oldParser.getTraceType() + ParserErrorType.OVERRIDE, + oldParser.getTrace().traceFile.file, + oldParser.getTraceType() ) ); return true; } console.log( - `Skipping trace ${newParser.getTrace().traceFile.file.name} (trace type: ${newParser.getTraceType()}).` + - ` Keep trace ${oldParser.getTrace().traceFile.file.name}` + `Skipping trace ${ + newParser.getTrace().traceFile.file.name + } (trace type: ${newParser.getTraceType()}).` + + ` Keep trace ${oldParser.getTrace().traceFile.file.name}` ); errors.push( new ParserError( - ParserErrorType.OVERRIDE, newParser.getTrace().traceFile.file, newParser.getTraceType() + ParserErrorType.OVERRIDE, + newParser.getTrace().traceFile.file, + newParser.getTraceType() ) ); return false; @@ -122,13 +133,13 @@ export class ParserFactory { export enum ParserErrorType { NO_INPUT_FILES, UNSUPPORTED_FORMAT, - OVERRIDE + OVERRIDE, } export class ParserError { constructor( public type: ParserErrorType, - public trace: File|undefined = undefined, - public traceType: TraceType|undefined = undefined) { - } + public trace: File | undefined = undefined, + public traceType: TraceType | undefined = undefined + ) {} } diff --git a/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts b/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts index 167942506..955fffe63 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts @@ -13,78 +13,77 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserInputMethodlClients", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserInputMethodlClients', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/InputMethodClients.pb"); + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/InputMethodClients.pb' + ); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)!.length) - .toEqual(13); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)!.length).toEqual(13); const expected = [ new Timestamp(TimestampType.ELAPSED, 15613638434n), new Timestamp(TimestampType.ELAPSED, 15647516364n), new Timestamp(TimestampType.ELAPSED, 15677650967n), ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const expected = [ new Timestamp(TimestampType.REAL, 1659107090215405395n), new Timestamp(TimestampType.REAL, 1659107090249283325n), new Timestamp(TimestampType.REAL, 1659107090279417928n), ]; - expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 15647516364n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(15647516364n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(15647516364n); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107090249283325n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(15647516364n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(15647516364n); }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodClients.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/InputMethodClients.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) - .toEqual(new Timestamp(TimestampType.ELAPSED, 1149083651642n)); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]).toEqual( + new Timestamp(TimestampType.ELAPSED, 1149083651642n) + ); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) - .toEqual(new Timestamp(TimestampType.ELAPSED, 1149083651642n)); + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]).toEqual( + new Timestamp(TimestampType.ELAPSED, 1149083651642n) + ); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_clients.ts b/tools/winscope-ng/src/parsers/parser_input_method_clients.ts index bb04c42de..7f0ee1dce 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_clients.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_clients.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {InputMethodClientsTraceFileProto} from "./proto_types"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { TimeUtils } from "common/utils/time_utils"; -import { ImeUtils } from "viewers/common/ime_utils"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TraceType} from 'common/trace/trace_type'; +import {TimeUtils} from 'common/utils/time_utils'; +import {ImeUtils} from 'viewers/common/ime_utils'; +import {Parser} from './parser'; +import {InputMethodClientsTraceFileProto} from './proto_types'; class ParserInputMethodClients extends Parser { constructor(trace: TraceFile) { @@ -39,61 +39,72 @@ class ParserInputMethodClients extends Parser { override decodeTrace(buffer: Uint8Array): any[] { const decoded = InputMethodClientsTraceFileProto.decode(buffer); - if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); - } - else { + } else { this.realToElapsedTimeOffsetNs = undefined; } return (InputMethodClientsTraceFileProto.decode(buffer)).entry; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type === TimestampType.ELAPSED) { return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs != undefined) { - return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs); + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs != undefined) { + return new Timestamp( + type, + BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs + ); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: TraceTreeNode): TraceTreeNode { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: TraceTreeNode + ): TraceTreeNode { if (entryProto.elapsedRealtimeNanos === undefined) { - throw Error("Missing elapsedRealtimeNanos on entry"); + throw Error('Missing elapsedRealtimeNanos on entry'); } - let clockTimeNanos: bigint|undefined = undefined; - if (this.realToElapsedTimeOffsetNs !== undefined - && entryProto.elapsedRealtimeNanos !== undefined) { + let clockTimeNanos: bigint | undefined = undefined; + if ( + this.realToElapsedTimeOffsetNs !== undefined && + entryProto.elapsedRealtimeNanos !== undefined + ) { clockTimeNanos = BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs; } - const timestamp = Timestamp.from(timestampType, BigInt(entryProto.elapsedRealtimeNanos), this.realToElapsedTimeOffsetNs); + const timestamp = Timestamp.from( + timestampType, + BigInt(entryProto.elapsedRealtimeNanos), + this.realToElapsedTimeOffsetNs + ); return { - name: TimeUtils.format(timestamp) + " - " + entryProto.where, - kind: "InputMethodClient entry", + name: TimeUtils.format(timestamp) + ' - ' + entryProto.where, + kind: 'InputMethodClient entry', children: [ { obj: ImeUtils.transformInputConnectionCall(entryProto.client), - kind: "Client", - name: entryProto.client?.viewRootImpl?.view ?? "", + kind: 'Client', + name: entryProto.client?.viewRootImpl?.view ?? '', children: [], - stableId: "client", - id: "client", - } + stableId: 'client', + id: 'client', + }, ], obj: entryProto, - stableId: "entry", - id: "entry", + stableId: 'entry', + id: 'entry', elapsedRealtimeNanos: entryProto.elapsedRealtimeNanos, clockTimeNanos, }; } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x43, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMCTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts index b6d0794fe..753660bfd 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts @@ -13,65 +13,69 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserInputMethodManagerService", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserInputMethodManagerService', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/InputMethodManagerService.pb"); + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/InputMethodManagerService.pb' + ); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_MANAGER_SERVICE); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual([new Timestamp(TimestampType.ELAPSED, 15963782518n)]); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual([ + new Timestamp(TimestampType.ELAPSED, 15963782518n), + ]); }); - it("provides real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual([new Timestamp(TimestampType.REAL, 1659107090565549479n)]); + it('provides real timestamps', () => { + expect(parser.getTimestamps(TimestampType.REAL)).toEqual([ + new Timestamp(TimestampType.REAL, 1659107090565549479n), + ]); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 15963782518n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(15963782518n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(15963782518n); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107090565549479n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(15963782518n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(15963782518n); }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodManagerService.pb"); + parser = await UnitTestUtils.getParser( + 'traces/elapsed_timestamp/InputMethodManagerService.pb' + ); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_MANAGER_SERVICE); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) - .toEqual(new Timestamp(TimestampType.ELAPSED, 1149226290110n)); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]).toEqual( + new Timestamp(TimestampType.ELAPSED, 1149226290110n) + ); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts index eb4eefd5b..fe0eb50a7 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { TimeUtils } from "common/utils/time_utils"; -import {Parser} from "./parser"; -import {InputMethodManagerServiceTraceFileProto} from "./proto_types"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TraceType} from 'common/trace/trace_type'; +import {TimeUtils} from 'common/utils/time_utils'; +import {Parser} from './parser'; +import {InputMethodManagerServiceTraceFileProto} from './proto_types'; class ParserInputMethodManagerService extends Parser { constructor(trace: TraceFile) { @@ -38,60 +38,71 @@ class ParserInputMethodManagerService extends Parser { override decodeTrace(buffer: Uint8Array): any[] { const decoded = InputMethodManagerServiceTraceFileProto.decode(buffer); - if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); - } - else { + } else { this.realToElapsedTimeOffsetNs = undefined; } return decoded.entry; } - protected override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + protected override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type === TimestampType.ELAPSED) { return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp( + type, + this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos) + ); } return undefined; } - protected override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: TraceTreeNode): TraceTreeNode { + protected override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: TraceTreeNode + ): TraceTreeNode { if (entryProto.elapsedRealtimeNanos === undefined) { - throw Error("Missing elapsedRealtimeNanos on entry"); + throw Error('Missing elapsedRealtimeNanos on entry'); } - let clockTimeNanos: bigint|undefined = undefined; - if (this.realToElapsedTimeOffsetNs !== undefined - && entryProto.elapsedRealtimeNanos !== undefined) { + let clockTimeNanos: bigint | undefined = undefined; + if ( + this.realToElapsedTimeOffsetNs !== undefined && + entryProto.elapsedRealtimeNanos !== undefined + ) { clockTimeNanos = BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs; } - const timestamp = Timestamp.from(timestampType, BigInt(entryProto.elapsedRealtimeNanos), this.realToElapsedTimeOffsetNs); + const timestamp = Timestamp.from( + timestampType, + BigInt(entryProto.elapsedRealtimeNanos), + this.realToElapsedTimeOffsetNs + ); return { - name: TimeUtils.format(timestamp) + " - " + entryProto.where, - kind: "InputMethodManagerService entry", + name: TimeUtils.format(timestamp) + ' - ' + entryProto.where, + kind: 'InputMethodManagerService entry', children: [ { obj: entryProto.inputMethodManagerService, - kind: "InputMethodManagerService", - name: "", + kind: 'InputMethodManagerService', + name: '', children: [], - stableId: "managerservice", - id: "managerservice", - } + stableId: 'managerservice', + id: 'managerservice', + }, ], obj: entryProto, - stableId: "entry", - id: "entry", + stableId: 'entry', + id: 'entry', elapsedRealtimeNanos: entryProto.elapsedRealtimeNanos, clockTimeNanos, }; } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x4d, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMMTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts b/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts index 3d112f02d..44cf2bfe6 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts @@ -13,71 +13,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserInputMethodService", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserInputMethodService', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/InputMethodService.pb"); + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/InputMethodService.pb' + ); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_SERVICE); }); - it("provides elapsed timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 16578752896n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); + it('provides elapsed timestamps', () => { + const expected = [new Timestamp(TimestampType.ELAPSED, 16578752896n)]; + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); }); - it("provides real timestamps", () => { - const expected = [ - new Timestamp(TimestampType.REAL, 1659107091180519857n), - ]; - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(expected); + it('provides real timestamps', () => { + const expected = [new Timestamp(TimestampType.REAL, 1659107091180519857n)]; + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 16578752896n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(16578752896n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(16578752896n); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107091180519857n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(16578752896n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)).toEqual(16578752896n); }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodService.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/InputMethodService.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_SERVICE); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) - .toEqual(new Timestamp(TimestampType.ELAPSED, 1149230019887n)); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]).toEqual( + new Timestamp(TimestampType.ELAPSED, 1149230019887n) + ); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_service.ts b/tools/winscope-ng/src/parsers/parser_input_method_service.ts index a5d75e698..57cbda59f 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_service.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_service.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { TimeUtils } from "common/utils/time_utils"; -import { ImeUtils } from "viewers/common/ime_utils"; -import {Parser} from "./parser"; -import {InputMethodServiceTraceFileProto} from "./proto_types"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TraceType} from 'common/trace/trace_type'; +import {TimeUtils} from 'common/utils/time_utils'; +import {ImeUtils} from 'viewers/common/ime_utils'; +import {Parser} from './parser'; +import {InputMethodServiceTraceFileProto} from './proto_types'; class ParserInputMethodService extends Parser { constructor(trace: TraceFile) { @@ -39,60 +39,71 @@ class ParserInputMethodService extends Parser { override decodeTrace(buffer: Uint8Array): any[] { const decoded = InputMethodServiceTraceFileProto.decode(buffer); - if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); - } - else { + } else { this.realToElapsedTimeOffsetNs = undefined; } return decoded.entry; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type === TimestampType.ELAPSED) { return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp( + type, + this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos) + ); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: TraceTreeNode): TraceTreeNode { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: TraceTreeNode + ): TraceTreeNode { if (entryProto.elapsedRealtimeNanos === undefined) { - throw Error("Missing elapsedRealtimeNanos on entry"); + throw Error('Missing elapsedRealtimeNanos on entry'); } - let clockTimeNanos: bigint|undefined = undefined; - if (this.realToElapsedTimeOffsetNs !== undefined - && entryProto.elapsedRealtimeNanos !== undefined) { + let clockTimeNanos: bigint | undefined = undefined; + if ( + this.realToElapsedTimeOffsetNs !== undefined && + entryProto.elapsedRealtimeNanos !== undefined + ) { clockTimeNanos = BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs; } - const timestamp = Timestamp.from(timestampType, BigInt(entryProto.elapsedRealtimeNanos), this.realToElapsedTimeOffsetNs); + const timestamp = Timestamp.from( + timestampType, + BigInt(entryProto.elapsedRealtimeNanos), + this.realToElapsedTimeOffsetNs + ); return { - name: TimeUtils.format(timestamp) + " - " + entryProto.where, - kind: "InputMethodService entry", + name: TimeUtils.format(timestamp) + ' - ' + entryProto.where, + kind: 'InputMethodService entry', children: [ { obj: ImeUtils.transformInputConnectionCall(entryProto.inputMethodService), - kind: "InputMethodService", - name: "", + kind: 'InputMethodService', + name: '', children: [], - stableId: "service", - id: "service", - } + stableId: 'service', + id: 'service', + }, ], obj: entryProto, - stableId: "entry", - id: "entry", + stableId: 'entry', + id: 'entry', elapsedRealtimeNanos: entryProto.elapsedRealtimeNanos, clockTimeNanos, }; } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x53, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMSTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_protolog.spec.ts b/tools/winscope-ng/src/parsers/parser_protolog.spec.ts index 0881aceac..4e9d88e96 100644 --- a/tools/winscope-ng/src/parsers/parser_protolog.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_protolog.spec.ts @@ -13,70 +13,66 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; -import {LogMessage} from "../common/trace/protolog"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {LogMessage} from '../common/trace/protolog'; +import {Parser} from './parser'; -describe("ParserProtoLog", () => { +describe('ParserProtoLog', () => { let parser: Parser; const expectedFirstLogMessageElapsed = { - text: "InsetsSource updateVisibility for ITYPE_IME, serverVisible: false clientVisible: false", - time: "14m10s746ms266486ns", - tag: "WindowManager", - level: "DEBUG", - at: "com/android/server/wm/InsetsSourceProvider.java", + text: 'InsetsSource updateVisibility for ITYPE_IME, serverVisible: false clientVisible: false', + time: '14m10s746ms266486ns', + tag: 'WindowManager', + level: 'DEBUG', + at: 'com/android/server/wm/InsetsSourceProvider.java', timestamp: 850746266486n, }; const expectedFirstLogMessageReal = { - text: "InsetsSource updateVisibility for ITYPE_IME, serverVisible: false clientVisible: false", - time: "2022-06-20T12:12:05.377266486", - tag: "WindowManager", - level: "DEBUG", - at: "com/android/server/wm/InsetsSourceProvider.java", + text: 'InsetsSource updateVisibility for ITYPE_IME, serverVisible: false clientVisible: false', + time: '2022-06-20T12:12:05.377266486', + tag: 'WindowManager', + level: 'DEBUG', + at: 'com/android/server/wm/InsetsSourceProvider.java', timestamp: 1655727125377266486n, }; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/ProtoLog.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/ProtoLog.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.PROTO_LOG); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - expect(timestamps.length) - .toEqual(50); + expect(timestamps.length).toEqual(50); const expected = [ new Timestamp(TimestampType.ELAPSED, 850746266486n), new Timestamp(TimestampType.ELAPSED, 850746336718n), new Timestamp(TimestampType.ELAPSED, 850746350430n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.REAL)!; - expect(timestamps.length) - .toEqual(50); + expect(timestamps.length).toEqual(50); const expected = [ new Timestamp(TimestampType.REAL, 1655727125377266486n), new Timestamp(TimestampType.REAL, 1655727125377336718n), new Timestamp(TimestampType.REAL, 1655727125377350430n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); - it("reconstructs human-readable log message (ELAPSED time)", () => { + it('reconstructs human-readable log message (ELAPSED time)', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850746266486n); const entry = parser.getTraceEntry(timestamp)!; @@ -89,7 +85,7 @@ describe("ParserProtoLog", () => { }); }); - it("reconstructs human-readable log message (REAL time)", () => { + it('reconstructs human-readable log message (REAL time)', () => { const timestamp = new Timestamp(TimestampType.REAL, 1655727125377266486n); const entry = parser.getTraceEntry(timestamp)!; diff --git a/tools/winscope-ng/src/parsers/parser_protolog.ts b/tools/winscope-ng/src/parsers/parser_protolog.ts index 63d1126d2..17f006681 100644 --- a/tools/winscope-ng/src/parsers/parser_protolog.ts +++ b/tools/winscope-ng/src/parsers/parser_protolog.ts @@ -14,13 +14,18 @@ * limitations under the License. */ -import {FormattedLogMessage, LogMessage, ProtoLogTraceEntry, UnformattedLogMessage} from "common/trace/protolog"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {ProtoLogFileProto} from "./proto_types"; -import configJson from "../../../../../frameworks/base/data/etc/services.core.protolog.json"; +import { + FormattedLogMessage, + LogMessage, + ProtoLogTraceEntry, + UnformattedLogMessage, +} from 'common/trace/protolog'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import configJson from '../../../../../frameworks/base/data/etc/services.core.protolog.json'; +import {Parser} from './parser'; +import {ProtoLogFileProto} from './proto_types'; class ParserProtoLog extends Parser { constructor(trace: TraceFile) { @@ -39,13 +44,13 @@ class ParserProtoLog extends Parser { const fileProto: any = ProtoLogFileProto.decode(buffer); if (fileProto.version !== ParserProtoLog.PROTOLOG_VERSION) { - const message = "Unsupported ProtoLog trace version"; + const message = 'Unsupported ProtoLog trace version'; console.log(message); throw new TypeError(message); } if (configJson.version !== ParserProtoLog.PROTOLOG_VERSION) { - const message = "Unsupported ProtoLog JSON config version"; + const message = 'Unsupported ProtoLog JSON config version'; console.log(message); throw new TypeError(message); } @@ -59,17 +64,24 @@ class ParserProtoLog extends Parser { return fileProto.log; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type == TimestampType.ELAPSED) { return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } if (type == TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs); + return new Timestamp( + type, + BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs + ); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): ProtoLogTraceEntry { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: any + ): ProtoLogTraceEntry { if (!this.decodedMessages || this.decodedTimestampType !== timestampType) { this.decodedTimestampType = timestampType; this.decodedMessages = this.decodedEntries.map((entryProto: any) => { @@ -87,9 +99,13 @@ class ParserProtoLog extends Parser { } try { - return new UnformattedLogMessage(entryProto, timestampType, this.realToElapsedTimeOffsetNs, message); - } - catch (error) { + return new UnformattedLogMessage( + entryProto, + timestampType, + this.realToElapsedTimeOffsetNs, + message + ); + } catch (error) { if (error instanceof FormatStringMismatchError) { return new FormattedLogMessage(entryProto, timestampType, this.realToElapsedTimeOffsetNs); } @@ -99,9 +115,9 @@ class ParserProtoLog extends Parser { private decodedMessages?: LogMessage[]; private decodedTimestampType?: TimestampType; - private realToElapsedTimeOffsetNs: undefined|bigint = undefined; + private realToElapsedTimeOffsetNs: undefined | bigint = undefined; private static readonly MAGIC_NUMBER = [0x09, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47]; // .PROTOLOG - private static readonly PROTOLOG_VERSION = "1.0.0"; + private static readonly PROTOLOG_VERSION = '1.0.0'; } class FormatStringMismatchError extends Error { diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts b/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts index 00f510701..6ffa460ea 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts @@ -13,54 +13,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {UnitTestUtils} from "test/unit/utils"; -import {Parser} from "./parser"; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserScreenRecording", () => { +describe('ParserScreenRecording', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4"); + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4' + ); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.SCREEN_RECORDING); }); - it ("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - expect(timestamps.length) - .toEqual(123); + expect(timestamps.length).toEqual(123); const expected = [ new Timestamp(TimestampType.ELAPSED, 211827840430n), new Timestamp(TimestampType.ELAPSED, 211842401430n), new Timestamp(TimestampType.ELAPSED, 211862172430n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.REAL)!; - expect(timestamps.length) - .toEqual(123); + expect(timestamps.length).toEqual(123); const expected = [ new Timestamp(TimestampType.REAL, 1666361048792787045n), new Timestamp(TimestampType.REAL, 1666361048807348045n), new Timestamp(TimestampType.REAL, 1666361048827119045n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { { const timestamp = new Timestamp(TimestampType.ELAPSED, 211827840430n); const entry = parser.getTraceEntry(timestamp)!; @@ -72,11 +70,11 @@ describe("ParserScreenRecording", () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 213198917430n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry); - expect(Number(entry.videoTimeSeconds)).toBeCloseTo(1.371077000, 0.001); + expect(Number(entry.videoTimeSeconds)).toBeCloseTo(1.371077, 0.001); } }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { { const timestamp = new Timestamp(TimestampType.REAL, 1666361048792787045n); const entry = parser.getTraceEntry(timestamp)!; @@ -88,7 +86,7 @@ describe("ParserScreenRecording", () => { const timestamp = new Timestamp(TimestampType.REAL, 1666361050163864045n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry); - expect(Number(entry.videoTimeSeconds)).toBeCloseTo(1.371077000, 0.001); + expect(Number(entry.videoTimeSeconds)).toBeCloseTo(1.371077, 0.001); } }); }); diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording.ts b/tools/winscope-ng/src/parsers/parser_screen_recording.ts index d2069846b..90017d963 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording.ts @@ -14,17 +14,16 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {ArrayUtils} from "common/utils/array_utils"; -import {Parser} from "./parser"; -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; -import {ScreenRecordingUtils} from "common/trace/screen_recording_utils"; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; +import {ScreenRecordingUtils} from 'common/trace/screen_recording_utils'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {ArrayUtils} from 'common/utils/array_utils'; +import {Parser} from './parser'; class ScreenRecordingMetadataEntry { - constructor(public timestampElapsedNs: bigint, public timestampRealtimeNs: bigint) { - } + constructor(public timestampElapsedNs: bigint, public timestampRealtimeNs: bigint) {} } class ParserScreenRecording extends Parser { @@ -67,34 +66,48 @@ class ParserScreenRecording extends Parser { const timestampsElapsedNs = this.parseTimestampsElapsedNs(videoData, posTimestamps, count); return timestampsElapsedNs.map((timestampElapsedNs: bigint) => { - return new ScreenRecordingMetadataEntry(timestampElapsedNs, timestampElapsedNs + timeOffsetNs); + return new ScreenRecordingMetadataEntry( + timestampElapsedNs, + timestampElapsedNs + timeOffsetNs + ); }); } - override getTimestamp(type: TimestampType, decodedEntry: ScreenRecordingMetadataEntry): undefined|Timestamp { + override getTimestamp( + type: TimestampType, + decodedEntry: ScreenRecordingMetadataEntry + ): undefined | Timestamp { if (type !== TimestampType.ELAPSED && type !== TimestampType.REAL) { return undefined; } if (type === TimestampType.ELAPSED) { return new Timestamp(type, decodedEntry.timestampElapsedNs); - } - else if (type === TimestampType.REAL) { + } else if (type === TimestampType.REAL) { return new Timestamp(type, decodedEntry.timestampRealtimeNs); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entry: ScreenRecordingMetadataEntry): ScreenRecordingTraceEntry { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entry: ScreenRecordingMetadataEntry + ): ScreenRecordingTraceEntry { const initialTimestamp = this.getTimestamps(TimestampType.ELAPSED)![0]; const currentTimestamp = new Timestamp(TimestampType.ELAPSED, entry.timestampElapsedNs); - const videoTimeSeconds = - ScreenRecordingUtils.timestampToVideoTimeSeconds(initialTimestamp, currentTimestamp); + const videoTimeSeconds = ScreenRecordingUtils.timestampToVideoTimeSeconds( + initialTimestamp, + currentTimestamp + ); const videoData = this.trace.file; return new ScreenRecordingTraceEntry(videoTimeSeconds, videoData); } private searchMagicString(videoData: Uint8Array): number { - let pos = ArrayUtils.searchSubarray(videoData, ParserScreenRecording.WINSCOPE_META_MAGIC_STRING); + let pos = ArrayUtils.searchSubarray( + videoData, + ParserScreenRecording.WINSCOPE_META_MAGIC_STRING + ); if (pos === undefined) { throw new TypeError("video data doesn't contain winscope magic string"); } @@ -102,48 +115,54 @@ class ParserScreenRecording extends Parser { return pos; } - private parseMetadataVersion(videoData: Uint8Array, pos: number) : [number, number] { + private parseMetadataVersion(videoData: Uint8Array, pos: number): [number, number] { if (pos + 4 > videoData.length) { - throw new TypeError("Failed to parse metadata version. Video data is too short."); + throw new TypeError('Failed to parse metadata version. Video data is too short.'); } - const version = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+4)); + const version = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos + 4)); pos += 4; return [pos, version]; } - private parseRealToElapsedTimeOffsetNs(videoData: Uint8Array, pos: number) : [number, bigint] { + private parseRealToElapsedTimeOffsetNs(videoData: Uint8Array, pos: number): [number, bigint] { if (pos + 8 > videoData.length) { - throw new TypeError("Failed to parse realtime-to-elapsed time offset. Video data is too short."); + throw new TypeError( + 'Failed to parse realtime-to-elapsed time offset. Video data is too short.' + ); } - const offset = ArrayUtils.toIntLittleEndian(videoData, pos, pos+8); + const offset = ArrayUtils.toIntLittleEndian(videoData, pos, pos + 8); pos += 8; return [pos, offset]; } - private parseFramesCount(videoData: Uint8Array, pos: number) : [number, number] { + private parseFramesCount(videoData: Uint8Array, pos: number): [number, number] { if (pos + 4 > videoData.length) { - throw new TypeError("Failed to parse frames count. Video data is too short."); + throw new TypeError('Failed to parse frames count. Video data is too short.'); } - const count = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+4)); + const count = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos + 4)); pos += 4; return [pos, count]; } - private parseTimestampsElapsedNs(videoData: Uint8Array, pos: number, count: number) : bigint[] { + private parseTimestampsElapsedNs(videoData: Uint8Array, pos: number, count: number): bigint[] { if (pos + count * 8 > videoData.length) { - throw new TypeError("Failed to parse timestamps. Video data is too short."); + throw new TypeError('Failed to parse timestamps. Video data is too short.'); } const timestamps: bigint[] = []; for (let i = 0; i < count; ++i) { - const timestamp = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8); + const timestamp = ArrayUtils.toUintLittleEndian(videoData, pos, pos + 8); pos += 8; timestamps.push(timestamp); } return timestamps; } - private static readonly MPEG4_MAGIC_NMBER = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32]; // ....ftypmp42 - private static readonly WINSCOPE_META_MAGIC_STRING = [0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x32, 0x23]; // #VV1NSC0PET1ME2# + private static readonly MPEG4_MAGIC_NMBER = [ + 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32, + ]; // ....ftypmp42 + private static readonly WINSCOPE_META_MAGIC_STRING = [ + 0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x32, 0x23, + ]; // #VV1NSC0PET1ME2# } export {ParserScreenRecording}; diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts index a0c8b76f1..3c4aef753 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts @@ -13,52 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {UnitTestUtils} from "test/unit/utils"; -import {Parser} from "./parser"; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserScreenRecordingLegacy", () => { +describe('ParserScreenRecordingLegacy', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/screen_recording.mp4"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/screen_recording.mp4'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.SCREEN_RECORDING); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - expect(timestamps.length) - .toEqual(85); + expect(timestamps.length).toEqual(85); let expected = [ new Timestamp(TimestampType.ELAPSED, 19446131807000n), new Timestamp(TimestampType.ELAPSED, 19446158500000n), new Timestamp(TimestampType.ELAPSED, 19446167117000n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); expected = [ new Timestamp(TimestampType.ELAPSED, 19448470076000n), new Timestamp(TimestampType.ELAPSED, 19448487525000n), new Timestamp(TimestampType.ELAPSED, 19448501007000n), ]; - expect(timestamps.slice(timestamps.length-3, timestamps.length)) - .toEqual(expected); + expect(timestamps.slice(timestamps.length - 3, timestamps.length)).toEqual(expected); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); - it("retrieves trace entry", () => { + it('retrieves trace entry', () => { { const timestamp = new Timestamp(TimestampType.ELAPSED, 19446131807000n); const entry = parser.getTraceEntry(timestamp)!; diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts index c6d6b0793..a53028da0 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {ArrayUtils} from "common/utils/array_utils"; -import {Parser} from "./parser"; -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {ArrayUtils} from 'common/utils/array_utils'; +import {Parser} from './parser'; class ParserScreenRecordingLegacy extends Parser { constructor(trace: TraceFile) { @@ -40,25 +40,32 @@ class ParserScreenRecordingLegacy extends Parser { return this.parseTimestamps(videoData, posTimestamps, count); } - override getTimestamp(type: TimestampType, decodedEntry: Timestamp): undefined|Timestamp { + override getTimestamp(type: TimestampType, decodedEntry: Timestamp): undefined | Timestamp { if (type !== TimestampType.ELAPSED) { return undefined; } return decodedEntry; } - override processDecodedEntry(index: number, timestampType: TimestampType, entry: Timestamp): ScreenRecordingTraceEntry { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entry: Timestamp + ): ScreenRecordingTraceEntry { const currentTimestamp = entry; const initialTimestamp = this.getTimestamps(TimestampType.ELAPSED)![0]; const videoTimeSeconds = - Number(currentTimestamp.getValueNs() - initialTimestamp.getValueNs()) / 1000000000 - + ParserScreenRecordingLegacy.EPSILON; + Number(currentTimestamp.getValueNs() - initialTimestamp.getValueNs()) / 1000000000 + + ParserScreenRecordingLegacy.EPSILON; const videoData = this.trace.file; return new ScreenRecordingTraceEntry(videoTimeSeconds, videoData); } private searchMagicString(videoData: Uint8Array): number { - let pos = ArrayUtils.searchSubarray(videoData, ParserScreenRecordingLegacy.WINSCOPE_META_MAGIC_STRING); + let pos = ArrayUtils.searchSubarray( + videoData, + ParserScreenRecordingLegacy.WINSCOPE_META_MAGIC_STRING + ); if (pos === undefined) { throw new TypeError("video data doesn't contain winscope magic string"); } @@ -66,30 +73,34 @@ class ParserScreenRecordingLegacy extends Parser { return pos; } - private parseFramesCount(videoData: Uint8Array, pos: number) : [number, number] { + private parseFramesCount(videoData: Uint8Array, pos: number): [number, number] { if (pos + 4 > videoData.length) { - throw new TypeError("Failed to parse frames count. Video data is too short."); + throw new TypeError('Failed to parse frames count. Video data is too short.'); } - const framesCount = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+4)); + const framesCount = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos + 4)); pos += 4; return [pos, framesCount]; } private parseTimestamps(videoData: Uint8Array, pos: number, count: number): Timestamp[] { if (pos + count * 8 > videoData.length) { - throw new TypeError("Failed to parse timestamps. Video data is too short."); + throw new TypeError('Failed to parse timestamps. Video data is too short.'); } const timestamps: Timestamp[] = []; for (let i = 0; i < count; ++i) { - const value = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8) * 1000n; + const value = ArrayUtils.toUintLittleEndian(videoData, pos, pos + 8) * 1000n; pos += 8; timestamps.push(new Timestamp(TimestampType.ELAPSED, value)); } return timestamps; } - private static readonly MPEG4_MAGIC_NMBER = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32]; // ....ftypmp42 - private static readonly WINSCOPE_META_MAGIC_STRING = [0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x21, 0x23]; // #VV1NSC0PET1ME!# + private static readonly MPEG4_MAGIC_NMBER = [ + 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32, + ]; // ....ftypmp42 + private static readonly WINSCOPE_META_MAGIC_STRING = [ + 0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x21, 0x23, + ]; // #VV1NSC0PET1ME!# private static readonly EPSILON = 0.00001; } diff --git a/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts b/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts index 814e5094e..163048d2e 100644 --- a/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts @@ -13,72 +13,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry"; -import {Layer} from "common/trace/flickerlib/layers/Layer"; -import {UnitTestUtils} from "test/unit/utils"; -import {Parser} from "./parser"; +import {Layer} from 'common/trace/flickerlib/layers/Layer'; +import {LayerTraceEntry} from 'common/trace/flickerlib/layers/LayerTraceEntry'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserSurfaceFlinger", () => { - it("decodes layer state flags", async () => { - const parser = - await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/SurfaceFlinger.pb"); +describe('ParserSurfaceFlinger', () => { + it('decodes layer state flags', async () => { + const parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/SurfaceFlinger.pb' + ); const timestamp = new Timestamp(TimestampType.REAL, 1659107089102062832n); const entry = parser.getTraceEntry(timestamp); { const layer = entry.flattenedLayers.find((layer: Layer) => layer.id === 27); - expect(layer.name).toEqual("Leaf:24:25#27"); + expect(layer.name).toEqual('Leaf:24:25#27'); expect(layer.flags).toEqual(0x0); - expect(layer.verboseFlags).toEqual(""); + expect(layer.verboseFlags).toEqual(''); } { const layer = entry.flattenedLayers.find((layer: Layer) => layer.id === 48); - expect(layer.name).toEqual("Task=4#48"); + expect(layer.name).toEqual('Task=4#48'); expect(layer.flags).toEqual(0x1); - expect(layer.verboseFlags).toEqual("HIDDEN (0x1)"); + expect(layer.verboseFlags).toEqual('HIDDEN (0x1)'); } { const layer = entry.flattenedLayers.find((layer: Layer) => layer.id === 77); - expect(layer.name).toEqual("Wallpaper BBQ wrapper#77"); + expect(layer.name).toEqual('Wallpaper BBQ wrapper#77'); expect(layer.flags).toEqual(0x100); - expect(layer.verboseFlags).toEqual("ENABLE_BACKPRESSURE (0x100)"); + expect(layer.verboseFlags).toEqual('ENABLE_BACKPRESSURE (0x100)'); } }); - describe("trace with elapsed + real timestamp", () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/SurfaceFlinger.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/SurfaceFlinger.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const expected = [ new Timestamp(TimestampType.ELAPSED, 14500282843n), new Timestamp(TimestampType.ELAPSED, 14631249355n), new Timestamp(TimestampType.ELAPSED, 15403446377n), ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const expected = [ new Timestamp(TimestampType.REAL, 1659107089102062832n), new Timestamp(TimestampType.REAL, 1659107089233029344n), new Timestamp(TimestampType.REAL, 1659107090005226366n), ]; - expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 14631249355n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(LayerTraceEntry); @@ -86,7 +85,7 @@ describe("ParserSurfaceFlinger", () => { expect(BigInt(entry.timestamp.unixNanos.toString())).toEqual(1659107089233029344n); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089233029376n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(LayerTraceEntry); @@ -94,43 +93,43 @@ describe("ParserSurfaceFlinger", () => { expect(BigInt(entry.timestamp.unixNanos.toString())).toEqual(1659107089233029344n); }); - it("formats entry timestamps", () => { + it('formats entry timestamps', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089233029344n); const entry = parser.getTraceEntry(timestamp)!; - expect(entry.name).toEqual("2022-07-29T15:04:49.233029376"); + expect(entry.name).toEqual('2022-07-29T15:04:49.233029376'); }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/SurfaceFlinger.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/SurfaceFlinger.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); }); - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) - .toEqual(new Timestamp(TimestampType.ELAPSED, 850335483446n)); + it('provides elapsed timestamps', () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]).toEqual( + new Timestamp(TimestampType.ELAPSED, 850335483446n) + ); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); - it("formats entry timestamps", () => { + it('formats entry timestamps', () => { expect(() => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089233029344n); parser.getTraceEntry(timestamp); - }).toThrow(Error("Timestamps with type \"REAL\" not available")); + }).toThrow(Error('Timestamps with type "REAL" not available')); const timestamp = new Timestamp(TimestampType.ELAPSED, 850335483446n); const entry = parser.getTraceEntry(timestamp)!; - expect(entry.name).toEqual("14m10s335ms483446ns"); + expect(entry.name).toEqual('14m10s335ms483446ns'); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_surface_flinger.ts b/tools/winscope-ng/src/parsers/parser_surface_flinger.ts index 67f341218..5147c9add 100644 --- a/tools/winscope-ng/src/parsers/parser_surface_flinger.ts +++ b/tools/winscope-ng/src/parsers/parser_surface_flinger.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {LayersTraceFileProto} from "./proto_types"; +import {LayerTraceEntry} from 'common/trace/flickerlib/layers/LayerTraceEntry'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {Parser} from './parser'; +import {LayersTraceFileProto} from './proto_types'; class ParserSurfaceFlinger extends Parser { constructor(trace: TraceFile) { @@ -37,31 +37,37 @@ class ParserSurfaceFlinger extends Parser { override decodeTrace(buffer: Uint8Array): any[] { const decoded = LayersTraceFileProto.decode(buffer); - if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); } else { - console.warn("Missing realToElapsedTimeOffsetNanos property on SF trace proto"); + console.warn('Missing realToElapsedTimeOffsetNanos property on SF trace proto'); this.realToElapsedTimeOffsetNs = undefined; } return decoded.entry; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { - const isDump = !Object.prototype.hasOwnProperty.call(entryProto, "elapsedRealtimeNanos"); + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { + const isDump = !Object.prototype.hasOwnProperty.call(entryProto, 'elapsedRealtimeNanos'); if (type === TimestampType.ELAPSED) { return isDump ? new Timestamp(type, 0n) : new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { return isDump ? new Timestamp(type, 0n) - : new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + : new Timestamp( + type, + this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos) + ); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): LayerTraceEntry { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: any + ): LayerTraceEntry { return LayerTraceEntry.fromProto( entryProto.layers.layers, entryProto.displays, @@ -75,8 +81,8 @@ class ParserSurfaceFlinger extends Parser { ); } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x4c, 0x59, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45]; // .LYRTRACE } -export { ParserSurfaceFlinger }; +export {ParserSurfaceFlinger}; diff --git a/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts b/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts index 6810d3d59..afba3b814 100644 --- a/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts @@ -13,40 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry"; -import {UnitTestUtils} from "test/unit/utils"; -import {Parser} from "./parser"; +import {LayerTraceEntry} from 'common/trace/flickerlib/layers/LayerTraceEntry'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserSurfaceFlingerDump", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserSurfaceFlingerDump', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; const DUMP_REAL_TIME = 1659176624505188647n; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/dump_SurfaceFlinger.pb"); + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/dump_SurfaceFlinger.pb' + ); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); }); - it("provides elapsed timestamp", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 0n), - ]; + it('provides elapsed timestamp', () => { + const expected = [new Timestamp(TimestampType.ELAPSED, 0n)]; expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); }); - it("provides real timestamp (always zero)", () => { - const expected = [ - new Timestamp(TimestampType.REAL, 0n), - ]; + it('provides real timestamp (always zero)', () => { + const expected = [new Timestamp(TimestampType.REAL, 0n)]; expect(parser.getTimestamps(TimestampType.REAL)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 0n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(LayerTraceEntry); @@ -55,21 +53,19 @@ describe("ParserSurfaceFlingerDump", () => { }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/dump_SurfaceFlinger.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/dump_SurfaceFlinger.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); }); - it("provides elapsed timestamp (always zero)", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 0n), - ]; + it('provides elapsed timestamp (always zero)', () => { + const expected = [new Timestamp(TimestampType.ELAPSED, 0n)]; expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); }); diff --git a/tools/winscope-ng/src/parsers/parser_transactions.spec.ts b/tools/winscope-ng/src/parsers/parser_transactions.spec.ts index 0994ffbbd..6363aeafd 100644 --- a/tools/winscope-ng/src/parsers/parser_transactions.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_transactions.spec.ts @@ -13,83 +13,82 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; -import {TransactionsTraceEntry} from "../common/trace/transactions"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {TransactionsTraceEntry} from '../common/trace/transactions'; +import {Parser} from './parser'; -describe("ParserTransactions", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserTransactions', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/Transactions.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/Transactions.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.TRANSACTIONS); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - expect(timestamps.length) - .toEqual(712); + expect(timestamps.length).toEqual(712); const expected = [ new Timestamp(TimestampType.ELAPSED, 2450981445n), new Timestamp(TimestampType.ELAPSED, 2517952515n), new Timestamp(TimestampType.ELAPSED, 4021151449n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.REAL)!; - expect(timestamps.length) - .toEqual(712); + expect(timestamps.length).toEqual(712); const expected = [ new Timestamp(TimestampType.REAL, 1659507541051480997n), new Timestamp(TimestampType.REAL, 1659507541118452067n), new Timestamp(TimestampType.REAL, 1659507542621651001n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 2517952515n); const entry: TransactionsTraceEntry = parser.getTraceEntry(timestamp)!; expect(entry.currentEntryIndex).toEqual(1); - expect(BigInt(entry.entriesProto[entry.currentEntryIndex].elapsedRealtimeNanos)) - .toEqual(2517952515n); + expect(BigInt(entry.entriesProto[entry.currentEntryIndex].elapsedRealtimeNanos)).toEqual( + 2517952515n + ); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659507541118452067n); const entry: TransactionsTraceEntry = parser.getTraceEntry(timestamp)!; expect(entry.currentEntryIndex).toEqual(1); - expect(BigInt(entry.entriesProto[entry.currentEntryIndex].elapsedRealtimeNanos)) - .toEqual(2517952515n); + expect(BigInt(entry.entriesProto[entry.currentEntryIndex].elapsedRealtimeNanos)).toEqual( + 2517952515n + ); }); it("decodes 'what' field in proto", () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 2517952515n); const entry: TransactionsTraceEntry = parser.getTraceEntry(timestamp)!; - expect(entry.entriesProto[0].transactions[0].layerChanges[0].what) - .toEqual("eLayerChanged"); - expect(entry.entriesProto[0].transactions[1].layerChanges[0].what) - .toEqual("eFlagsChanged | eDestinationFrameChanged"); - expect(entry.entriesProto[222].transactions[1].displayChanges[0].what) - .toEqual("eLayerStackChanged | eDisplayProjectionChanged | eFlagsChanged"); + expect(entry.entriesProto[0].transactions[0].layerChanges[0].what).toEqual('eLayerChanged'); + expect(entry.entriesProto[0].transactions[1].layerChanges[0].what).toEqual( + 'eFlagsChanged | eDestinationFrameChanged' + ); + expect(entry.entriesProto[222].transactions[1].displayChanges[0].what).toEqual( + 'eLayerStackChanged | eDisplayProjectionChanged | eFlagsChanged' + ); }); - it("includes timestamp type in TransactionsTraceEntry", () => { + it('includes timestamp type in TransactionsTraceEntry', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659507541118452067n); const entry: TransactionsTraceEntry = parser.getTraceEntry(timestamp)!; @@ -98,38 +97,35 @@ describe("ParserTransactions", () => { }); }); - describe("trace with elapsed (only) timestamp", () => { + describe('trace with elapsed (only) timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/Transactions.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/Transactions.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.TRANSACTIONS); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - expect(timestamps.length) - .toEqual(4997); + expect(timestamps.length).toEqual(4997); const expected = [ new Timestamp(TimestampType.ELAPSED, 14862317023n), new Timestamp(TimestampType.ELAPSED, 14873423549n), new Timestamp(TimestampType.ELAPSED, 14884850511n), ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); + expect(timestamps.slice(0, 3)).toEqual(expected); }); it("doesn't provide real timestamps", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); - it("includes timestamp type in TransactionsTraceEntry", () => { + it('includes timestamp type in TransactionsTraceEntry', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 14884850511n); const entry: TransactionsTraceEntry = parser.getTraceEntry(timestamp)!; diff --git a/tools/winscope-ng/src/parsers/parser_transactions.ts b/tools/winscope-ng/src/parsers/parser_transactions.ts index e5196ac83..155517c4c 100644 --- a/tools/winscope-ng/src/parsers/parser_transactions.ts +++ b/tools/winscope-ng/src/parsers/parser_transactions.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {TransactionsTraceEntry} from "common/trace/transactions"; -import {Parser} from "./parser"; -import {TransactionsTraceFileProto} from "./proto_types"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {TransactionsTraceEntry} from 'common/trace/transactions'; +import {Parser} from './parser'; +import {TransactionsTraceFileProto} from './proto_types'; class ParserTransactions extends Parser { constructor(trace: TraceFile) { @@ -39,10 +39,9 @@ class ParserTransactions extends Parser { const decodedProto = TransactionsTraceFileProto.decode(buffer); this.decodeWhatFields(decodedProto); - if (Object.prototype.hasOwnProperty.call(decodedProto, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decodedProto, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decodedProto.realToElapsedTimeOffsetNanos); - } - else { + } else { this.realToElapsedTimeOffsetNs = undefined; } return decodedProto.entry; @@ -50,7 +49,7 @@ class ParserTransactions extends Parser { private decodeWhatFields(decodedProto: any) { const decodeBitset32 = (bitset: number, EnumProto: any) => { - return Object.keys(EnumProto).filter(key => { + return Object.keys(EnumProto).filter((key) => { const value = EnumProto[key]; return (bitset & value) != 0; }); @@ -58,13 +57,15 @@ class ParserTransactions extends Parser { const concatBitsetTokens = (tokens: string[]) => { if (tokens.length == 0) { - return "0"; + return '0'; } - return tokens.join(" | "); + return tokens.join(' | '); }; - const LayerStateChangesLsbEnum = (TransactionsTraceFileProto?.parent).LayerState.ChangesLsb; - const LayerStateChangesMsbEnum = (TransactionsTraceFileProto?.parent).LayerState.ChangesMsb; + const LayerStateChangesLsbEnum = (TransactionsTraceFileProto?.parent).LayerState + .ChangesLsb; + const LayerStateChangesMsbEnum = (TransactionsTraceFileProto?.parent).LayerState + .ChangesMsb; const DisplayStateChangesEnum = (TransactionsTraceFileProto?.parent).DisplayState.Changes; decodedProto.entry.forEach((transactionTraceEntry: any) => { @@ -92,21 +93,32 @@ class ParserTransactions extends Parser { }); } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type === TimestampType.ELAPSED) { return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp( + type, + this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos) + ); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): TransactionsTraceEntry { - return new TransactionsTraceEntry(this.decodedEntries, timestampType, this.realToElapsedTimeOffsetNs, index); + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: any + ): TransactionsTraceEntry { + return new TransactionsTraceEntry( + this.decodedEntries, + timestampType, + this.realToElapsedTimeOffsetNs, + index + ); } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x54, 0x4e, 0x58, 0x54, 0x52, 0x41, 0x43, 0x45]; // .TNXTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts b/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts index 2ad3f3562..cf43b615e 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts @@ -13,45 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; +import {WindowManagerState} from 'common/trace/flickerlib/windows/WindowManagerState'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserWindowManager", () => { - describe("trace with elapsed + real timestamp", () => { +describe('ParserWindowManager', () => { + describe('trace with elapsed + real timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/WindowManager.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/WindowManager.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); }); - it("provides elapsed timestamps", () => { + it('provides elapsed timestamps', () => { const expected = [ new Timestamp(TimestampType.ELAPSED, 14474594000n), new Timestamp(TimestampType.ELAPSED, 15398076788n), new Timestamp(TimestampType.ELAPSED, 15409222011n), ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)).toEqual(expected); }); - it("provides real timestamps", () => { + it('provides real timestamps', () => { const expected = [ new Timestamp(TimestampType.REAL, 1659107089075566202n), new Timestamp(TimestampType.REAL, 1659107089999048990n), new Timestamp(TimestampType.REAL, 1659107090010194213n), ]; - expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)).toEqual(expected); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 15398076788n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(WindowManagerState); @@ -59,7 +57,7 @@ describe("ParserWindowManager", () => { expect(BigInt(entry.timestamp.unixNanos.toString())).toEqual(1659107089999048990n); }); - it("retrieves trace entry from real timestamp", () => { + it('retrieves trace entry from real timestamp', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048990n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(WindowManagerState); @@ -67,50 +65,49 @@ describe("ParserWindowManager", () => { expect(BigInt(entry.timestamp.unixNanos.toString())).toEqual(1659107089999048990n); }); - it("formats entry timestamps", () => { + it('formats entry timestamps', () => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048990n); const entry = parser.getTraceEntry(timestamp)!; - expect(entry.name).toEqual("2022-07-29T15:04:49.999048960"); + expect(entry.name).toEqual('2022-07-29T15:04:49.999048960'); }); }); - describe("trace elapsed timestamp", () => { + describe('trace elapsed timestamp', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/WindowManager.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/WindowManager.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); }); - it("provides timestamps", () => { + it('provides timestamps', () => { const expected = [ new Timestamp(TimestampType.ELAPSED, 850254319343n), new Timestamp(TimestampType.ELAPSED, 850763506110n), new Timestamp(TimestampType.ELAPSED, 850782750048n), ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); }); - it("retrieves trace entry", () => { + it('retrieves trace entry', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(WindowManagerState); expect(BigInt(entry.timestamp.elapsedNanos.toString())).toEqual(850254319343n); }); - it("formats entry timestamps", () => { + it('formats entry timestamps', () => { expect(() => { const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048990n); parser.getTraceEntry(timestamp); - }).toThrow(Error("Timestamps with type \"REAL\" not available")); + }).toThrow(Error('Timestamps with type "REAL" not available')); const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); const entry = parser.getTraceEntry(timestamp)!; - expect(entry.name).toEqual("14m10s254ms319343ns"); + expect(entry.name).toEqual('14m10s254ms319343ns'); }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_window_manager.ts b/tools/winscope-ng/src/parsers/parser_window_manager.ts index 995943c92..09914ea85 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {WindowManagerTraceFileProto} from "./proto_types"; -import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; +import {WindowManagerState} from 'common/trace/flickerlib/windows/WindowManagerState'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {Parser} from './parser'; +import {WindowManagerTraceFileProto} from './proto_types'; class ParserWindowManager extends Parser { constructor(trace: TraceFile) { @@ -36,26 +36,31 @@ class ParserWindowManager extends Parser { override decodeTrace(buffer: Uint8Array): any[] { const decoded = WindowManagerTraceFileProto.decode(buffer); - if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) { this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); - } - else { + } else { this.realToElapsedTimeOffsetNs = undefined; } return decoded.entry; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type === TimestampType.ELAPSED) { return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); - } - else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp( + type, + this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos) + ); } return undefined; } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): WindowManagerState { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: any + ): WindowManagerState { return WindowManagerState.fromProto( entryProto.windowManagerService, BigInt(entryProto.elapsedRealtimeNanos.toString()), @@ -65,7 +70,7 @@ class ParserWindowManager extends Parser { ); } - private realToElapsedTimeOffsetNs: undefined|bigint; + private realToElapsedTimeOffsetNs: undefined | bigint; private static readonly MAGIC_NUMBER = [0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45]; // .WINTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts b/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts index 5f4e10a01..5afe279a8 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts @@ -13,37 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {UnitTestUtils} from "test/unit/utils"; +import {WindowManagerState} from 'common/trace/flickerlib/windows/WindowManagerState'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from './parser'; -describe("ParserWindowManagerDump", () => { +describe('ParserWindowManagerDump', () => { let parser: Parser; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/dump_WindowManager.pb"); + parser = await UnitTestUtils.getParser('traces/dump_WindowManager.pb'); }); - it("has expected trace type", () => { + it('has expected trace type', () => { expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); }); - it("provides elapsed timestamp (always zero)", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 0n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); + it('provides elapsed timestamp (always zero)', () => { + const expected = [new Timestamp(TimestampType.ELAPSED, 0n)]; + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); }); it("doesn't provide real timestamp (never)", () => { - expect(parser.getTimestamps(TimestampType.REAL)) - .toEqual(undefined); + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); }); - it("retrieves trace entry from elapsed timestamp", () => { + it('retrieves trace entry from elapsed timestamp', () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 0n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(WindowManagerState); diff --git a/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts b/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts index 602b4cbc2..cee00a9f4 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "./parser"; -import {WindowManagerServiceDumpProto} from "./proto_types"; -import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; +import {WindowManagerState} from 'common/trace/flickerlib/windows/WindowManagerState'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {Parser} from './parser'; +import {WindowManagerServiceDumpProto} from './proto_types'; class ParserWindowManagerDump extends Parser { constructor(trace: TraceFile) { @@ -47,14 +47,18 @@ class ParserWindowManagerDump extends Parser { return [entryProto]; } - override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { if (type !== TimestampType.ELAPSED) { return undefined; } return new Timestamp(TimestampType.ELAPSED, 0n); } - override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): WindowManagerState { + override processDecodedEntry( + index: number, + timestampType: TimestampType, + entryProto: any + ): WindowManagerState { return WindowManagerState.fromProto(entryProto); } } diff --git a/tools/winscope-ng/src/parsers/proto_types.js b/tools/winscope-ng/src/parsers/proto_types.js index 9763ca5a2..331667891 100644 --- a/tools/winscope-ng/src/parsers/proto_types.js +++ b/tools/winscope-ng/src/parsers/proto_types.js @@ -13,28 +13,46 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as protobuf from "protobufjs"; -import Long from "long"; +import Long from 'long'; +import * as protobuf from 'protobufjs'; protobuf.util.Long = Long; // otherwise 64-bit types would be decoded as javascript number (only 53-bits precision) protobuf.configure(); -import accessibilityJson from "frameworks/base/core/proto/android/server/accessibilitytrace.proto"; -import inputMethodClientsJson from "frameworks/base/core/proto/android/view/inputmethod/inputmethodeditortrace.proto"; -import layersJson from "frameworks/native/services/surfaceflinger/layerproto/layerstrace.proto"; -import protoLogJson from "frameworks/base/core/proto/android/internal/protolog.proto"; -import transactionsJson from "frameworks/native/services/surfaceflinger/layerproto/transactions.proto"; -import windowManagerJson from "frameworks/base/core/proto/android/server/windowmanagertrace.proto"; +import protoLogJson from 'frameworks/base/core/proto/android/internal/protolog.proto'; +import accessibilityJson from 'frameworks/base/core/proto/android/server/accessibilitytrace.proto'; +import windowManagerJson from 'frameworks/base/core/proto/android/server/windowmanagertrace.proto'; +import inputMethodClientsJson from 'frameworks/base/core/proto/android/view/inputmethod/inputmethodeditortrace.proto'; +import layersJson from 'frameworks/native/services/surfaceflinger/layerproto/layerstrace.proto'; +import transactionsJson from 'frameworks/native/services/surfaceflinger/layerproto/transactions.proto'; -const AccessibilityTraceFileProto = protobuf.Root.fromJSON(accessibilityJson).lookupType("com.android.server.accessibility.AccessibilityTraceFileProto"); -const InputMethodClientsTraceFileProto = protobuf.Root.fromJSON(inputMethodClientsJson).lookupType("android.view.inputmethod.InputMethodClientsTraceFileProto"); -const InputMethodManagerServiceTraceFileProto = protobuf.Root.fromJSON(inputMethodClientsJson).lookupType("android.view.inputmethod.InputMethodManagerServiceTraceFileProto"); -const InputMethodServiceTraceFileProto = protobuf.Root.fromJSON(inputMethodClientsJson).lookupType("android.view.inputmethod.InputMethodServiceTraceFileProto"); -const LayersTraceFileProto = protobuf.Root.fromJSON(layersJson).lookupType("android.surfaceflinger.LayersTraceFileProto"); -const ProtoLogFileProto = protobuf.Root.fromJSON(protoLogJson).lookupType("com.android.internal.protolog.ProtoLogFileProto"); -const TransactionsTraceFileProto = protobuf.Root.fromJSON(transactionsJson).lookupType("android.surfaceflinger.proto.TransactionTraceFile"); -const WindowManagerServiceDumpProto = protobuf.Root.fromJSON(windowManagerJson).lookupType("com.android.server.wm.WindowManagerServiceDumpProto"); -const WindowManagerTraceFileProto = protobuf.Root.fromJSON(windowManagerJson).lookupType("com.android.server.wm.WindowManagerTraceFileProto"); +const AccessibilityTraceFileProto = protobuf.Root.fromJSON(accessibilityJson).lookupType( + 'com.android.server.accessibility.AccessibilityTraceFileProto' +); +const InputMethodClientsTraceFileProto = protobuf.Root.fromJSON(inputMethodClientsJson).lookupType( + 'android.view.inputmethod.InputMethodClientsTraceFileProto' +); +const InputMethodManagerServiceTraceFileProto = protobuf.Root.fromJSON( + inputMethodClientsJson +).lookupType('android.view.inputmethod.InputMethodManagerServiceTraceFileProto'); +const InputMethodServiceTraceFileProto = protobuf.Root.fromJSON(inputMethodClientsJson).lookupType( + 'android.view.inputmethod.InputMethodServiceTraceFileProto' +); +const LayersTraceFileProto = protobuf.Root.fromJSON(layersJson).lookupType( + 'android.surfaceflinger.LayersTraceFileProto' +); +const ProtoLogFileProto = protobuf.Root.fromJSON(protoLogJson).lookupType( + 'com.android.internal.protolog.ProtoLogFileProto' +); +const TransactionsTraceFileProto = protobuf.Root.fromJSON(transactionsJson).lookupType( + 'android.surfaceflinger.proto.TransactionTraceFile' +); +const WindowManagerServiceDumpProto = protobuf.Root.fromJSON(windowManagerJson).lookupType( + 'com.android.server.wm.WindowManagerServiceDumpProto' +); +const WindowManagerTraceFileProto = protobuf.Root.fromJSON(windowManagerJson).lookupType( + 'com.android.server.wm.WindowManagerTraceFileProto' +); export { AccessibilityTraceFileProto, @@ -45,5 +63,5 @@ export { ProtoLogFileProto, TransactionsTraceFileProto, WindowManagerServiceDumpProto, - WindowManagerTraceFileProto + WindowManagerTraceFileProto, }; diff --git a/tools/winscope-ng/src/polyfills.ts b/tools/winscope-ng/src/polyfills.ts index ef841f852..e4555ed11 100644 --- a/tools/winscope-ng/src/polyfills.ts +++ b/tools/winscope-ng/src/polyfills.ts @@ -45,8 +45,7 @@ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ -import "zone.js"; // Included with Angular CLI. - +import 'zone.js'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/tools/winscope-ng/src/test/common/blob.ts b/tools/winscope-ng/src/test/common/blob.ts index 0646a7c85..d0205f97e 100644 --- a/tools/winscope-ng/src/test/common/blob.ts +++ b/tools/winscope-ng/src/test/common/blob.ts @@ -18,7 +18,7 @@ class Blob { constructor(buffer: ArrayBuffer) { this.size = buffer.byteLength; - this.type = "application/octet-stream"; + this.type = 'application/octet-stream'; this.buffer = buffer; } @@ -29,15 +29,15 @@ class Blob { } slice(start?: number, end?: number, contentType?: string): Blob { - throw new Error("Not implemented!"); + throw new Error('Not implemented!'); } stream(): any { - throw new Error("Not implemented!"); + throw new Error('Not implemented!'); } text(): Promise { - throw new Error("Not implemented!"); + throw new Error('Not implemented!'); } readonly size: number; diff --git a/tools/winscope-ng/src/test/common/file.ts b/tools/winscope-ng/src/test/common/file.ts index f1205b672..e7de1af6e 100644 --- a/tools/winscope-ng/src/test/common/file.ts +++ b/tools/winscope-ng/src/test/common/file.ts @@ -15,7 +15,7 @@ */ // This class is needed for testing because Node.js doesn't provide the Web API's File type -import { Blob } from "./blob"; +import {Blob} from './blob'; class File extends Blob { constructor(buffer: ArrayBuffer, fileName: string) { @@ -25,7 +25,7 @@ class File extends Blob { readonly lastModified: number = 0; readonly name: string; - readonly webkitRelativePath: string = ""; + readonly webkitRelativePath: string = ''; } export {File}; diff --git a/tools/winscope-ng/src/test/common/utils.ts b/tools/winscope-ng/src/test/common/utils.ts index acdb50c81..95f672b83 100644 --- a/tools/winscope-ng/src/test/common/utils.ts +++ b/tools/winscope-ng/src/test/common/utils.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as fs from "fs"; -import * as path from "path"; -import {Blob} from "./blob"; -import {File} from "./file"; +import * as fs from 'fs'; +import * as path from 'path'; +import {Blob} from './blob'; +import {File} from './file'; class CommonTestUtils { static async getFixtureFile(filename: string): Promise { @@ -33,12 +33,12 @@ class CommonTestUtils { if (path.isAbsolute(filename)) { return filename; } - return path.join(CommonTestUtils.getProjectRootPath(), "src/test/fixtures", filename); + return path.join(CommonTestUtils.getProjectRootPath(), 'src/test/fixtures', filename); } static getProjectRootPath(): string { let root = __dirname; - while (path.basename(root) !== "winscope-ng") { + while (path.basename(root) !== 'winscope-ng') { root = path.dirname(root); } return root; diff --git a/tools/winscope-ng/src/test/e2e/cross_tool_protocol.spec.ts b/tools/winscope-ng/src/test/e2e/cross_tool_protocol.spec.ts index ef8e54b6e..1d941fb6e 100644 --- a/tools/winscope-ng/src/test/e2e/cross_tool_protocol.spec.ts +++ b/tools/winscope-ng/src/test/e2e/cross_tool_protocol.spec.ts @@ -14,28 +14,28 @@ * limitations under the License. */ -import {browser, by, element, ElementFinder} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element, ElementFinder} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Cross-Tool Protocol", () => { - const WINSCOPE_URL = "http://localhost:8080"; - const REMOTE_TOOL_MOCK_URL = "http://localhost:8081"; +describe('Cross-Tool Protocol', () => { + const WINSCOPE_URL = 'http://localhost:8080'; + const REMOTE_TOOL_MOCK_URL = 'http://localhost:8081'; - const TIMESTAMP_IN_BUGREPORT_MESSAGE = "1670509911000000000"; - const TIMESTAMP_FROM_REMOTE_TOOL_TO_WINSCOPE = "1670509912000000000"; - const TIMESTAMP_FROM_WINSCOPE_TO_REMOTE_TOOL = "1670509913000000000"; + const TIMESTAMP_IN_BUGREPORT_MESSAGE = '1670509911000000000'; + const TIMESTAMP_FROM_REMOTE_TOOL_TO_WINSCOPE = '1670509912000000000'; + const TIMESTAMP_FROM_WINSCOPE_TO_REMOTE_TOOL = '1670509913000000000'; beforeAll(async () => { await browser.manage().timeouts().implicitlyWait(5000); - await checkServerIsUp("Remote tool mock", REMOTE_TOOL_MOCK_URL); - await checkServerIsUp("Winscope", WINSCOPE_URL); + await checkServerIsUp('Remote tool mock', REMOTE_TOOL_MOCK_URL); + await checkServerIsUp('Winscope', WINSCOPE_URL); }); beforeEach(async () => { await browser.get(REMOTE_TOOL_MOCK_URL); }); - it("allows communication between remote tool and Winscope", async () => { + it('allows communication between remote tool and Winscope', async () => { await openWinscopeTabFromRemoteTool(); await waitWinscopeTabIsOpen(); @@ -65,19 +65,21 @@ describe("Cross-Tool Protocol", () => { const openWinscopeTabFromRemoteTool = async () => { await browser.switchTo().window(await getWindowHandleRemoteToolMock()); - const buttonElement = element(by.css(".button-open-winscope")); + const buttonElement = element(by.css('.button-open-winscope')); await buttonElement.click(); }; const sendBugreportToWinscope = async () => { await browser.switchTo().window(await getWindowHandleRemoteToolMock()); - const inputFileElement = element(by.css(".button-upload-bugreport")); - await inputFileElement.sendKeys(E2eTestUtils.getFixturePath("bugreports/bugreport_stripped.zip")); + const inputFileElement = element(by.css('.button-upload-bugreport')); + await inputFileElement.sendKeys( + E2eTestUtils.getFixturePath('bugreports/bugreport_stripped.zip') + ); }; const checkWinscopeRendersUploadView = async () => { await browser.switchTo().window(await getWindowHandleWinscope()); - const isPresent = await element(by.css(".uploaded-files")).isPresent(); + const isPresent = await element(by.css('.uploaded-files')).isPresent(); expect(isPresent).toBeTruthy(); }; @@ -92,35 +94,37 @@ describe("Cross-Tool Protocol", () => { }; const waitWinscopeTabIsOpen = async () => { - await browser.wait(async () => { - const handles = await browser.getAllWindowHandles(); - return handles.length >= 2; - }, - 20000, - "The Winscope tab did not open"); + await browser.wait( + async () => { + const handles = await browser.getAllWindowHandles(); + return handles.length >= 2; + }, + 20000, + 'The Winscope tab did not open' + ); }; const checkWinscopeRenderedSurfaceFlingerView = async () => { await browser.switchTo().window(await getWindowHandleWinscope()); - const viewerPresent = await element(by.css("viewer-surface-flinger")).isPresent(); + const viewerPresent = await element(by.css('viewer-surface-flinger')).isPresent(); expect(viewerPresent).toBeTruthy(); }; const checkWinscopeRenderedAllViewTabs = async () => { - const linkElements = await element.all(by.css(".tabs-navigation-bar a")); + const linkElements = await element.all(by.css('.tabs-navigation-bar a')); const actualLinks = await Promise.all( - (linkElements as ElementFinder[]).map(async linkElement => await linkElement.getText()) + (linkElements as ElementFinder[]).map(async (linkElement) => await linkElement.getText()) ); const expectedLinks = [ - "Input Method Clients", - "Input Method Manager Service", - "Input Method Service", - "ProtoLog", - "Surface Flinger", - "Transactions", - "Window Manager", + 'Input Method Clients', + 'Input Method Manager Service', + 'Input Method Service', + 'ProtoLog', + 'Surface Flinger', + 'Transactions', + 'Window Manager', ]; expect(actualLinks.sort()).toEqual(expectedLinks.sort()); @@ -128,40 +132,39 @@ describe("Cross-Tool Protocol", () => { const checkWinscopeAppliedTimestampInBugreportMessage = async () => { await browser.switchTo().window(await getWindowHandleWinscope()); - const inputElement = element(by.css("input[name=\"nsTimeInput\"]")); - const valueWithNsSuffix = await inputElement.getAttribute("value"); - expect(valueWithNsSuffix).toEqual(TIMESTAMP_IN_BUGREPORT_MESSAGE + " ns"); + const inputElement = element(by.css('input[name="nsTimeInput"]')); + const valueWithNsSuffix = await inputElement.getAttribute('value'); + expect(valueWithNsSuffix).toEqual(TIMESTAMP_IN_BUGREPORT_MESSAGE + ' ns'); }; const sendTimestampToWinscope = async () => { await browser.switchTo().window(await getWindowHandleRemoteToolMock()); - const inputElement = element(by.css(".input-timestamp")); + const inputElement = element(by.css('.input-timestamp')); await inputElement.sendKeys(TIMESTAMP_FROM_REMOTE_TOOL_TO_WINSCOPE); - const buttonElement = element(by.css(".button-send-timestamp")); + const buttonElement = element(by.css('.button-send-timestamp')); await buttonElement.click(); }; const checkWinscopeReceivedTimestamp = async () => { await browser.switchTo().window(await getWindowHandleWinscope()); - const inputElement = element(by.css("input[name=\"nsTimeInput\"]")); - const valueWithNsSuffix = await inputElement.getAttribute("value"); - expect(valueWithNsSuffix).toEqual(TIMESTAMP_FROM_REMOTE_TOOL_TO_WINSCOPE + " ns"); + const inputElement = element(by.css('input[name="nsTimeInput"]')); + const valueWithNsSuffix = await inputElement.getAttribute('value'); + expect(valueWithNsSuffix).toEqual(TIMESTAMP_FROM_REMOTE_TOOL_TO_WINSCOPE + ' ns'); }; const changeTimestampInWinscope = async () => { await browser.switchTo().window(await getWindowHandleWinscope()); - const inputElement = element(by.css("input[name=\"nsTimeInput\"]")); + const inputElement = element(by.css('input[name="nsTimeInput"]')); const inputStringStep1 = TIMESTAMP_FROM_WINSCOPE_TO_REMOTE_TOOL.slice(0, -1); - const inputStringStep2 = TIMESTAMP_FROM_WINSCOPE_TO_REMOTE_TOOL.slice(-1) + "\r\n"; - const script = - `document.querySelector("input[name=\\"nsTimeInput\\"]").value = "${inputStringStep1}"`; + const inputStringStep2 = TIMESTAMP_FROM_WINSCOPE_TO_REMOTE_TOOL.slice(-1) + '\r\n'; + const script = `document.querySelector("input[name=\\"nsTimeInput\\"]").value = "${inputStringStep1}"`; await browser.executeScript(script); await inputElement.sendKeys(inputStringStep2); }; const checkRemoteToolReceivedTimestamp = async () => { await browser.switchTo().window(await getWindowHandleRemoteToolMock()); - const paragraphElement = element(by.css(".paragraph-received-timestamp")); + const paragraphElement = element(by.css('.paragraph-received-timestamp')); const value = await paragraphElement.getText(); expect(value).toEqual(TIMESTAMP_FROM_WINSCOPE_TO_REMOTE_TOOL); }; diff --git a/tools/winscope-ng/src/test/e2e/upload_traces.spec.ts b/tools/winscope-ng/src/test/e2e/upload_traces.spec.ts index 3993f685c..77db45483 100644 --- a/tools/winscope-ng/src/test/e2e/upload_traces.spec.ts +++ b/tools/winscope-ng/src/test/e2e/upload_traces.spec.ts @@ -14,20 +14,20 @@ * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Upload traces", () => { +describe('Upload traces', () => { beforeAll(async () => { await browser.manage().timeouts().implicitlyWait(5000); }); beforeEach(async () => { - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }); - it("can process bugreport", async () => { - await E2eTestUtils.uploadFixture("bugreports/bugreport_stripped.zip"); + it('can process bugreport', async () => { + await E2eTestUtils.uploadFixture('bugreports/bugreport_stripped.zip'); await checkHasLoadedTraces(); expect(await areMessagesEmitted()).toBeTruthy(); await checkEmitsUnsupportedFileFormatMessages(); @@ -38,37 +38,37 @@ describe("Upload traces", () => { }); it("doesn't emit messages for valid trace file", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/SurfaceFlinger.pb"); + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/SurfaceFlinger.pb'); expect(await areMessagesEmitted()).toBeFalsy(); }); const checkHasLoadedTraces = async () => { - const text = await element(by.css(".uploaded-files")).getText(); - expect(text).toContain("wm_log.winscope (ProtoLog)"); - expect(text).toContain("ime_trace_service.winscope (IME Service)"); - expect(text).toContain("ime_trace_managerservice.winscope (IME Manager Service)"); - expect(text).toContain("wm_trace.winscope (Window Manager)"); - expect(text).toContain("layers_trace_from_transactions.winscope (Surface Flinger)"); - expect(text).toContain("ime_trace_clients.winscope (IME Clients)"); - expect(text).toContain("transactions_trace.winscope (Transactions)"); + const text = await element(by.css('.uploaded-files')).getText(); + expect(text).toContain('wm_log.winscope (ProtoLog)'); + expect(text).toContain('ime_trace_service.winscope (IME Service)'); + expect(text).toContain('ime_trace_managerservice.winscope (IME Manager Service)'); + expect(text).toContain('wm_trace.winscope (Window Manager)'); + expect(text).toContain('layers_trace_from_transactions.winscope (Surface Flinger)'); + expect(text).toContain('ime_trace_clients.winscope (IME Clients)'); + expect(text).toContain('transactions_trace.winscope (Transactions)'); }; const checkEmitsUnsupportedFileFormatMessages = async () => { - const text = await element(by.css("upload-snack-bar")).getText(); - expect(text).toContain("unsupported file format"); + const text = await element(by.css('upload-snack-bar')).getText(); + expect(text).toContain('unsupported file format'); }; const checkEmitsOverriddenTracesMessages = async () => { - const text = await element(by.css("upload-snack-bar")).getText(); - expect(text).toContain("overridden by another trace"); + const text = await element(by.css('upload-snack-bar')).getText(); + expect(text).toContain('overridden by another trace'); }; const areMessagesEmitted = async (): Promise => { - return element(by.css("upload-snack-bar")).isPresent(); + return element(by.css('upload-snack-bar')).isPresent(); }; const checkRendersSurfaceFlingerView = async () => { - const viewerPresent = await element(by.css("viewer-surface-flinger")).isPresent(); + const viewerPresent = await element(by.css('viewer-surface-flinger')).isPresent(); expect(viewerPresent).toBeTruthy(); }; }); diff --git a/tools/winscope-ng/src/test/e2e/utils.ts b/tools/winscope-ng/src/test/e2e/utils.ts index 279ee660b..9a1999a2b 100644 --- a/tools/winscope-ng/src/test/e2e/utils.ts +++ b/tools/winscope-ng/src/test/e2e/utils.ts @@ -13,27 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as path from "path"; -import {CommonTestUtils} from "../common/utils"; -import {by, element} from "protractor"; +import * as path from 'path'; +import {by, element} from 'protractor'; +import {CommonTestUtils} from '../common/utils'; class E2eTestUtils extends CommonTestUtils { static getProductionIndexHtmlPath(): string { - return path.join(CommonTestUtils.getProjectRootPath(), "dist/prod/index.html"); + return path.join(CommonTestUtils.getProjectRootPath(), 'dist/prod/index.html'); } static async uploadFixture(path: string) { - const inputFile = element(by.css("input[type=\"file\"]")); + const inputFile = element(by.css('input[type="file"]')); await inputFile.sendKeys(E2eTestUtils.getFixturePath(path)); } static async clickViewTracesButton() { - const button = element(by.css(".load-btn")); + const button = element(by.css('.load-btn')); await button.click(); } static async closeSnackBarIfNeeded() { - const closeButton = element(by.css(".snack-bar-action")); + const closeButton = element(by.css('.snack-bar-action')); const isPresent = await closeButton.isPresent(); if (isPresent) { await closeButton.click(); diff --git a/tools/winscope-ng/src/test/e2e/viewer_input_method_clients.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_input_method_clients.spec.ts index 808abee79..1939d874a 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_input_method_clients.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_input_method_clients.spec.ts @@ -13,21 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer InputMethodClients", () => { +describe('Viewer InputMethodClients', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/InputMethodClients.pb'); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/InputMethodClients.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); - - const viewerPresent = await element(by.css("viewer-input-method")).isPresent(); - expect(viewerPresent).toBeTruthy(); - }); + const viewerPresent = await element(by.css('viewer-input-method')).isPresent(); + expect(viewerPresent).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_input_method_manager_service.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_input_method_manager_service.spec.ts index cec5d7041..5114a9b78 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_input_method_manager_service.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_input_method_manager_service.spec.ts @@ -13,21 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer InputMethodManagerService", () => { +describe('Viewer InputMethodManagerService', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture( + 'traces/elapsed_and_real_timestamp/InputMethodManagerService.pb' + ); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/InputMethodManagerService.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); - - const viewerPresent = await element(by.css("viewer-input-method")).isPresent(); - expect(viewerPresent).toBeTruthy(); - }); + const viewerPresent = await element(by.css('viewer-input-method')).isPresent(); + expect(viewerPresent).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_input_method_service.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_input_method_service.spec.ts index f5739a618..674384535 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_input_method_service.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_input_method_service.spec.ts @@ -13,21 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer InputMethodService", () => { +describe('Viewer InputMethodService', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/InputMethodService.pb'); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/InputMethodService.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); - - const viewerPresent = await element(by.css("viewer-input-method")).isPresent(); - expect(viewerPresent).toBeTruthy(); - }); + const viewerPresent = await element(by.css('viewer-input-method')).isPresent(); + expect(viewerPresent).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_protolog.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_protolog.spec.ts index 7249726b2..6edaaeb1d 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_protolog.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_protolog.spec.ts @@ -13,24 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer ProtoLog", () => { +describe('Viewer ProtoLog', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/ProtoLog.pb'); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/ProtoLog.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); + const isViewerRendered = await element(by.css('viewer-protolog')).isPresent(); + expect(isViewerRendered).toBeTruthy(); - const isViewerRendered = await element(by.css("viewer-protolog")).isPresent(); - expect(isViewerRendered).toBeTruthy(); - - const isFirstMessageRendered = await element(by.css("viewer-protolog .scroll-messages .message")).isPresent(); - expect(isFirstMessageRendered).toBeTruthy(); - }); + const isFirstMessageRendered = await element( + by.css('viewer-protolog .scroll-messages .message') + ).isPresent(); + expect(isFirstMessageRendered).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_screen_recording.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_screen_recording.spec.ts index 3f2ed0d38..65baa48a0 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_screen_recording.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_screen_recording.spec.ts @@ -13,30 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer ScreenRecording", () => { +describe('Viewer ScreenRecording', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture( + 'traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4' + ); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/screen_recording_metadata_v2.mp4"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); + const viewer = element(by.css('viewer-screen-recording')); + expect(await viewer.isPresent()).toBeTruthy(); - const viewer = element(by.css("viewer-screen-recording")); - expect(await viewer.isPresent()) - .toBeTruthy(); - - const video = element(by.css("viewer-screen-recording video")); - expect(await video.isPresent()) - .toBeTruthy(); - expect(await video.getAttribute("src")) - .toContain("blob:"); - expect(await video.getAttribute("currentTime")) - .toEqual("0"); - }); + const video = element(by.css('viewer-screen-recording video')); + expect(await video.isPresent()).toBeTruthy(); + expect(await video.getAttribute('src')).toContain('blob:'); + expect(await video.getAttribute('currentTime')).toEqual('0'); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_surface_flinger.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_surface_flinger.spec.ts index 621d1af09..788b7398d 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_surface_flinger.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_surface_flinger.spec.ts @@ -13,21 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer SurfaceFlinger", () => { +describe('Viewer SurfaceFlinger', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/SurfaceFlinger.pb'); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/SurfaceFlinger.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); - - const viewerPresent = await element(by.css("viewer-surface-flinger")).isPresent(); - expect(viewerPresent).toBeTruthy(); - }); + const viewerPresent = await element(by.css('viewer-surface-flinger')).isPresent(); + expect(viewerPresent).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_transactions.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_transactions.spec.ts index d25aeaa22..3ed07ebbc 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_transactions.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_transactions.spec.ts @@ -13,24 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer Transactions", () => { +describe('Viewer Transactions', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/Transactions.pb'); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/Transactions.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); + const isViewerRendered = await element(by.css('viewer-transactions')).isPresent(); + expect(isViewerRendered).toBeTruthy(); - const isViewerRendered = await element(by.css("viewer-transactions")).isPresent(); - expect(isViewerRendered).toBeTruthy(); - - const isFirstEntryRendered = await element(by.css("viewer-transactions .scroll .entry")).isPresent(); - expect(isFirstEntryRendered).toBeTruthy(); - }); + const isFirstEntryRendered = await element( + by.css('viewer-transactions .scroll .entry') + ).isPresent(); + expect(isFirstEntryRendered).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts index bd617babc..3f20cdd45 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts @@ -13,21 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by, ElementFinder} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("Viewer WindowManager", () => { +describe('Viewer WindowManager', () => { beforeAll(async () => { browser.manage().timeouts().implicitlyWait(1000); - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), + it('processes trace and renders view', async () => { + await E2eTestUtils.uploadFixture('traces/elapsed_and_real_timestamp/WindowManager.pb'); + await E2eTestUtils.closeSnackBarIfNeeded(); + await E2eTestUtils.clickViewTracesButton(); - it("processes trace and renders view", async () => { - await E2eTestUtils.uploadFixture("traces/elapsed_and_real_timestamp/WindowManager.pb"); - await E2eTestUtils.closeSnackBarIfNeeded(); - await E2eTestUtils.clickViewTracesButton(); - - const viewerPresent = await element(by.css("viewer-window-manager")).isPresent(); - expect(viewerPresent).toBeTruthy(); - }); + const viewerPresent = await element(by.css('viewer-window-manager')).isPresent(); + expect(viewerPresent).toBeTruthy(); + }); }); diff --git a/tools/winscope-ng/src/test/e2e/winscope.spec.ts b/tools/winscope-ng/src/test/e2e/winscope.spec.ts index e3f99806a..4d60e44c2 100644 --- a/tools/winscope-ng/src/test/e2e/winscope.spec.ts +++ b/tools/winscope-ng/src/test/e2e/winscope.spec.ts @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {browser, element, by} from "protractor"; -import {E2eTestUtils} from "./utils"; +import {browser, by, element} from 'protractor'; +import {E2eTestUtils} from './utils'; -describe("winscope", () => { +describe('winscope', () => { beforeAll(() => { - browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath()); + browser.get('file://' + E2eTestUtils.getProductionIndexHtmlPath()); }), - - it("has title", () => { - const title = element(by.css(".app-title")); - expect(title.getText()).toContain("Winscope"); - }); -}); \ No newline at end of file + it('has title', () => { + const title = element(by.css('.app-title')); + expect(title.getText()).toContain('Winscope'); + }); +}); diff --git a/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts b/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts index f7e72514c..9752e5367 100644 --- a/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts +++ b/tools/winscope-ng/src/test/remote_tool_mock/app.component.ts @@ -14,58 +14,61 @@ * limitations under the License. */ -import {ChangeDetectorRef, Component, Inject} from "@angular/core"; +import {ChangeDetectorRef, Component, Inject} from '@angular/core'; +import {FunctionUtils} from 'common/utils/function_utils'; import { Message, MessageBugReport, MessagePing, MessageTimestamp, - MessageType} from "cross_tool/messages"; -import {FunctionUtils} from "common/utils/function_utils"; + MessageType, +} from 'cross_tool/messages'; @Component({ - selector: "app-root", + selector: 'app-root', template: ` Remote Tool Mock (simulates cross-tool protocol) -
+

Open Winscope tab

- + -
-

- Send bugreport -

- +
+

Send bugreport

+ -
-

- Send timestamp [ns] -

- - +
+

Send timestamp [ns]

+ + -
-

- Received timestamp: -

-

-

- ` +
+

Received timestamp:

+

+ `, }) export class AppComponent { - static readonly TARGET = "http://localhost:8080"; + static readonly TARGET = 'http://localhost:8080'; static readonly TIMESTAMP_IN_BUGREPORT_MESSAGE = 1670509911000000000n; - private winscope: Window|null = null; + private winscope: Window | null = null; private isWinscopeUp = false; private onMessagePongReceived = FunctionUtils.DO_NOTHING; constructor(@Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef) { - window.addEventListener("message", (event) => { + window.addEventListener('message', (event) => { this.onMessageReceived(event); }); } @@ -81,24 +84,23 @@ export class AppComponent { } public onButtonSendTimestampClick() { - const inputTimestampElement = - document.querySelector(".input-timestamp")! as HTMLInputElement; + const inputTimestampElement = document.querySelector('.input-timestamp')! as HTMLInputElement; this.sendTimestamp(BigInt(inputTimestampElement.value)); } private openWinscope() { - this.printStatus("OPENING WINSCOPE"); + this.printStatus('OPENING WINSCOPE'); this.winscope = window.open(AppComponent.TARGET); if (!this.winscope) { - throw new Error("Failed to open winscope"); + throw new Error('Failed to open winscope'); } - this.printStatus("OPENED WINSCOPE"); + this.printStatus('OPENED WINSCOPE'); } private async waitWinscopeUp() { - this.printStatus("WAITING WINSCOPE UP"); + this.printStatus('WAITING WINSCOPE UP'); const promise = new Promise((resolve) => { this.onMessagePongReceived = () => { @@ -109,91 +111,86 @@ export class AppComponent { setTimeout(async () => { while (!this.isWinscopeUp) { - this.winscope!.postMessage( - new MessagePing(), - AppComponent.TARGET - ); + this.winscope!.postMessage(new MessagePing(), AppComponent.TARGET); await this.sleep(10); } }, 0); await promise; - this.printStatus("DONE WAITING (WINSCOPE IS UP)"); + this.printStatus('DONE WAITING (WINSCOPE IS UP)'); } private sendBugreport(file: File, buffer: ArrayBuffer) { - this.printStatus("SENDING BUGREPORT"); + this.printStatus('SENDING BUGREPORT'); this.winscope!.postMessage( new MessageBugReport(file, AppComponent.TIMESTAMP_IN_BUGREPORT_MESSAGE), AppComponent.TARGET ); - this.printStatus("SENT BUGREPORT"); + this.printStatus('SENT BUGREPORT'); } private sendTimestamp(value: bigint) { - this.printStatus("SENDING TIMESTAMP"); + this.printStatus('SENDING TIMESTAMP'); - this.winscope!.postMessage( - new MessageTimestamp(value), - AppComponent.TARGET - ); + this.winscope!.postMessage(new MessageTimestamp(value), AppComponent.TARGET); - this.printStatus("SENT TIMESTAMP"); + this.printStatus('SENT TIMESTAMP'); } private onMessageReceived(event: MessageEvent) { const message = event.data as Message; if (!message.type) { - console.log("Cross-tool protocol received unrecognized message:", message); + console.log('Cross-tool protocol received unrecognized message:', message); return; } switch (message.type) { - case MessageType.PING: - console.log("Cross-tool protocol received unexpected ping message:", message); - break; - case MessageType.PONG: - this.onMessagePongReceived(); - break; - case MessageType.BUGREPORT: - console.log("Cross-tool protocol received unexpected bugreport message:", message); - break; - case MessageType.TIMESTAMP: - console.log("Cross-tool protocol received timestamp message:", message); - this.onMessageTimestampReceived(message as MessageTimestamp); - break; - case MessageType.FILES: - console.log("Cross-tool protocol received unexpected files message:", message); - break; - default: - console.log("Cross-tool protocol received unrecognized message:", message); - break; + case MessageType.PING: + console.log('Cross-tool protocol received unexpected ping message:', message); + break; + case MessageType.PONG: + this.onMessagePongReceived(); + break; + case MessageType.BUGREPORT: + console.log('Cross-tool protocol received unexpected bugreport message:', message); + break; + case MessageType.TIMESTAMP: + console.log('Cross-tool protocol received timestamp message:', message); + this.onMessageTimestampReceived(message as MessageTimestamp); + break; + case MessageType.FILES: + console.log('Cross-tool protocol received unexpected files message:', message); + break; + default: + console.log('Cross-tool protocol received unrecognized message:', message); + break; } } private onMessageTimestampReceived(message: MessageTimestamp) { - const paragraph = - document.querySelector(".paragraph-received-timestamp") as HTMLParagraphElement; + const paragraph = document.querySelector( + '.paragraph-received-timestamp' + ) as HTMLParagraphElement; paragraph.textContent = message.timestampNs.toString(); this.changeDetectorRef.detectChanges(); } private printStatus(status: string) { - console.log("STATUS: " + status); + console.log('STATUS: ' + status); } private sleep(ms: number): Promise { - return new Promise( resolve => setTimeout(resolve, ms) ); + return new Promise((resolve) => setTimeout(resolve, ms)); } private async readInputFile(event: Event): Promise<[File, ArrayBuffer]> { - const files: FileList|null = (event?.target as HTMLInputElement)?.files; + const files: FileList | null = (event?.target as HTMLInputElement)?.files; if (!files || !files[0]) { - throw new Error("Failed to read input files"); + throw new Error('Failed to read input files'); } return [files[0], await files[0].arrayBuffer()]; diff --git a/tools/winscope-ng/src/test/remote_tool_mock/app.module.ts b/tools/winscope-ng/src/test/remote_tool_mock/app.module.ts index 8b52449c2..b037abc96 100644 --- a/tools/winscope-ng/src/test/remote_tool_mock/app.module.ts +++ b/tools/winscope-ng/src/test/remote_tool_mock/app.module.ts @@ -14,22 +14,16 @@ * limitations under the License. */ -import {CommonModule} from "@angular/common"; -import {NgModule} from "@angular/core"; -import {BrowserModule} from "@angular/platform-browser"; -import {AppComponent} from "./app.component"; +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; +import {AppComponent} from './app.component'; @NgModule({ - declarations: [ - AppComponent, - ], - imports: [ - BrowserModule, - CommonModule, - ], - bootstrap: [AppComponent] + declarations: [AppComponent], + imports: [BrowserModule, CommonModule], + bootstrap: [AppComponent], }) -class AppModule { -} +class AppModule {} export {AppModule}; diff --git a/tools/winscope-ng/src/test/remote_tool_mock/main.ts b/tools/winscope-ng/src/test/remote_tool_mock/main.ts index da5885dd8..486b41068 100644 --- a/tools/winscope-ng/src/test/remote_tool_mock/main.ts +++ b/tools/winscope-ng/src/test/remote_tool_mock/main.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {platformBrowserDynamic} from "@angular/platform-browser-dynamic"; -import {AppModule} from "./app.module"; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; +import {AppModule} from './app.module'; -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/tools/winscope-ng/src/test/remote_tool_mock/polyfills.ts b/tools/winscope-ng/src/test/remote_tool_mock/polyfills.ts index ef841f852..e4555ed11 100644 --- a/tools/winscope-ng/src/test/remote_tool_mock/polyfills.ts +++ b/tools/winscope-ng/src/test/remote_tool_mock/polyfills.ts @@ -45,8 +45,7 @@ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ -import "zone.js"; // Included with Angular CLI. - +import 'zone.js'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/tools/winscope-ng/src/test/remote_tool_mock/webpack.config.js b/tools/winscope-ng/src/test/remote_tool_mock/webpack.config.js index 59e8a4364..e81df56c4 100644 --- a/tools/winscope-ng/src/test/remote_tool_mock/webpack.config.js +++ b/tools/winscope-ng/src/test/remote_tool_mock/webpack.config.js @@ -14,62 +14,58 @@ * limitations under the License. */ -const HtmlWebpackPlugin = require("html-webpack-plugin"); +const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin'); module.exports = { resolve: { - extensions: [".ts", ".js", ".css"], - modules: [ - __dirname + "/../../../node_modules", - __dirname + "/../../../src", - __dirname - ] + extensions: ['.ts', '.js', '.css'], + modules: [__dirname + '/../../../node_modules', __dirname + '/../../../src', __dirname], }, module: { - rules:[ + rules: [ { test: /\.ts$/, - use: ["ts-loader", "angular2-template-loader"] + use: ['ts-loader', 'angular2-template-loader'], }, { test: /\.html$/, - use: ["html-loader"] + use: ['html-loader'], }, { test: /\.css$/, - use: ["style-loader", "css-loader"] + use: ['style-loader', 'css-loader'], }, { test: /\.s[ac]ss$/i, - use: ["style-loader", "css-loader", "sass-loader"] - } - ] + use: ['style-loader', 'css-loader', 'sass-loader'], + }, + ], }, - mode: "development", + mode: 'development', entry: { - polyfills: __dirname + "/polyfills.ts", - app: __dirname + "/main.ts" + polyfills: __dirname + '/polyfills.ts', + app: __dirname + '/main.ts', }, output: { - path: __dirname + "/../../../dist/remote_tool_mock", - publicPath: "/", - filename: "js/[name].[hash].js", - chunkFilename: "js/[name].[id].[hash].chunk.js", + path: __dirname + '/../../../dist/remote_tool_mock', + publicPath: '/', + filename: 'js/[name].[hash].js', + chunkFilename: 'js/[name].[id].[hash].chunk.js', }, - devtool: "source-map", + devtool: 'source-map', plugins: [ new HtmlWebpackPlugin({ - template: __dirname + "/index.html", - inject: "body", - inlineSource: ".(css|js)$", + template: __dirname + '/index.html', + inject: 'body', + inlineSource: '.(css|js)$', }), new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin), - ] + ], }; diff --git a/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts b/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts index 0a2d1c4fe..23fd73b71 100644 --- a/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts +++ b/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { HierarchyTreeNode } from "viewers/common/ui_tree_utils"; -import Chip from "viewers/common/chip"; +import Chip from 'viewers/common/chip'; +import {HierarchyTreeNode} from 'viewers/common/ui_tree_utils'; class HierarchyTreeBuilder { - stableId = ""; - name = ""; - kind = ""; + stableId = ''; + name = ''; + kind = ''; children: HierarchyTreeNode[] = []; shortName?: string; type?: string; diff --git a/tools/winscope-ng/src/test/unit/layer_builder.ts b/tools/winscope-ng/src/test/unit/layer_builder.ts index c50593cc8..8d6dfca5c 100644 --- a/tools/winscope-ng/src/test/unit/layer_builder.ts +++ b/tools/winscope-ng/src/test/unit/layer_builder.ts @@ -16,13 +16,13 @@ import { ActiveBuffer, - Layer, - LayerProperties, EMPTY_COLOR, EMPTY_RECT, EMPTY_RECTF, - EMPTY_TRANSFORM -} from "common/trace/flickerlib/common"; + EMPTY_TRANSFORM, + Layer, + LayerProperties, +} from 'common/trace/flickerlib/common'; class LayerBuilder { setFlags(value: number): LayerBuilder { @@ -40,7 +40,7 @@ class LayerBuilder { false /* isOpaque */, 0 /* shadowRadius */, 0 /* cornerRadius */, - "type" /* type */, + 'type' /* type */, EMPTY_RECTF /* screenBounds */, EMPTY_TRANSFORM /* transform */, EMPTY_RECTF /* sourceBounds */, @@ -62,7 +62,7 @@ class LayerBuilder { ); return new Layer( - "name" /* name */, + 'name' /* name */, 0 /* id */, -1 /*parentId */, 0 /* z */, diff --git a/tools/winscope-ng/src/test/unit/mock_storage.spec.ts b/tools/winscope-ng/src/test/unit/mock_storage.spec.ts index 0986fd1c0..7ebaf2df5 100644 --- a/tools/winscope-ng/src/test/unit/mock_storage.spec.ts +++ b/tools/winscope-ng/src/test/unit/mock_storage.spec.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { MockStorage } from "./mock_storage"; +import {MockStorage} from './mock_storage'; -describe("MockStorage", () => { - it("can store values", () => { +describe('MockStorage', () => { + it('can store values', () => { const mockStorage = new MockStorage(); - mockStorage.setItem("key", "value"); + mockStorage.setItem('key', 'value'); - expect(mockStorage.getItem("key")).toBe("value"); + expect(mockStorage.getItem('key')).toBe('value'); }); -}); \ No newline at end of file +}); diff --git a/tools/winscope-ng/src/test/unit/mock_storage.ts b/tools/winscope-ng/src/test/unit/mock_storage.ts index a5eff8be0..7c6698321 100644 --- a/tools/winscope-ng/src/test/unit/mock_storage.ts +++ b/tools/winscope-ng/src/test/unit/mock_storage.ts @@ -15,7 +15,7 @@ */ export class MockStorage implements Storage { - private store: { [key: string]: string } = {}; + private store: {[key: string]: string} = {}; [name: string]: any; get length(): number { @@ -23,7 +23,7 @@ export class MockStorage implements Storage { } clear(): void { - throw new Error("Method not implemented."); + throw new Error('Method not implemented.'); } getItem(key: string): string | null { return this.store[key]; @@ -37,5 +37,4 @@ export class MockStorage implements Storage { setItem(key: string, value: string): void { this.store[key] = value; } - -} \ No newline at end of file +} diff --git a/tools/winscope-ng/src/test/unit/utils.ts b/tools/winscope-ng/src/test/unit/utils.ts index f98b01ba9..011cdf85a 100644 --- a/tools/winscope-ng/src/test/unit/utils.ts +++ b/tools/winscope-ng/src/test/unit/utils.ts @@ -14,61 +14,60 @@ * limitations under the License. */ -import {Parser} from "parsers/parser"; -import {ParserFactory} from "parsers/parser_factory"; -import {CommonTestUtils} from "test/common/utils"; -import { - LayerTraceEntry, - WindowManagerState -} from "common/trace/flickerlib/common"; -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceFile} from "common/trace/trace"; -import {TraceType} from "common/trace/trace_type"; +import {LayerTraceEntry, WindowManagerState} from 'common/trace/flickerlib/common'; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceFile} from 'common/trace/trace'; +import {TraceType} from 'common/trace/trace_type'; +import {Parser} from 'parsers/parser'; +import {ParserFactory} from 'parsers/parser_factory'; +import {CommonTestUtils} from 'test/common/utils'; class UnitTestUtils extends CommonTestUtils { static async getParser(filename: string): Promise { - const file = new TraceFile( - await CommonTestUtils.getFixtureFile(filename), - undefined); + const file = new TraceFile(await CommonTestUtils.getFixtureFile(filename), undefined); const [parsers, errors] = await new ParserFactory().createParsers([file]); expect(parsers.length).toEqual(1); return parsers[0]; } static async getWindowManagerState(): Promise { - return this.getTraceEntry("traces/elapsed_timestamp/WindowManager.pb"); + return this.getTraceEntry('traces/elapsed_timestamp/WindowManager.pb'); } static async getLayerTraceEntry(): Promise { - return await this.getTraceEntry("traces/elapsed_timestamp/SurfaceFlinger.pb"); + return await this.getTraceEntry('traces/elapsed_timestamp/SurfaceFlinger.pb'); } static async getImeTraceEntries(): Promise> { - let surfaceFlingerEntry: LayerTraceEntry|undefined; + let surfaceFlingerEntry: LayerTraceEntry | undefined; { - const parser = await UnitTestUtils.getParser("traces/ime/SurfaceFlinger_with_IME.pb"); + const parser = await UnitTestUtils.getParser('traces/ime/SurfaceFlinger_with_IME.pb'); const timestamp = new Timestamp(TimestampType.ELAPSED, 502942319579n); surfaceFlingerEntry = await parser.getTraceEntry(timestamp); } - let windowManagerEntry: WindowManagerState|undefined; + let windowManagerEntry: WindowManagerState | undefined; { - const parser = await UnitTestUtils.getParser("traces/ime/WindowManager_with_IME.pb"); + const parser = await UnitTestUtils.getParser('traces/ime/WindowManager_with_IME.pb'); const timestamp = new Timestamp(TimestampType.ELAPSED, 502938057652n); windowManagerEntry = await parser.getTraceEntry(timestamp)!; } const entries = new Map(); - entries.set(TraceType.INPUT_METHOD_CLIENTS, - [await this.getTraceEntry("traces/ime/InputMethodClients.pb"), null]); - entries.set(TraceType.INPUT_METHOD_MANAGER_SERVICE, - [await this.getTraceEntry("traces/ime/InputMethodManagerService.pb"), null]); - entries.set(TraceType.INPUT_METHOD_SERVICE, - [await this.getTraceEntry("traces/ime/InputMethodService.pb"), null]); - entries.set(TraceType.SURFACE_FLINGER, - [surfaceFlingerEntry, null]); - entries.set(TraceType.WINDOW_MANAGER, - [windowManagerEntry, null]); + entries.set(TraceType.INPUT_METHOD_CLIENTS, [ + await this.getTraceEntry('traces/ime/InputMethodClients.pb'), + null, + ]); + entries.set(TraceType.INPUT_METHOD_MANAGER_SERVICE, [ + await this.getTraceEntry('traces/ime/InputMethodManagerService.pb'), + null, + ]); + entries.set(TraceType.INPUT_METHOD_SERVICE, [ + await this.getTraceEntry('traces/ime/InputMethodService.pb'), + null, + ]); + entries.set(TraceType.SURFACE_FLINGER, [surfaceFlingerEntry, null]); + entries.set(TraceType.WINDOW_MANAGER, [windowManagerEntry, null]); return entries; } diff --git a/tools/winscope-ng/src/trace_collection/connection.ts b/tools/winscope-ng/src/trace_collection/connection.ts index b52f65c73..235a6b677 100644 --- a/tools/winscope-ng/src/trace_collection/connection.ts +++ b/tools/winscope-ng/src/trace_collection/connection.ts @@ -13,43 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ProxyClient } from "trace_collection/proxy_client"; -import { configMap } from "./trace_collection_utils"; +import {ProxyClient} from 'trace_collection/proxy_client'; +import {configMap} from './trace_collection_utils'; export interface Device { - [key: string]: DeviceProperties + [key: string]: DeviceProperties; } export interface DeviceProperties { authorised: boolean; - model: string; + model: string; } export interface Connection { - adbSuccess: () => boolean; - setProxyKey?(key:string): any; - devices(): Device; - selectedDevice(): DeviceProperties; - selectedDeviceId(): string; - restart(): any; - selectDevice(id:string): any; - state(): any; - onConnectChange(newState: any): any; - resetLastDevice(): any; - isDevicesState(): boolean; - isStartTraceState(): boolean; - isErrorState(): boolean; - isEndTraceState(): boolean; - isLoadDataState(): boolean; - isConnectingState(): boolean; - throwNoTargetsError(): any; - startTrace( - reqEnableConfig?: Array, - reqSelectedSfConfig?: configMap, - reqSelectedWmConfig?: configMap - ): any; - endTrace(): any; - adbData(): Array; - dumpState(): any; - proxy?: ProxyClient; + adbSuccess: () => boolean; + setProxyKey?(key: string): any; + devices(): Device; + selectedDevice(): DeviceProperties; + selectedDeviceId(): string; + restart(): any; + selectDevice(id: string): any; + state(): any; + onConnectChange(newState: any): any; + resetLastDevice(): any; + isDevicesState(): boolean; + isStartTraceState(): boolean; + isErrorState(): boolean; + isEndTraceState(): boolean; + isLoadDataState(): boolean; + isConnectingState(): boolean; + throwNoTargetsError(): any; + startTrace( + reqEnableConfig?: Array, + reqSelectedSfConfig?: configMap, + reqSelectedWmConfig?: configMap + ): any; + endTrace(): any; + adbData(): Array; + dumpState(): any; + proxy?: ProxyClient; } diff --git a/tools/winscope-ng/src/trace_collection/proxy_client.ts b/tools/winscope-ng/src/trace_collection/proxy_client.ts index 2079c00ef..f1b30a745 100644 --- a/tools/winscope-ng/src/trace_collection/proxy_client.ts +++ b/tools/winscope-ng/src/trace_collection/proxy_client.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { OnProgressUpdateType } from "common/utils/function_utils"; -import { PersistentStore } from "common/utils/persistent_store"; -import { configMap } from "./trace_collection_utils"; -import { Device } from "./connection"; +import {OnProgressUpdateType} from 'common/utils/function_utils'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {Device} from './connection'; +import {configMap} from './trace_collection_utils'; export enum ProxyState { ERROR = 0, @@ -32,34 +32,34 @@ export enum ProxyState { } export enum ProxyEndpoint { - DEVICES = "/devices/", - START_TRACE = "/start/", - END_TRACE = "/end/", - ENABLE_CONFIG_TRACE = "/configtrace/", - SELECTED_WM_CONFIG_TRACE = "/selectedwmconfigtrace/", - SELECTED_SF_CONFIG_TRACE = "/selectedsfconfigtrace/", - DUMP = "/dump/", - FETCH = "/fetch/", - STATUS = "/status/", - CHECK_WAYLAND = "/checkwayland/", + DEVICES = '/devices/', + START_TRACE = '/start/', + END_TRACE = '/end/', + ENABLE_CONFIG_TRACE = '/configtrace/', + SELECTED_WM_CONFIG_TRACE = '/selectedwmconfigtrace/', + SELECTED_SF_CONFIG_TRACE = '/selectedsfconfigtrace/', + DUMP = '/dump/', + FETCH = '/fetch/', + STATUS = '/status/', + CHECK_WAYLAND = '/checkwayland/', } // from here, all requests to the proxy are made class ProxyRequest { // List of trace we are actively tracing - private tracingTraces: string[]|undefined; + private tracingTraces: string[] | undefined; async call( method: string, path: string, - onSuccess: ((request: XMLHttpRequest) => void|Promise) | undefined, + onSuccess: ((request: XMLHttpRequest) => void | Promise) | undefined, type?: XMLHttpRequest['responseType'], jsonRequest: any = null ): Promise { return new Promise((resolve) => { const request = new XMLHttpRequest(); const client = proxyClient; - request.onreadystatechange = async function() { + request.onreadystatechange = async function () { if (this.readyState !== XMLHttpRequest.DONE) { return; } @@ -67,17 +67,19 @@ class ProxyRequest { client.setState(ProxyState.NO_PROXY); resolve(); } else if (this.status === 200) { - if (this.getResponseHeader("Winscope-Proxy-Version") !== client.VERSION) { + if (this.getResponseHeader('Winscope-Proxy-Version') !== client.VERSION) { client.setState(ProxyState.INVALID_VERSION); resolve(); } else if (onSuccess) { try { await onSuccess(this); - } catch(err) { + } catch (err) { console.error(err); - proxyClient.setState(ProxyState.ERROR, - `Error handling request response:\n${err}\n\n`+ - `Request:\n ${request.responseText}`); + proxyClient.setState( + ProxyState.ERROR, + `Error handling request response:\n${err}\n\n` + + `Request:\n ${request.responseText}` + ); resolve(); } } @@ -86,25 +88,25 @@ class ProxyRequest { client.setState(ProxyState.UNAUTH); resolve(); } else { - if (this.responseType === "text" || !this.responseType) { + if (this.responseType === 'text' || !this.responseType) { client.errorText = this.responseText; - } else if (this.responseType === "arraybuffer") { + } else if (this.responseType === 'arraybuffer') { client.errorText = String.fromCharCode.apply(null, new Array(this.response)); } client.setState(ProxyState.ERROR, client.errorText); resolve(); } }; - request.responseType = type || ""; + request.responseType = type || ''; request.open(method, client.WINSCOPE_PROXY_URL + path); - const lastKey = client.store.get("adb.proxyKey"); + const lastKey = client.store.get('adb.proxyKey'); if (lastKey !== null) { client.proxyKey = lastKey; } - request.setRequestHeader("Winscope-Token", client.proxyKey); + request.setRequestHeader('Winscope-Token', client.proxyKey); if (jsonRequest) { const json = JSON.stringify(jsonRequest); - request.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); + request.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); request.send(json); } else { request.send(); @@ -113,60 +115,89 @@ class ProxyRequest { } async getDevices(view: any) { - await proxyRequest.call("GET", ProxyEndpoint.DEVICES, proxyRequest.onSuccessGetDevices); + await proxyRequest.call('GET', ProxyEndpoint.DEVICES, proxyRequest.onSuccessGetDevices); } async setEnabledConfig(view: any, req: Array) { - await proxyRequest.call("POST", `${ProxyEndpoint.ENABLE_CONFIG_TRACE}${view.proxy.selectedDevice}/`, undefined, undefined, req); + await proxyRequest.call( + 'POST', + `${ProxyEndpoint.ENABLE_CONFIG_TRACE}${view.proxy.selectedDevice}/`, + undefined, + undefined, + req + ); } async setSelectedConfig(endpoint: ProxyEndpoint, view: any, req: configMap) { - await proxyRequest.call("POST", `${endpoint}${view.proxy.selectedDevice}/`, undefined, undefined, req); + await proxyRequest.call( + 'POST', + `${endpoint}${view.proxy.selectedDevice}/`, + undefined, + undefined, + req + ); } async startTrace(view: any, requestedTraces: string[]) { this.tracingTraces = requestedTraces; - await proxyRequest.call("POST", `${ProxyEndpoint.START_TRACE}${view.proxy.selectedDevice}/`, (request:XMLHttpRequest) => { - view.keepAliveTrace(view); - }, undefined, requestedTraces); + await proxyRequest.call( + 'POST', + `${ProxyEndpoint.START_TRACE}${view.proxy.selectedDevice}/`, + (request: XMLHttpRequest) => { + view.keepAliveTrace(view); + }, + undefined, + requestedTraces + ); } async endTrace(view: any, progressCallback: OnProgressUpdateType): Promise { const requestedTraces = this.tracingTraces; this.tracingTraces = undefined; if (requestedTraces === undefined) { - throw Error("Trace no started before stopping"); + throw Error('Trace no started before stopping'); } - await proxyRequest.call("POST", `${ProxyEndpoint.END_TRACE}${view.proxy.selectedDevice}/`, + await proxyRequest.call( + 'POST', + `${ProxyEndpoint.END_TRACE}${view.proxy.selectedDevice}/`, async (request: XMLHttpRequest) => { - await proxyClient.updateAdbData(requestedTraces, "trace", progressCallback); - }); + await proxyClient.updateAdbData(requestedTraces, 'trace', progressCallback); + } + ); } async keepTraceAlive(view: any) { - await this.call("GET", `${ProxyEndpoint.STATUS}${view.proxy.selectedDevice}/`, (request: XMLHttpRequest) => { - if (request.responseText !== "True") { - view.endTrace(); - } else if (view.keep_alive_worker === null) { - view.keep_alive_worker = setInterval(view.keepAliveTrace, 1000, view); + await this.call( + 'GET', + `${ProxyEndpoint.STATUS}${view.proxy.selectedDevice}/`, + (request: XMLHttpRequest) => { + if (request.responseText !== 'True') { + view.endTrace(); + } else if (view.keep_alive_worker === null) { + view.keep_alive_worker = setInterval(view.keepAliveTrace, 1000, view); + } } - }); + ); } async dumpState(view: any, requestedDumps: string[], progressCallback: OnProgressUpdateType) { - await proxyRequest.call("POST", `${ProxyEndpoint.DUMP}${view.proxy.selectedDevice}/`, + await proxyRequest.call( + 'POST', + `${ProxyEndpoint.DUMP}${view.proxy.selectedDevice}/`, async (request: XMLHttpRequest) => { - await proxyClient.updateAdbData(requestedDumps, "dump", progressCallback); - }, undefined, requestedDumps); + await proxyClient.updateAdbData(requestedDumps, 'dump', progressCallback); + }, + undefined, + requestedDumps + ); } - onSuccessGetDevices = function(request: XMLHttpRequest) { + onSuccessGetDevices = function (request: XMLHttpRequest) { const client = proxyClient; try { client.devices = JSON.parse(request.responseText); - const last = client.store.get("adb.lastDevice"); - if (last && client.devices[last] && - client.devices[last].authorised) { + const last = client.store.get('adb.lastDevice'); + if (last && client.devices[last] && client.devices[last].authorised) { client.selectDevice(last); } else { if (client.refresh_worker === null) { @@ -185,10 +216,12 @@ class ProxyRequest { const files = adbParams.files; const idx = adbParams.idx; - await proxyRequest.call("GET", `${ProxyEndpoint.FETCH}${dev}/${files[idx]}/`, + await proxyRequest.call( + 'GET', + `${ProxyEndpoint.FETCH}${dev}/${files[idx]}/`, async (request: XMLHttpRequest) => { try { - const enc = new TextDecoder("utf-8"); + const enc = new TextDecoder('utf-8'); const resp = enc.decode(request.response); const filesByType = JSON.parse(resp); @@ -205,33 +238,35 @@ class ProxyRequest { proxyClient.setState(ProxyState.ERROR, request.responseText); throw error; } - }, "arraybuffer"); + }, + 'arraybuffer' + ); } } export const proxyRequest = new ProxyRequest(); interface AdbParams { - files: Array, - idx: number, - traceType: string + files: Array; + idx: number; + traceType: string; } // stores all the changing variables from proxy and sets up calls from ProxyRequest export class ProxyClient { - readonly WINSCOPE_PROXY_URL = "http://localhost:5544"; - readonly VERSION = "1.0"; + readonly WINSCOPE_PROXY_URL = 'http://localhost:5544'; + readonly VERSION = '1.0'; state: ProxyState = ProxyState.CONNECTING; - stateChangeListeners: {(param:ProxyState, errorText:string): void;}[] = []; + stateChangeListeners: {(param: ProxyState, errorText: string): void}[] = []; refresh_worker: NodeJS.Timer | null = null; devices: Device = {}; - selectedDevice = ""; - errorText = ""; + selectedDevice = ''; + errorText = ''; adbData: Array = []; - proxyKey = ""; - lastDevice = ""; + proxyKey = ''; + lastDevice = ''; store = new PersistentStore(); - setState(state:ProxyState, errorText = "") { + setState(state: ProxyState, errorText = '') { this.state = state; this.errorText = errorText; for (const listener of this.stateChangeListeners) { @@ -239,13 +274,13 @@ export class ProxyClient { } } - onProxyChange(fn: (state:ProxyState, errorText:string) => void) { + onProxyChange(fn: (state: ProxyState, errorText: string) => void) { this.removeOnProxyChange(fn); this.stateChangeListeners.push(fn); } - removeOnProxyChange(removeFn: (state:ProxyState, errorText:string) => void) { - this.stateChangeListeners = this.stateChangeListeners.filter(fn => fn !== removeFn); + removeOnProxyChange(removeFn: (state: ProxyState, errorText: string) => void) { + this.stateChangeListeners = this.stateChangeListeners.filter((fn) => fn !== removeFn); } getDevices() { @@ -259,19 +294,23 @@ export class ProxyClient { selectDevice(device_id: string) { this.selectedDevice = device_id; - this.store.add("adb.lastDevice", device_id); + this.store.add('adb.lastDevice', device_id); this.setState(ProxyState.START_TRACE); } - async updateAdbData(files: Array, traceType: string, progressCallback: OnProgressUpdateType) { + async updateAdbData( + files: Array, + traceType: string, + progressCallback: OnProgressUpdateType + ) { for (let idx = 0; idx < files.length; idx++) { const adbParams = { files, idx, - traceType + traceType, }; await proxyRequest.fetchFiles(this.selectedDevice, adbParams); - progressCallback(100 * (idx + 1) / files.length); + progressCallback((100 * (idx + 1)) / files.length); } } } diff --git a/tools/winscope-ng/src/trace_collection/proxy_connection.ts b/tools/winscope-ng/src/trace_collection/proxy_connection.ts index 3ef50c13b..c7067ef74 100644 --- a/tools/winscope-ng/src/trace_collection/proxy_connection.ts +++ b/tools/winscope-ng/src/trace_collection/proxy_connection.ts @@ -14,36 +14,28 @@ * limitations under the License. */ -import {FunctionUtils, OnProgressUpdateType} from "common/utils/function_utils"; -import { - proxyRequest, - proxyClient, - ProxyState, - ProxyEndpoint -} from "trace_collection/proxy_client"; -import { TracingConfig } from "./tracing_config"; -import { Connection, DeviceProperties } from "./connection"; -import { configMap } from "./trace_collection_utils"; +import {FunctionUtils, OnProgressUpdateType} from 'common/utils/function_utils'; +import {proxyClient, ProxyEndpoint, proxyRequest, ProxyState} from 'trace_collection/proxy_client'; +import {Connection, DeviceProperties} from './connection'; +import {configMap} from './trace_collection_utils'; +import {TracingConfig} from './tracing_config'; export class ProxyConnection implements Connection { proxy = proxyClient; keep_alive_worker: any = null; - notConnected = [ - ProxyState.NO_PROXY, - ProxyState.UNAUTH, - ProxyState.INVALID_VERSION, - ]; + notConnected = [ProxyState.NO_PROXY, ProxyState.UNAUTH, ProxyState.INVALID_VERSION]; constructor( private proxyStateChangeCallback: (state: ProxyState) => void, - private progressCallback: OnProgressUpdateType = FunctionUtils.DO_NOTHING) { + private progressCallback: OnProgressUpdateType = FunctionUtils.DO_NOTHING + ) { this.proxy.setState(ProxyState.CONNECTING); this.proxy.onProxyChange((newState) => this.onConnectChange(newState)); const urlParams = new URLSearchParams(window.location.search); - if (urlParams.has("token")) { - this.proxy.proxyKey = urlParams.get("token")!; - } else if (this.proxy.store.get("adb.proxyKey")) { - this.proxy.proxyKey = this.proxy.store.get("adb.proxyKey")!; + if (urlParams.has('token')) { + this.proxy.proxyKey = urlParams.get('token')!; + } else if (this.proxy.store.get('adb.proxyKey')) { + this.proxy.proxyKey = this.proxy.store.get('adb.proxyKey')!; } this.proxy.getDevices(); } @@ -85,12 +77,12 @@ export class ProxyConnection implements Connection { } public throwNoTargetsError() { - this.proxy.setState(ProxyState.ERROR, "No targets selected"); + this.proxy.setState(ProxyState.ERROR, 'No targets selected'); } public setProxyKey(key: string) { this.proxy.proxyKey = key; - this.proxy.store.add("adb.proxyKey", key); + this.proxy.store.add('adb.proxyKey', key); this.restart(); } @@ -111,7 +103,7 @@ export class ProxyConnection implements Connection { } public resetLastDevice() { - this.proxy.store.add("adb.lastDevice", ""); + this.proxy.store.add('adb.lastDevice', ''); this.restart(); } @@ -119,7 +111,7 @@ export class ProxyConnection implements Connection { this.proxy.selectDevice(id); } - public keepAliveTrace(view:ProxyConnection) { + public keepAliveTrace(view: ProxyConnection) { if (!view.isEndTraceState()) { clearInterval(view.keep_alive_worker); view.keep_alive_worker = null; @@ -137,10 +129,18 @@ export class ProxyConnection implements Connection { proxyRequest.setEnabledConfig(this, reqEnableConfig); } if (reqSelectedSfConfig) { - proxyRequest.setSelectedConfig(ProxyEndpoint.SELECTED_SF_CONFIG_TRACE, this, reqSelectedSfConfig); + proxyRequest.setSelectedConfig( + ProxyEndpoint.SELECTED_SF_CONFIG_TRACE, + this, + reqSelectedSfConfig + ); } if (reqSelectedWmConfig) { - proxyRequest.setSelectedConfig(ProxyEndpoint.SELECTED_WM_CONFIG_TRACE, this, reqSelectedWmConfig); + proxyRequest.setSelectedConfig( + ProxyEndpoint.SELECTED_WM_CONFIG_TRACE, + this, + reqSelectedWmConfig + ); } proxyClient.setState(ProxyState.END_TRACE); proxyRequest.startTrace(this, TracingConfig.getInstance().requestedTraces); @@ -155,19 +155,23 @@ export class ProxyConnection implements Connection { public async dumpState(): Promise { this.progressCallback(0); if (TracingConfig.getInstance().requestedDumps.length < 1) { - console.error("No targets selected"); - this.proxy.setState(ProxyState.ERROR, "No targets selected"); + console.error('No targets selected'); + this.proxy.setState(ProxyState.ERROR, 'No targets selected'); return false; } this.proxy.setState(ProxyState.LOAD_DATA); - await proxyRequest.dumpState(this, TracingConfig.getInstance().requestedDumps, this.progressCallback); + await proxyRequest.dumpState( + this, + TracingConfig.getInstance().requestedDumps, + this.progressCallback + ); return true; } public async isWaylandAvailable(): Promise { return new Promise((resolve, reject) => { - proxyRequest.call("GET", ProxyEndpoint.CHECK_WAYLAND, (request:XMLHttpRequest) => { - resolve(request.responseText == "true"); + proxyRequest.call('GET', ProxyEndpoint.CHECK_WAYLAND, (request: XMLHttpRequest) => { + resolve(request.responseText == 'true'); }); }); } diff --git a/tools/winscope-ng/src/trace_collection/trace_collection_utils.ts b/tools/winscope-ng/src/trace_collection/trace_collection_utils.ts index 76921cf81..c74f61ffd 100644 --- a/tools/winscope-ng/src/trace_collection/trace_collection_utils.ts +++ b/tools/winscope-ng/src/trace_collection/trace_collection_utils.ts @@ -1,221 +1,208 @@ -import { StoreObject } from "common/utils/persistent_store_proxy"; +import {StoreObject} from 'common/utils/persistent_store_proxy'; export type TraceConfiguration = { - [key: string]: string|boolean|undefined|StoreObject, - name: string|undefined, - run: boolean|undefined, - isTraceCollection: boolean|undefined, - config: ConfigurationOptions|undefined -} + [key: string]: string | boolean | undefined | StoreObject; + name: string | undefined; + run: boolean | undefined; + isTraceCollection: boolean | undefined; + config: ConfigurationOptions | undefined; +}; export type TraceConfigurationMap = { - [key: string]: TraceConfiguration -} + [key: string]: TraceConfiguration; +}; type ConfigurationOptions = { - [key: string]: string|boolean|undefined|StoreObject, - enableConfigs: EnableConfiguration[], - selectionConfigs: SelectionConfiguration[] -} + [key: string]: string | boolean | undefined | StoreObject; + enableConfigs: EnableConfiguration[]; + selectionConfigs: SelectionConfiguration[]; +}; export type EnableConfiguration = { - name: string, - key: string, - enabled: boolean, -} + name: string; + key: string; + enabled: boolean; +}; export type SelectionConfiguration = { - key: string, - name: string, - options: string[], - value: string -} + key: string; + name: string; + options: string[]; + value: string; +}; export type configMap = { -[key: string]: string[] | string; -} + [key: string]: string[] | string; +}; const wmTraceSelectionConfigs: Array = [ { - key: "wmbuffersize", - name: "buffer size (KB)", - options: [ - "4000", - "8000", - "16000", - "32000", - ], - value: "32000" + key: 'wmbuffersize', + name: 'buffer size (KB)', + options: ['4000', '8000', '16000', '32000'], + value: '32000', }, { - key: "tracingtype", - name: "tracing type", - options: [ - "frame", - "transaction", - ], - value: "frame" + key: 'tracingtype', + name: 'tracing type', + options: ['frame', 'transaction'], + value: 'frame', }, { - key: "tracinglevel", - name: "tracing level", - options: [ - "verbose", - "debug", - "critical", - ], - value: "verbose" + key: 'tracinglevel', + name: 'tracing level', + options: ['verbose', 'debug', 'critical'], + value: 'verbose', }, ]; const sfTraceEnableConfigs: Array = [ { - name: "input", - key: "input", - enabled: true + name: 'input', + key: 'input', + enabled: true, }, { - name: "composition", - key: "composition", - enabled: true + name: 'composition', + key: 'composition', + enabled: true, }, { - name: "metadata", - key: "metadata", - enabled: false + name: 'metadata', + key: 'metadata', + enabled: false, }, { - name: "hwc", - key: "hwc", - enabled: true + name: 'hwc', + key: 'hwc', + enabled: true, }, { - name: "trace buffers", - key: "tracebuffers", - enabled: true + name: 'trace buffers', + key: 'tracebuffers', + enabled: true, }, { - name: "virtual displays", - key: "virtualdisplays", - enabled: false - } + name: 'virtual displays', + key: 'virtualdisplays', + enabled: false, + }, ]; const sfTraceSelectionConfigs: Array = [ { - key: "sfbuffersize", - name: "buffer size (KB)", - options: ["4000","8000","16000","32000"], - value: "32000" - } + key: 'sfbuffersize', + name: 'buffer size (KB)', + options: ['4000', '8000', '16000', '32000'], + value: '32000', + }, ]; export const traceConfigurations: TraceConfigurationMap = { - "layers_trace": { - name: "Surface Flinger", + layers_trace: { + name: 'Surface Flinger', run: true, isTraceCollection: undefined, config: { enableConfigs: sfTraceEnableConfigs, selectionConfigs: sfTraceSelectionConfigs, - } + }, }, - "window_trace": { - name: "Window Manager", + window_trace: { + name: 'Window Manager', run: true, isTraceCollection: undefined, config: { enableConfigs: [], selectionConfigs: wmTraceSelectionConfigs, - } + }, }, - "screen_recording": { - name: "Screen Recording", + screen_recording: { + name: 'Screen Recording', isTraceCollection: undefined, run: true, - config: undefined + config: undefined, }, - "ime_tracing": { - name: "IME Tracing", + ime_tracing: { + name: 'IME Tracing', run: true, isTraceCollection: true, config: { enableConfigs: [ { - name: "Input Method Clients", - key: "ime_trace_clients", + name: 'Input Method Clients', + key: 'ime_trace_clients', enabled: true, }, { - name: "Input Method Service", - key: "ime_trace_service", + name: 'Input Method Service', + key: 'ime_trace_service', enabled: true, }, { - name: "Input Method Manager Service", - key: "ime_trace_managerservice", + name: 'Input Method Manager Service', + key: 'ime_trace_managerservice', enabled: true, }, ], - selectionConfigs: [] - } + selectionConfigs: [], + }, }, - "ime_trace_clients": { - name: "Input Method Clients", + ime_trace_clients: { + name: 'Input Method Clients', isTraceCollection: undefined, run: true, - config: undefined + config: undefined, }, - "ime_trace_service": { - name: "Input Method Service", + ime_trace_service: { + name: 'Input Method Service', isTraceCollection: undefined, run: true, - config: undefined + config: undefined, }, - "ime_trace_managerservice": { - name: "Input Method Manager Service", + ime_trace_managerservice: { + name: 'Input Method Manager Service', isTraceCollection: undefined, run: true, - config: undefined + config: undefined, }, - "accessibility_trace": { - name: "Accessibility", + accessibility_trace: { + name: 'Accessibility', isTraceCollection: undefined, run: false, - config: undefined + config: undefined, }, - "transactions": { - name: "Transaction", + transactions: { + name: 'Transaction', isTraceCollection: undefined, run: false, - config: undefined + config: undefined, }, - "proto_log": { - name: "ProtoLog", + proto_log: { + name: 'ProtoLog', isTraceCollection: undefined, run: false, - config: undefined + config: undefined, }, - "wayland_trace": { - name: "Wayland", + wayland_trace: { + name: 'Wayland', isTraceCollection: undefined, run: false, - config: undefined + config: undefined, }, }; - -export const TRACES: { [key: string]: TraceConfigurationMap; } = { - "default": { - "window_trace": traceConfigurations["window_trace"], - "accessibility_trace": traceConfigurations["accessibility_trace"], - "layers_trace": traceConfigurations["layers_trace"], - "transactions": traceConfigurations["transactions"], - "proto_log": traceConfigurations["proto_log"], - "screen_recording": traceConfigurations["screen_recording"], - "ime_tracing": traceConfigurations["ime_tracing"], +export const TRACES: {[key: string]: TraceConfigurationMap} = { + default: { + window_trace: traceConfigurations['window_trace'], + accessibility_trace: traceConfigurations['accessibility_trace'], + layers_trace: traceConfigurations['layers_trace'], + transactions: traceConfigurations['transactions'], + proto_log: traceConfigurations['proto_log'], + screen_recording: traceConfigurations['screen_recording'], + ime_tracing: traceConfigurations['ime_tracing'], }, - "arc": { - "wayland_trace": traceConfigurations["wayland_trace"], + arc: { + wayland_trace: traceConfigurations['wayland_trace'], }, }; diff --git a/tools/winscope-ng/src/trace_collection/tracing_config.ts b/tools/winscope-ng/src/trace_collection/tracing_config.ts index f6aa40ffe..4b812d592 100644 --- a/tools/winscope-ng/src/trace_collection/tracing_config.ts +++ b/tools/winscope-ng/src/trace_collection/tracing_config.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TraceConfigurationMap, TRACES } from "./trace_collection_utils"; -import { PersistentStoreProxy } from "common/utils/persistent_store_proxy"; +import {PersistentStoreProxy} from 'common/utils/persistent_store_proxy'; +import {TraceConfigurationMap, TRACES} from './trace_collection_utils'; export class TracingConfig { public requestedTraces: string[] = []; public requestedDumps: string[] = []; - private storage: Storage|undefined; - private tracingConfig: TraceConfigurationMap|undefined; - private dumpConfig: TraceConfigurationMap|undefined; + private storage: Storage | undefined; + private tracingConfig: TraceConfigurationMap | undefined; + private dumpConfig: TraceConfigurationMap | undefined; static getInstance(): TracingConfig { return setTracesInstance; @@ -30,27 +30,35 @@ export class TracingConfig { public initialize(storage: Storage) { this.storage = storage; - this.tracingConfig = PersistentStoreProxy.new("TracingSettings", TRACES["default"], this.storage); - this.dumpConfig = PersistentStoreProxy.new("DumpSettings", { - "window_dump": { - name: "Window Manager", - isTraceCollection: undefined, - run: true, - config: undefined + this.tracingConfig = PersistentStoreProxy.new( + 'TracingSettings', + TRACES['default'], + this.storage + ); + this.dumpConfig = PersistentStoreProxy.new( + 'DumpSettings', + { + window_dump: { + name: 'Window Manager', + isTraceCollection: undefined, + run: true, + config: undefined, + }, + layers_dump: { + name: 'Surface Flinger', + isTraceCollection: undefined, + run: true, + config: undefined, + }, }, - "layers_dump": { - name: "Surface Flinger", - isTraceCollection: undefined, - run: true, - config: undefined - } - }, this.storage); + this.storage + ); } public setTracingConfigForAvailableTraces(isWaylandAvailable = false) { - const availableTracesConfig = TRACES["default"]; + const availableTracesConfig = TRACES['default']; if (isWaylandAvailable) { - Object.assign(availableTracesConfig, TRACES["arc"]); + Object.assign(availableTracesConfig, TRACES['arc']); } this.setTracingConfig(availableTracesConfig); } @@ -61,21 +69,25 @@ export class TracingConfig { public getTracingConfig(): TraceConfigurationMap { if (this.tracingConfig === undefined) { - throw Error("Tracing config not initialized yet"); + throw Error('Tracing config not initialized yet'); } return this.tracingConfig; } private setTracingConfig(traceConfig: TraceConfigurationMap) { if (this.storage === undefined) { - throw Error("not initialized"); + throw Error('not initialized'); } - this.tracingConfig = PersistentStoreProxy.new("TraceConfiguration", traceConfig, this.storage); + this.tracingConfig = PersistentStoreProxy.new( + 'TraceConfiguration', + traceConfig, + this.storage + ); } public getDumpConfig(): TraceConfigurationMap { if (this.dumpConfig === undefined) { - throw Error("Dump config not initialized yet"); + throw Error('Dump config not initialized yet'); } return this.dumpConfig; } diff --git a/tools/winscope-ng/src/viewers/common/chip.ts b/tools/winscope-ng/src/viewers/common/chip.ts index 842d4c2af..bad23694d 100644 --- a/tools/winscope-ng/src/viewers/common/chip.ts +++ b/tools/winscope-ng/src/viewers/common/chip.ts @@ -26,34 +26,22 @@ export default class Chip { } } -export const VISIBLE_CHIP = new Chip("V", "visible", "default"); +export const VISIBLE_CHIP = new Chip('V', 'visible', 'default'); -export const RELATIVE_Z_CHIP = new Chip( - "RelZ", - "Is relative Z-ordered to another surface", - "warn", -); +export const RELATIVE_Z_CHIP = new Chip('RelZ', 'Is relative Z-ordered to another surface', 'warn'); export const RELATIVE_Z_PARENT_CHIP = new Chip( - "RelZParent", - "Something is relative Z-ordered to this surface", - "warn", + 'RelZParent', + 'Something is relative Z-ordered to this surface', + 'warn' ); -export const MISSING_LAYER = new Chip( - "MissingLayer", - "This layer was referenced from the parent, but not present in the trace", - "error", +export const MISSING_LAYER = new Chip( + 'MissingLayer', + 'This layer was referenced from the parent, but not present in the trace', + 'error' ); -export const GPU_CHIP = new Chip( - "GPU", - "This layer was composed on the GPU", - "gpu", -); +export const GPU_CHIP = new Chip('GPU', 'This layer was composed on the GPU', 'gpu'); -export const HWC_CHIP = new Chip( - "HWC", - "This layer was composed by Hardware Composer", - "hwc", -); \ No newline at end of file +export const HWC_CHIP = new Chip('HWC', 'This layer was composed by Hardware Composer', 'hwc'); diff --git a/tools/winscope-ng/src/viewers/common/ime_additional_properties.ts b/tools/winscope-ng/src/viewers/common/ime_additional_properties.ts index 52e7610f7..8959d8821 100644 --- a/tools/winscope-ng/src/viewers/common/ime_additional_properties.ts +++ b/tools/winscope-ng/src/viewers/common/ime_additional_properties.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImeLayers, ProcessedWindowManagerState } from "./ime_utils"; +import {ImeLayers, ProcessedWindowManagerState} from './ime_utils'; export class ImeAdditionalProperties { constructor( public wm: ProcessedWindowManagerState | undefined, - public sf: ImeLayers | undefined, + public sf: ImeLayers | undefined ) {} } diff --git a/tools/winscope-ng/src/viewers/common/ime_ui_data.ts b/tools/winscope-ng/src/viewers/common/ime_ui_data.ts index f0e6849b9..bc1d88278 100644 --- a/tools/winscope-ng/src/viewers/common/ime_ui_data.ts +++ b/tools/winscope-ng/src/viewers/common/ime_ui_data.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils"; -import { UserOptions } from "viewers/common/user_options"; -import { TraceType } from "common/trace/trace_type"; -import { TableProperties } from "viewers/common/table_properties"; -import { ImeAdditionalProperties } from "viewers/common/ime_additional_properties"; +import {TraceType} from 'common/trace/trace_type'; +import {ImeAdditionalProperties} from 'viewers/common/ime_additional_properties'; +import {TableProperties} from 'viewers/common/table_properties'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; export class ImeUiData { dependencies: Array; diff --git a/tools/winscope-ng/src/viewers/common/ime_utils.spec.ts b/tools/winscope-ng/src/viewers/common/ime_utils.spec.ts index e82b3fe2c..5178e49b5 100644 --- a/tools/winscope-ng/src/viewers/common/ime_utils.spec.ts +++ b/tools/winscope-ng/src/viewers/common/ime_utils.spec.ts @@ -13,84 +13,75 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ImeUtils} from "./ime_utils"; -import {UnitTestUtils} from "test/unit/utils"; -import {TraceType} from "common/trace/trace_type"; +import {TraceType} from 'common/trace/trace_type'; +import {UnitTestUtils} from 'test/unit/utils'; +import {ImeUtils} from './ime_utils'; -describe("ImeUtils", () => { - it("processes WindowManager trace entry", async () => { +describe('ImeUtils', () => { + it('processes WindowManager trace entry', async () => { const entries = await UnitTestUtils.getImeTraceEntries(); const processed = ImeUtils.processWindowManagerTraceEntry( - entries.get(TraceType.WINDOW_MANAGER)[0]); + entries.get(TraceType.WINDOW_MANAGER)[0] + ); - expect(processed.focusedApp) - .toEqual("com.google.android.apps.messaging/.ui.search.ZeroStateSearchActivity"); + expect(processed.focusedApp).toEqual( + 'com.google.android.apps.messaging/.ui.search.ZeroStateSearchActivity' + ); - expect(processed.focusedActivity.token) - .toEqual("9d8c2ef"); - expect(processed.focusedActivity.layerId) - .toEqual(260); + expect(processed.focusedActivity.token).toEqual('9d8c2ef'); + expect(processed.focusedActivity.layerId).toEqual(260); - expect(processed.focusedWindow.token) - .toEqual("928b3d"); - expect(processed.focusedWindow.title) - .toEqual("com.google.android.apps.messaging/com.google.android.apps.messaging.ui.search.ZeroStateSearchActivity"); + expect(processed.focusedWindow.token).toEqual('928b3d'); + expect(processed.focusedWindow.title).toEqual( + 'com.google.android.apps.messaging/com.google.android.apps.messaging.ui.search.ZeroStateSearchActivity' + ); - expect(processed.protoImeControlTarget.windowContainer.identifier.title) - .toEqual("com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity"); - expect(processed.protoImeControlTarget.windowContainer.identifier.hashCode) - .toEqual(247026562); + expect(processed.protoImeControlTarget.windowContainer.identifier.title).toEqual( + 'com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity' + ); + expect(processed.protoImeControlTarget.windowContainer.identifier.hashCode).toEqual(247026562); - expect(processed.protoImeInputTarget.windowContainer.identifier.title) - .toEqual("com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity"); - expect(processed.protoImeInputTarget.windowContainer.identifier.hashCode) - .toEqual(247026562); + expect(processed.protoImeInputTarget.windowContainer.identifier.title).toEqual( + 'com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity' + ); + expect(processed.protoImeInputTarget.windowContainer.identifier.hashCode).toEqual(247026562); - expect(processed.protoImeInsetsSourceProvider - .insetsSourceProvider).toBeDefined(); + expect(processed.protoImeInsetsSourceProvider.insetsSourceProvider).toBeDefined(); - expect(processed.protoImeLayeringTarget.windowContainer.identifier.title) - .toEqual("SnapshotStartingWindow for taskId=1393"); - expect(processed.protoImeLayeringTarget.windowContainer.identifier.hashCode) - .toEqual(222907471); + expect(processed.protoImeLayeringTarget.windowContainer.identifier.title).toEqual( + 'SnapshotStartingWindow for taskId=1393' + ); + expect(processed.protoImeLayeringTarget.windowContainer.identifier.hashCode).toEqual(222907471); - expect( - processed.isInputMethodWindowVisible) - .toBeFalse(); + expect(processed.isInputMethodWindowVisible).toBeFalse(); }); - it("processes SurfaceFlinger trace entry", async () => { + it('processes SurfaceFlinger trace entry', async () => { const entries = await UnitTestUtils.getImeTraceEntries(); const processedWindowManagerState = ImeUtils.processWindowManagerTraceEntry( - entries.get(TraceType.WINDOW_MANAGER)[0]); + entries.get(TraceType.WINDOW_MANAGER)[0] + ); const layers = ImeUtils.getImeLayers( entries.get(TraceType.SURFACE_FLINGER)[0], - processedWindowManagerState)!; + processedWindowManagerState + )!; - expect(layers.inputMethodSurface.id) - .toEqual(280); - expect(layers.inputMethodSurface.isVisible) - .toEqual(false); + expect(layers.inputMethodSurface.id).toEqual(280); + expect(layers.inputMethodSurface.isVisible).toEqual(false); expect(layers.inputMethodSurface.rect.label).toEqual( - "Surface(name=77f1069 InputMethod)/@0xb4afb8f - animation-leash of insets_animation#280"); - expect(layers.inputMethodSurface.screenBounds) - .toBeDefined(); + 'Surface(name=77f1069 InputMethod)/@0xb4afb8f - animation-leash of insets_animation#280' + ); + expect(layers.inputMethodSurface.screenBounds).toBeDefined(); - expect(layers.imeContainer.id) - .toEqual(12); + expect(layers.imeContainer.id).toEqual(12); expect(layers.imeContainer.z).toEqual(1); - expect(layers.imeContainer.zOrderRelativeOfId) - .toEqual(115); + expect(layers.imeContainer.zOrderRelativeOfId).toEqual(115); - expect(String(layers.focusedWindow.color)) - .toEqual("r:0 g:0 b:0 a:1"); + expect(String(layers.focusedWindow.color)).toEqual('r:0 g:0 b:0 a:1'); - expect(layers.taskOfImeContainer.kind) - .toEqual("SF subtree - 114"); - expect(layers.taskOfImeContainer.name) - .toEqual("Task=1391#114"); + expect(layers.taskOfImeContainer.kind).toEqual('SF subtree - 114'); + expect(layers.taskOfImeContainer.name).toEqual('Task=1391#114'); - expect(layers.taskOfImeSnapshot) - .toBeUndefined(); + expect(layers.taskOfImeSnapshot).toBeUndefined(); }); }); diff --git a/tools/winscope-ng/src/viewers/common/ime_utils.ts b/tools/winscope-ng/src/viewers/common/ime_utils.ts index 52d121f08..30ccf1e04 100644 --- a/tools/winscope-ng/src/viewers/common/ime_utils.ts +++ b/tools/winscope-ng/src/viewers/common/ime_utils.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import Activity from "common/trace/flickerlib/windows/Activity"; -import {Layer} from "common/trace/flickerlib/layers/Layer"; -import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry"; -import {WindowContainer} from "common/trace/flickerlib/common"; -import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; -import WindowState from "common/trace/flickerlib/windows/WindowState"; -import {TreeUtils, FilterType} from "common/utils/tree_utils"; +import {WindowContainer} from 'common/trace/flickerlib/common'; +import {Layer} from 'common/trace/flickerlib/layers/Layer'; +import {LayerTraceEntry} from 'common/trace/flickerlib/layers/LayerTraceEntry'; +import Activity from 'common/trace/flickerlib/windows/Activity'; +import {WindowManagerState} from 'common/trace/flickerlib/windows/WindowManagerState'; +import WindowState from 'common/trace/flickerlib/windows/WindowState'; +import {FilterType, TreeUtils} from 'common/utils/tree_utils'; class ProcessedWindowManagerState { constructor( @@ -42,15 +42,16 @@ class ImeLayers { public name: string, public imeContainer: Layer, public inputMethodSurface: Layer, - public focusedWindow: Layer|undefined, - public taskOfImeContainer: Layer|undefined, - public taskOfImeSnapshot: Layer|undefined - ) { - } + public focusedWindow: Layer | undefined, + public taskOfImeContainer: Layer | undefined, + public taskOfImeSnapshot: Layer | undefined + ) {} } class ImeUtils { - public static processWindowManagerTraceEntry(entry: WindowManagerState): ProcessedWindowManagerState { + public static processWindowManagerTraceEntry( + entry: WindowManagerState + ): ProcessedWindowManagerState { const displayContent = entry.root.children[0]; return new ProcessedWindowManagerState( @@ -64,22 +65,22 @@ class ImeUtils { this.getImeInputTargetProperty(displayContent.proto), this.getImeLayeringTargetProperty(displayContent.proto), displayContent.proto.imeInsetsSourceProvider, - entry.proto, + entry.proto ); } public static getImeLayers( entry: LayerTraceEntry, - processedWindowManagerState: ProcessedWindowManagerState): ImeLayers|undefined { - const isImeContainer = TreeUtils.makeNodeFilter("ImeContainer"); + processedWindowManagerState: ProcessedWindowManagerState + ): ImeLayers | undefined { + const isImeContainer = TreeUtils.makeNodeFilter('ImeContainer'); const imeContainer = TreeUtils.findDescendantNode(entry, isImeContainer); if (!imeContainer) { return undefined; } - const isInputMethodSurface = TreeUtils.makeNodeFilter("InputMethod"); - const inputMethodSurface = - TreeUtils.findDescendantNode(imeContainer, isInputMethodSurface); + const isInputMethodSurface = TreeUtils.makeNodeFilter('InputMethod'); + const inputMethodSurface = TreeUtils.findDescendantNode(imeContainer, isInputMethodSurface); let focusedWindowLayer: Layer = undefined; const focusedWindowToken = processedWindowManagerState.focusedWindow?.token; @@ -90,11 +91,15 @@ class ImeUtils { // we want to see both ImeContainer and IME-snapshot if there are // cases where both exist - const taskLayerOfImeContainer = - this.findAncestorTaskLayerOfImeLayer(entry, TreeUtils.makeNodeFilter("ImeContainer")); + const taskLayerOfImeContainer = this.findAncestorTaskLayerOfImeLayer( + entry, + TreeUtils.makeNodeFilter('ImeContainer') + ); - const taskLayerOfImeSnapshot = - this.findAncestorTaskLayerOfImeLayer(entry, TreeUtils.makeNodeFilter("IME-snapshot")); + const taskLayerOfImeSnapshot = this.findAncestorTaskLayerOfImeLayer( + entry, + TreeUtils.makeNodeFilter('IME-snapshot') + ); return new ImeLayers( entry.name, @@ -109,7 +114,7 @@ class ImeUtils { public static transformInputConnectionCall(entry: any) { const obj = Object.assign({}, entry); if (obj.inputConnectionCall) { - Object.getOwnPropertyNames(obj.inputConnectionCall).forEach(name => { + Object.getOwnPropertyNames(obj.inputConnectionCall).forEach((name) => { const value = Object.getOwnPropertyDescriptor(obj.inputConnectionCall, name); if (!value?.value) delete obj.inputConnectionCall[name]; }); @@ -117,46 +122,50 @@ class ImeUtils { return obj; } - private static findAncestorTaskLayerOfImeLayer(entry: LayerTraceEntry, isTargetImeLayer: FilterType): Layer { + private static findAncestorTaskLayerOfImeLayer( + entry: LayerTraceEntry, + isTargetImeLayer: FilterType + ): Layer { const imeLayer = TreeUtils.findDescendantNode(entry, isTargetImeLayer); if (!imeLayer) { return undefined; } - const isTaskLayer = TreeUtils.makeNodeFilter("Task, ImePlaceholder"); + const isTaskLayer = TreeUtils.makeNodeFilter('Task, ImePlaceholder'); const taskLayer = TreeUtils.findAncestorNode(imeLayer, isTaskLayer); if (!taskLayer) { return undefined; } - taskLayer.kind = "SF subtree - " + taskLayer.id; + taskLayer.kind = 'SF subtree - ' + taskLayer.id; return taskLayer; } private static getImeControlTargetProperty(displayContentProto: any): any { - const POSSIBLE_NAMES = ["inputMethodControlTarget", "imeControlTarget"]; + const POSSIBLE_NAMES = ['inputMethodControlTarget', 'imeControlTarget']; return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES); } private static getImeInputTargetProperty(displayContentProto: any): any { - const POSSIBLE_NAMES = ["inputMethodInputTarget", "imeInputTarget"]; + const POSSIBLE_NAMES = ['inputMethodInputTarget', 'imeInputTarget']; return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES); } private static getImeLayeringTargetProperty(displayContentProto: any): any { - const POSSIBLE_NAMES = ["inputMethodTarget", "imeLayeringTarget"]; + const POSSIBLE_NAMES = ['inputMethodTarget', 'imeLayeringTarget']; return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES); } private static findAnyPropertyWithMatchingName(object: any, possible_names: string[]): any { - const key = Object.keys(object).find(key => possible_names.includes(key)); + const key = Object.keys(object).find((key) => possible_names.includes(key)); return key ? object[key] : undefined; } - private static isInputMethodVisible(displayContent: WindowContainer) : boolean { - const isInputMethod = TreeUtils.makeNodeFilter("InputMethod"); - const inputMethodWindowOrLayer = - TreeUtils.findDescendantNode(displayContent, isInputMethod); + private static isInputMethodVisible(displayContent: WindowContainer): boolean { + const isInputMethod = TreeUtils.makeNodeFilter('InputMethod'); + const inputMethodWindowOrLayer = ( + TreeUtils.findDescendantNode(displayContent, isInputMethod) + ); return inputMethodWindowOrLayer?.isVisible == true; } } diff --git a/tools/winscope-ng/src/viewers/common/presenter_input_method.ts b/tools/winscope-ng/src/viewers/common/presenter_input_method.ts index 2d76ccfa7..d57e2dbeb 100644 --- a/tools/winscope-ng/src/viewers/common/presenter_input_method.ts +++ b/tools/winscope-ng/src/viewers/common/presenter_input_method.ts @@ -1,4 +1,3 @@ - /* * Copyright (C) 2022 The Android Open Source Project * @@ -14,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImeUiData } from "viewers/common/ime_ui_data"; -import { TraceType } from "common/trace/trace_type"; -import { UserOptions } from "viewers/common/user_options"; -import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils"; -import { TreeGenerator } from "viewers/common/tree_generator"; -import { TreeTransformer } from "viewers/common/tree_transformer"; -import { TreeUtils, FilterType } from "common/utils/tree_utils"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { ImeLayers, ImeUtils, ProcessedWindowManagerState } from "viewers/common/ime_utils"; -import { ImeAdditionalProperties } from "viewers/common/ime_additional_properties"; -import { TableProperties } from "viewers/common/table_properties"; -import { PersistentStoreProxy } from "common/utils/persistent_store_proxy"; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStoreProxy} from 'common/utils/persistent_store_proxy'; +import {FilterType, TreeUtils} from 'common/utils/tree_utils'; +import {ImeAdditionalProperties} from 'viewers/common/ime_additional_properties'; +import {ImeUiData} from 'viewers/common/ime_ui_data'; +import {ImeLayers, ImeUtils, ProcessedWindowManagerState} from 'viewers/common/ime_utils'; +import {TableProperties} from 'viewers/common/table_properties'; +import {TreeGenerator} from 'viewers/common/tree_generator'; +import {TreeTransformer} from 'viewers/common/tree_transformer'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; type NotifyImeViewCallbackType = (uiData: ImeUiData) => void; @@ -43,8 +42,8 @@ export abstract class PresenterInputMethod { public updatePinnedItems(pinnedItem: HierarchyTreeNode) { const pinnedId = `${pinnedItem.id}`; - if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) { - this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId); + if (this.pinnedItems.map((item) => `${item.id}`).includes(pinnedId)) { + this.pinnedItems = this.pinnedItems.filter((pinned) => `${pinned.id}` != pinnedId); } else { this.pinnedItems.push(pinnedItem); } @@ -55,7 +54,7 @@ export abstract class PresenterInputMethod { public updateHighlightedItems(id: string) { if (this.highlightedItems.includes(id)) { - this.highlightedItems = this.highlightedItems.filter(hl => hl != id); + this.highlightedItems = this.highlightedItems.filter((hl) => hl != id); } else { this.highlightedItems = []; //if multi-select surfaces implemented, remove this line this.highlightedItems.push(id); @@ -95,12 +94,16 @@ export abstract class PresenterInputMethod { } public newAdditionalPropertiesTree(selectedItem: any) { - this.selectedHierarchyTree = new HierarchyTreeNode(selectedItem.name, "AdditionalProperty", "AdditionalProperty"); + this.selectedHierarchyTree = new HierarchyTreeNode( + selectedItem.name, + 'AdditionalProperty', + 'AdditionalProperty' + ); this.additionalPropertyEntry = { name: selectedItem.name, - kind: "AdditionalProperty", + kind: 'AdditionalProperty', children: [], - stableId: "AdditionalProperty", + stableId: 'AdditionalProperty', proto: selectedItem.proto, }; this.updateSelectedTreeUiData(); @@ -130,7 +133,10 @@ export abstract class PresenterInputMethod { this.notifyViewCallback(this.uiData); } - protected getAdditionalProperties(wmEntry: TraceTreeNode | undefined, sfEntry: TraceTreeNode | undefined) { + protected getAdditionalProperties( + wmEntry: TraceTreeNode | undefined, + sfEntry: TraceTreeNode | undefined + ) { let wmProperties: ProcessedWindowManagerState | undefined; let sfProperties: ImeLayers | undefined; let sfSubtrees: any[]; @@ -143,29 +149,25 @@ export abstract class PresenterInputMethod { sfSubtrees = [sfProperties?.taskOfImeContainer, sfProperties?.taskOfImeSnapshot] .filter((node) => node) // filter away null values .map((node) => { - node.kind = "SF subtree - " + node.id; + node.kind = 'SF subtree - ' + node.id; return node; }); this.entry?.children.push(...sfSubtrees); } } - return new ImeAdditionalProperties( - wmProperties, - sfProperties, - ); + return new ImeAdditionalProperties(wmProperties, sfProperties); } - protected generateTree() { if (!this.entry) { return null; } const generator = new TreeGenerator(this.entry, this.hierarchyFilter, this.pinnedIds) - .setIsOnlyVisibleView(this.hierarchyUserOptions["onlyVisible"]?.enabled) - .setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled) - .setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled) + .setIsOnlyVisibleView(this.hierarchyUserOptions['onlyVisible']?.enabled) + .setIsSimplifyNames(this.hierarchyUserOptions['simplifyNames']?.enabled) + .setIsFlatView(this.hierarchyUserOptions['flat']?.enabled) .withUniqueNodeId(); const tree: HierarchyTreeNode | null = generator.generateTree(); this.pinnedItems = generator.getPinnedItems(); @@ -175,13 +177,15 @@ export abstract class PresenterInputMethod { private updateSelectedTreeUiData() { if (this.selectedHierarchyTree) { - this.uiData.propertiesTree = this.getTreeWithTransformedProperties(this.selectedHierarchyTree); + this.uiData.propertiesTree = this.getTreeWithTransformedProperties( + this.selectedHierarchyTree + ); } this.notifyViewCallback(this.uiData); } private updatePinnedIds(newId: string) { if (this.pinnedIds.includes(newId)) { - this.pinnedIds = this.pinnedIds.filter(pinned => pinned != newId); + this.pinnedIds = this.pinnedIds.filter((pinned) => pinned != newId); } else { this.pinnedIds.push(newId); } @@ -190,15 +194,15 @@ export abstract class PresenterInputMethod { private getTreeWithTransformedProperties(selectedTree: HierarchyTreeNode): PropertiesTreeNode { const transformer = new TreeTransformer(selectedTree, this.propertiesFilter) .setOnlyProtoDump(this.additionalPropertyEntry != null) - .setIsShowDefaults(this.propertiesUserOptions["showDefaults"]?.enabled) + .setIsShowDefaults(this.propertiesUserOptions['showDefaults']?.enabled) .setTransformerOptions({skip: selectedTree.skip}) .setProperties(this.additionalPropertyEntry ?? this.entry); const transformedTree = transformer.transform(); return transformedTree; } - private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter(""); - private propertiesFilter: FilterType = TreeUtils.makeNodeFilter(""); + private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter(''); + private propertiesFilter: FilterType = TreeUtils.makeNodeFilter(''); private pinnedItems: Array = []; private pinnedIds: Array = []; private selectedHierarchyTree: HierarchyTreeNode | null = null; @@ -207,33 +211,41 @@ export abstract class PresenterInputMethod { protected readonly dependencies: Array; protected uiData: ImeUiData; protected highlightedItems: Array = []; - protected entry: TraceTreeNode | null = null; + protected entry: TraceTreeNode | null = null; protected additionalPropertyEntry: TraceTreeNode | null = null; - protected hierarchyUserOptions: UserOptions = PersistentStoreProxy.new("ImeHierarchyOptions", { - simplifyNames: { - name: "Simplify names", - enabled: true + protected hierarchyUserOptions: UserOptions = PersistentStoreProxy.new( + 'ImeHierarchyOptions', + { + simplifyNames: { + name: 'Simplify names', + enabled: true, + }, + onlyVisible: { + name: 'Only visible', + enabled: false, + }, + flat: { + name: 'Flat', + enabled: false, + }, }, - onlyVisible: { - name: "Only visible", - enabled: false - }, - flat: { - name: "Flat", - enabled: false - } - }, this.storage); - protected propertiesUserOptions: UserOptions = PersistentStoreProxy.new("ImePropertiesOptions", { - showDefaults: { - name: "Show defaults", - enabled: false, - tooltip: ` + this.storage + ); + protected propertiesUserOptions: UserOptions = PersistentStoreProxy.new( + 'ImePropertiesOptions', + { + showDefaults: { + name: 'Show defaults', + enabled: false, + tooltip: ` If checked, shows the value of all properties. Otherwise, hides all properties whose value is the default for its data type. - ` + `, + }, }, - }, this.storage); + this.storage + ); protected abstract updateHierarchyTableProperties(): TableProperties; } diff --git a/tools/winscope-ng/src/viewers/common/presenter_input_method_test_utils.ts b/tools/winscope-ng/src/viewers/common/presenter_input_method_test_utils.ts index 5032148f1..76d83964d 100644 --- a/tools/winscope-ng/src/viewers/common/presenter_input_method_test_utils.ts +++ b/tools/winscope-ng/src/viewers/common/presenter_input_method_test_utils.ts @@ -14,27 +14,30 @@ * limitations under the License.d */ -import {TraceType} from "common/trace/trace_type"; -import {PresenterInputMethod} from "./presenter_input_method"; -import {HierarchyTreeBuilder} from "test/unit/hierarchy_tree_builder"; -import {UnitTestUtils} from "test/unit/utils"; -import {ImeUiData} from "viewers/common/ime_ui_data"; -import {HierarchyTreeNode, PropertiesTreeNode} from "viewers/common/ui_tree_utils"; -import {UserOptions} from "viewers/common/user_options"; -import {PresenterInputMethodClients} from "viewers/viewer_input_method_clients/presenter_input_method_clients"; -import {PresenterInputMethodService} from "viewers/viewer_input_method_service/presenter_input_method_service"; -import {PresenterInputMethodManagerService} from "viewers/viewer_input_method_manager_service/presenter_input_method_manager_service"; -import { MockStorage } from "test/unit/mock_storage"; +import {TraceType} from 'common/trace/trace_type'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {MockStorage} from 'test/unit/mock_storage'; +import {UnitTestUtils} from 'test/unit/utils'; +import {ImeUiData} from 'viewers/common/ime_ui_data'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {PresenterInputMethodClients} from 'viewers/viewer_input_method_clients/presenter_input_method_clients'; +import {PresenterInputMethodManagerService} from 'viewers/viewer_input_method_manager_service/presenter_input_method_manager_service'; +import {PresenterInputMethodService} from 'viewers/viewer_input_method_service/presenter_input_method_service'; +import {PresenterInputMethod} from './presenter_input_method'; export function executePresenterInputMethodTests( selected: HierarchyTreeNode, propertiesTreeFilterString: string, expectedChildren: [number, number], expectHierarchyTreeWithSfSubtree: boolean, - PresenterInputMethod: typeof PresenterInputMethodClients | typeof PresenterInputMethodService | typeof PresenterInputMethodManagerService, - traceType: TraceType, + PresenterInputMethod: + | typeof PresenterInputMethodClients + | typeof PresenterInputMethodService + | typeof PresenterInputMethodManagerService, + traceType: TraceType ) { - describe("PresenterInputMethod", () => { + describe('PresenterInputMethod', () => { let presenter: PresenterInputMethod; let uiData: ImeUiData; let entries: Map; @@ -43,19 +46,23 @@ export function executePresenterInputMethodTests( beforeEach(async () => { entries = await UnitTestUtils.getImeTraceEntries(); selectedTree = selected; - presenter = new PresenterInputMethod((newData: ImeUiData) => { - uiData = newData; - }, [traceType], new MockStorage()); + presenter = new PresenterInputMethod( + (newData: ImeUiData) => { + uiData = newData; + }, + [traceType], + new MockStorage() + ); }); - it("can notify current trace entries", () => { + it('can notify current trace entries', () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.hierarchyUserOptions).toBeTruthy(); expect(uiData.propertiesUserOptions).toBeTruthy(); expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); - it("is robust to trace entry without SF", () => { + it('is robust to trace entry without SF', () => { entries.delete(TraceType.SURFACE_FLINGER); presenter.notifyCurrentTraceEntries(entries); expect(uiData.hierarchyUserOptions).toBeTruthy(); @@ -63,7 +70,7 @@ export function executePresenterInputMethodTests( expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); - it("is robust to trace entry without WM", () => { + it('is robust to trace entry without WM', () => { entries.delete(TraceType.WINDOW_MANAGER); presenter.notifyCurrentTraceEntries(entries); expect(uiData.hierarchyUserOptions).toBeTruthy(); @@ -71,7 +78,7 @@ export function executePresenterInputMethodTests( expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); - it("is robust to trace entry without WM and SF", () => { + it('is robust to trace entry without WM and SF', () => { entries.delete(TraceType.SURFACE_FLINGER); entries.delete(TraceType.WINDOW_MANAGER); presenter.notifyCurrentTraceEntries(entries); @@ -80,7 +87,7 @@ export function executePresenterInputMethodTests( expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); - it("can handle unavailable trace entry", () => { + it('can handle unavailable trace entry', () => { presenter.notifyCurrentTraceEntries(entries); expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); const emptyEntries = new Map(); @@ -88,36 +95,39 @@ export function executePresenterInputMethodTests( expect(uiData.tree).toBeFalsy(); }); - it("can update pinned items", () => { + it('can update pinned items', () => { expect(uiData.pinnedItems).toEqual([]); - const pinnedItem = new HierarchyTreeBuilder().setName("FirstPinnedItem") - .setStableId("TestItem 4").setLayerId(4).build(); + const pinnedItem = new HierarchyTreeBuilder() + .setName('FirstPinnedItem') + .setStableId('TestItem 4') + .setLayerId(4) + .build(); presenter.updatePinnedItems(pinnedItem); expect(uiData.pinnedItems).toContain(pinnedItem); }); - it("can update highlighted items", () => { + it('can update highlighted items', () => { expect(uiData.highlightedItems).toEqual([]); - const id = "entry"; + const id = 'entry'; presenter.updateHighlightedItems(id); expect(uiData.highlightedItems).toContain(id); }); - it("can update hierarchy tree", () => { + it('can update hierarchy tree', () => { //change flat view to true const userOptions: UserOptions = { onlyVisible: { - name: "Only visible", - enabled: true + name: 'Only visible', + enabled: true, }, simplifyNames: { - name: "Simplify names", - enabled: true + name: 'Simplify names', + enabled: true, }, flat: { - name: "Flat", - enabled: false - } + name: 'Flat', + enabled: false, + }, }; let expectedChildren = expectHierarchyTreeWithSfSubtree ? 2 : 1; @@ -131,20 +141,20 @@ export function executePresenterInputMethodTests( expect(uiData.tree?.children.length).toEqual(expectedChildren); }); - it("can filter hierarchy tree", () => { + it('can filter hierarchy tree', () => { const userOptions: UserOptions = { onlyVisible: { - name: "Only visible", - enabled: false + name: 'Only visible', + enabled: false, }, simplifyNames: { - name: "Simplify names", - enabled: true + name: 'Simplify names', + enabled: true, }, flat: { - name: "Flat", - enabled: true - } + name: 'Flat', + enabled: true, + }, }; const expectedChildren = expectHierarchyTreeWithSfSubtree ? 12 : 1; @@ -153,30 +163,32 @@ export function executePresenterInputMethodTests( expect(uiData.tree?.children.length).toEqual(expectedChildren); // Filter out all children - presenter.filterHierarchyTree("Reject all"); + presenter.filterHierarchyTree('Reject all'); expect(uiData.tree?.children.length).toEqual(0); }); - it("can set new properties tree and associated ui data", () => { + it('can set new properties tree and associated ui data', () => { presenter.notifyCurrentTraceEntries(entries); presenter.newPropertiesTree(selectedTree); // does not check specific tree values as tree transformation method may change expect(uiData.propertiesTree).toBeTruthy(); }); - it("can filter properties tree", () => { + it('can filter properties tree', () => { presenter.notifyCurrentTraceEntries(entries); presenter.newPropertiesTree(selectedTree); - let nonTerminalChildren = uiData.propertiesTree?.children?.filter( - (child: PropertiesTreeNode) => typeof child.propertyKey === "string" - ) ?? []; + let nonTerminalChildren = + uiData.propertiesTree?.children?.filter( + (child: PropertiesTreeNode) => typeof child.propertyKey === 'string' + ) ?? []; expect(nonTerminalChildren.length).toEqual(expectedChildren[0]); presenter.filterPropertiesTree(propertiesTreeFilterString); - nonTerminalChildren = uiData.propertiesTree?.children?.filter( - (child: PropertiesTreeNode) => typeof child.propertyKey === "string" - ) ?? []; + nonTerminalChildren = + uiData.propertiesTree?.children?.filter( + (child: PropertiesTreeNode) => typeof child.propertyKey === 'string' + ) ?? []; expect(nonTerminalChildren.length).toEqual(expectedChildren[1]); }); }); diff --git a/tools/winscope-ng/src/viewers/common/properties_tree_generator.spec.ts b/tools/winscope-ng/src/viewers/common/properties_tree_generator.spec.ts index 89566b6be..389aaa9f8 100644 --- a/tools/winscope-ng/src/viewers/common/properties_tree_generator.spec.ts +++ b/tools/winscope-ng/src/viewers/common/properties_tree_generator.spec.ts @@ -13,163 +13,161 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import Long from "long"; -import { PropertiesTreeGenerator } from "viewers/common/properties_tree_generator"; -import {PropertiesTreeNode} from "./ui_tree_utils"; +import Long from 'long'; +import {PropertiesTreeGenerator} from 'viewers/common/properties_tree_generator'; +import {PropertiesTreeNode} from './ui_tree_utils'; -describe("PropertiesTreeGenerator", () => { - it("handles boolean", () => { +describe('PropertiesTreeGenerator', () => { + it('handles boolean', () => { const input = true; - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", - propertyValue: "true" + propertyKey: 'root', + propertyValue: 'true', }; expect(actual).toEqual(expected); }); - it("handles number", () => { + it('handles number', () => { const input = 10; - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", - propertyValue: "10" + propertyKey: 'root', + propertyValue: '10', }; expect(actual).toEqual(expected); }); - it("handles longs", () => { + it('handles longs', () => { const input = new Long(10, 100, false); - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", - propertyValue: "429496729610" + propertyKey: 'root', + propertyValue: '429496729610', }; expect(actual).toEqual(expected); }); - it("handles string", () => { - const input = "value"; - const actual = new PropertiesTreeGenerator().generate("root", input); + it('handles string', () => { + const input = 'value'; + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", - propertyValue: "value" + propertyKey: 'root', + propertyValue: 'value', }; expect(actual).toEqual(expected); }); - it("handles empty array", () => { + it('handles empty array', () => { const input: any[] = []; - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", - propertyValue: "[]" + propertyKey: 'root', + propertyValue: '[]', }; expect(actual).toEqual(expected); }); - it("handles array", () => { - const input = ["value0", "value1"]; - const actual = new PropertiesTreeGenerator().generate("root", input); + it('handles array', () => { + const input = ['value0', 'value1']; + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", + propertyKey: 'root', children: [ { - propertyKey: "0", - propertyValue: "value0" + propertyKey: '0', + propertyValue: 'value0', }, { - propertyKey: "1", - propertyValue: "value1" - } - ] + propertyKey: '1', + propertyValue: 'value1', + }, + ], }; expect(actual).toEqual(expected); }); - it("handles empty object", () => { + it('handles empty object', () => { const input = {}; - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", - propertyValue: "{}" + propertyKey: 'root', + propertyValue: '{}', }; expect(actual).toEqual(expected); }); - it("handles object", () => { + it('handles object', () => { const input = { - key0: "value0", - key1: "value1" + key0: 'value0', + key1: 'value1', }; - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", + propertyKey: 'root', children: [ { - propertyKey: "key0", - propertyValue: "value0" + propertyKey: 'key0', + propertyValue: 'value0', }, { - propertyKey: "key1", - propertyValue: "value1" - } - ] + propertyKey: 'key1', + propertyValue: 'value1', + }, + ], }; expect(actual).toEqual(expected); }); - it("handles nested objects", () => { + it('handles nested objects', () => { const input = { object: { - key: "object_value" + key: 'object_value', }, - array: [ - "array_value" - ] + array: ['array_value'], }; - const actual = new PropertiesTreeGenerator().generate("root", input); + const actual = new PropertiesTreeGenerator().generate('root', input); const expected: PropertiesTreeNode = { - propertyKey: "root", + propertyKey: 'root', children: [ { - propertyKey: "object", + propertyKey: 'object', children: [ { - propertyKey: "key", - propertyValue: "object_value" - } - ] + propertyKey: 'key', + propertyValue: 'object_value', + }, + ], }, { - propertyKey: "array", + propertyKey: 'array', children: [ { - propertyKey: "0", - propertyValue: "array_value" - } - ] - } - ] + propertyKey: '0', + propertyValue: 'array_value', + }, + ], + }, + ], }; expect(actual).toEqual(expected); }); -}); \ No newline at end of file +}); diff --git a/tools/winscope-ng/src/viewers/common/properties_tree_generator.ts b/tools/winscope-ng/src/viewers/common/properties_tree_generator.ts index 3e2079f86..e5117b439 100644 --- a/tools/winscope-ng/src/viewers/common/properties_tree_generator.ts +++ b/tools/winscope-ng/src/viewers/common/properties_tree_generator.ts @@ -14,13 +14,10 @@ * limitations under the License. */ -import {PropertiesTreeNode} from "./ui_tree_utils"; +import {PropertiesTreeNode} from './ui_tree_utils'; class PropertiesTreeGenerator { - public generate( - key: string, - value: any, - ): PropertiesTreeNode { + public generate(key: string, value: any): PropertiesTreeNode { if (this.isLeaf(value)) { return { propertyKey: key, @@ -31,15 +28,14 @@ class PropertiesTreeGenerator { let children: PropertiesTreeNode[]; if (Array.isArray(value)) { - children = value.map((element, index) => this.generate("" + index, element)); - } - else { - children = Object.keys(value).map(childName => this.generate(childName, value[childName])); + children = value.map((element, index) => this.generate('' + index, element)); + } else { + children = Object.keys(value).map((childName) => this.generate(childName, value[childName])); } return { propertyKey: key, - children: children + children: children, }; } @@ -47,35 +43,37 @@ class PropertiesTreeGenerator { return this.leafToString(value) !== undefined; } - private leafToString(value: any): undefined|string { + private leafToString(value: any): undefined | string { if (value == null) { - return ""; + return ''; } - if (typeof value === "boolean") { - return "" + value; + if (typeof value === 'boolean') { + return '' + value; } - if (typeof value === "number") { - return "" + value; + if (typeof value === 'number') { + return '' + value; } - if (typeof value === "string") { + if (typeof value === 'string') { return value; } if (this.isLong(value)) { return value.toString(); } if (Array.isArray(value) && value.length === 0) { - return "[]"; + return '[]'; } - if (typeof value === "object" && Object.keys(value).length === 0) { - return "{}"; + if (typeof value === 'object' && Object.keys(value).length === 0) { + return '{}'; } return undefined; } private isLong(value: any) { - return Object.prototype.hasOwnProperty.call(value, "high") && - Object.prototype.hasOwnProperty.call(value, "low") && - Object.prototype.hasOwnProperty.call(value, "unsigned"); + return ( + Object.prototype.hasOwnProperty.call(value, 'high') && + Object.prototype.hasOwnProperty.call(value, 'low') && + Object.prototype.hasOwnProperty.call(value, 'unsigned') + ); } } diff --git a/tools/winscope-ng/src/viewers/common/rectangle.ts b/tools/winscope-ng/src/viewers/common/rectangle.ts index ee2ff9cfb..5a8817a93 100644 --- a/tools/winscope-ng/src/viewers/common/rectangle.ts +++ b/tools/winscope-ng/src/viewers/common/rectangle.ts @@ -30,13 +30,13 @@ export interface Rectangle { } export interface Point { - x: number, - y: number + x: number; + y: number; } export interface Size { - width: number, - height: number + width: number; + height: number; } export interface RectTransform { diff --git a/tools/winscope-ng/src/viewers/common/table_properties.ts b/tools/winscope-ng/src/viewers/common/table_properties.ts index 1c44acdb8..68aff48c1 100644 --- a/tools/winscope-ng/src/viewers/common/table_properties.ts +++ b/tools/winscope-ng/src/viewers/common/table_properties.ts @@ -15,4 +15,4 @@ */ export type TableProperties = { [key: string]: string | boolean | undefined; -} +}; diff --git a/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts b/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts index 95f3bed6b..f8fc7d5f3 100644 --- a/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts +++ b/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts @@ -13,109 +13,180 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { TreeUtils } from "common/utils/tree_utils"; -import { DiffType, HierarchyTreeNode} from "viewers/common/ui_tree_utils"; -import { TreeGenerator } from "viewers/common/tree_generator"; -import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TreeUtils} from 'common/utils/tree_utils'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {TreeGenerator} from 'viewers/common/tree_generator'; +import {DiffType, HierarchyTreeNode} from 'viewers/common/ui_tree_utils'; -describe("TreeGenerator", () => { +describe('TreeGenerator', () => { let entry: TraceTreeNode; + beforeAll(async () => { entry = { - kind: "entry", - name: "BaseLayerTraceEntry", - stableId: "BaseLayerTraceEntry", - id: 0, - parent: undefined, - children: [{ - kind: "3", - id: 3, - name: "Child1", - stableId: "3 Child1", - parent: undefined, - children: [ - { - kind: "2", - id: 2, - name: "Child2", - stableId: "2 Child2", - parent: undefined, - children: [], - } - ]}] - }; - }); - it("generates tree", () => { - const expected: HierarchyTreeNode = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry") - .setChildren([ - new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").setKind("3").setChildren([ - new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).build() - ]).setId(3).build() - ]).setId(0).build(); - - const filter = TreeUtils.makeNodeFilter(""); - const generator = new TreeGenerator(entry, filter); - expect(generator.generateTree()).toEqual(expected); - }); - - it("generates diff tree with no diff", () => { - const expected: HierarchyTreeNode = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry") - .setChildren([ - new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").setKind("3").setChildren([ - new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).setDiffType(DiffType.NONE).build() - ]).setId(3).setDiffType(DiffType.NONE).build() - ]).setId(0).setDiffType(DiffType.NONE).build(); - - const filter = TreeUtils.makeNodeFilter(""); - const tree = new TreeGenerator(entry, filter).withUniqueNodeId((node: any) => { - if (node) return node.stableId; - else return null; - }).compareWith(entry).generateFinalTreeWithDiff(); - expect(tree).toEqual(expected); - }); - - it("generates diff tree with moved node", () => { - const prevEntry: TraceTreeNode = { - kind: "entry", - name: "BaseLayerTraceEntry", - stableId: "BaseLayerTraceEntry", + kind: 'entry', + name: 'BaseLayerTraceEntry', + stableId: 'BaseLayerTraceEntry', id: 0, parent: undefined, children: [ { - kind: "3", + kind: '3', id: 3, - stableId: "3 Child1", - name: "Child1", + name: 'Child1', + stableId: '3 Child1', parent: undefined, - children: [] + children: [ + { + kind: '2', + id: 2, + name: 'Child2', + stableId: '2 Child2', + parent: undefined, + children: [], + }, + ], }, + ], + }; + }); + + it('generates tree', () => { + const expected: HierarchyTreeNode = new HierarchyTreeBuilder() + .setName('BaseLayerTraceEntry') + .setKind('entry') + .setStableId('BaseLayerTraceEntry') + .setChildren([ + new HierarchyTreeBuilder() + .setName('Child1') + .setStableId('3 Child1') + .setKind('3') + .setChildren([ + new HierarchyTreeBuilder() + .setName('Child2') + .setStableId('2 Child2') + .setKind('2') + .setId(2) + .build(), + ]) + .setId(3) + .build(), + ]) + .setId(0) + .build(); + + const filter = TreeUtils.makeNodeFilter(''); + const generator = new TreeGenerator(entry, filter); + expect(generator.generateTree()).toEqual(expected); + }); + + it('generates diff tree with no diff', () => { + const expected: HierarchyTreeNode = new HierarchyTreeBuilder() + .setName('BaseLayerTraceEntry') + .setKind('entry') + .setStableId('BaseLayerTraceEntry') + .setChildren([ + new HierarchyTreeBuilder() + .setName('Child1') + .setStableId('3 Child1') + .setKind('3') + .setChildren([ + new HierarchyTreeBuilder() + .setName('Child2') + .setStableId('2 Child2') + .setKind('2') + .setId(2) + .setDiffType(DiffType.NONE) + .build(), + ]) + .setId(3) + .setDiffType(DiffType.NONE) + .build(), + ]) + .setId(0) + .setDiffType(DiffType.NONE) + .build(); + + const filter = TreeUtils.makeNodeFilter(''); + const tree = new TreeGenerator(entry, filter) + .withUniqueNodeId((node: any) => { + if (node) return node.stableId; + else return null; + }) + .compareWith(entry) + .generateFinalTreeWithDiff(); + expect(tree).toEqual(expected); + }); + + it('generates diff tree with moved node', () => { + const prevEntry: TraceTreeNode = { + kind: 'entry', + name: 'BaseLayerTraceEntry', + stableId: 'BaseLayerTraceEntry', + id: 0, + parent: undefined, + children: [ { - kind: "2", - id: 2, - stableId: "2 Child2", - name: "Child2", + kind: '3', + id: 3, + stableId: '3 Child1', + name: 'Child1', parent: undefined, children: [], - } - ] + }, + { + kind: '2', + id: 2, + stableId: '2 Child2', + name: 'Child2', + parent: undefined, + children: [], + }, + ], }; - const expected: HierarchyTreeNode = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry") + const expected: HierarchyTreeNode = new HierarchyTreeBuilder() + .setName('BaseLayerTraceEntry') + .setKind('entry') + .setStableId('BaseLayerTraceEntry') .setChildren([ - new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").setKind("3").setChildren([ - new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).setDiffType(DiffType.ADDED_MOVE).build() - ]).setId(3).setDiffType(DiffType.NONE).build(), - new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).setDiffType(DiffType.DELETED_MOVE).build() - ]).setId(0).setDiffType(DiffType.NONE).build(); + new HierarchyTreeBuilder() + .setName('Child1') + .setStableId('3 Child1') + .setKind('3') + .setChildren([ + new HierarchyTreeBuilder() + .setName('Child2') + .setStableId('2 Child2') + .setKind('2') + .setId(2) + .setDiffType(DiffType.ADDED_MOVE) + .build(), + ]) + .setId(3) + .setDiffType(DiffType.NONE) + .build(), + new HierarchyTreeBuilder() + .setName('Child2') + .setStableId('2 Child2') + .setKind('2') + .setId(2) + .setDiffType(DiffType.DELETED_MOVE) + .build(), + ]) + .setId(0) + .setDiffType(DiffType.NONE) + .build(); - const filter = TreeUtils.makeNodeFilter(""); + const filter = TreeUtils.makeNodeFilter(''); const generator = new TreeGenerator(entry, filter); - const newDiffTree = generator.withUniqueNodeId((node: any) => { - if (node) return node.stableId; - else return null; - }).compareWith(prevEntry).generateFinalTreeWithDiff(); + const newDiffTree = generator + .withUniqueNodeId((node: any) => { + if (node) return node.stableId; + else return null; + }) + .compareWith(prevEntry) + .generateFinalTreeWithDiff(); expect(newDiffTree).toEqual(expected); }); diff --git a/tools/winscope-ng/src/viewers/common/tree_generator.ts b/tools/winscope-ng/src/viewers/common/tree_generator.ts index 7054559d8..f3f3009ff 100644 --- a/tools/winscope-ng/src/viewers/common/tree_generator.ts +++ b/tools/winscope-ng/src/viewers/common/tree_generator.ts @@ -13,25 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TreeNode, FilterType} from "common/utils/tree_utils"; -import {TraceTreeNode} from "common/trace/trace_tree_node"; +import ObjectFormatter from 'common/trace/flickerlib/ObjectFormatter'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {FilterType, TreeNode} from 'common/utils/tree_utils'; import { - UiTreeUtils, - DiffType, - HierarchyTreeNode -} from "./ui_tree_utils"; -import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter"; -import { - HWC_CHIP, GPU_CHIP, + HWC_CHIP, MISSING_LAYER, - VISIBLE_CHIP, RELATIVE_Z_CHIP, - RELATIVE_Z_PARENT_CHIP -} from "viewers/common/chip"; + RELATIVE_Z_PARENT_CHIP, + VISIBLE_CHIP, +} from 'viewers/common/chip'; +import {DiffType, HierarchyTreeNode, UiTreeUtils} from './ui_tree_utils'; type GetNodeIdCallbackType = (node: TraceTreeNode | null) => string | null; -type IsModifiedCallbackType = (newTree: TraceTreeNode | null, oldTree: TraceTreeNode | null) => boolean; +type IsModifiedCallbackType = ( + newTree: TraceTreeNode | null, + oldTree: TraceTreeNode | null +) => boolean; const HwcCompositionType = { CLIENT: 1, @@ -89,7 +88,7 @@ export class TreeGenerator { this.getNodeId = (node: TraceTreeNode | null) => { const id = getNodeId ? getNodeId(node) : this.defaultNodeIdCallback(node); if (id === null || id === undefined) { - console.error("Null node ID for node", node); + console.error('Null node ID for node', node); throw new Error("Node ID can't be null or undefined"); } return id; @@ -111,11 +110,11 @@ export class TreeGenerator { let diffTree: TraceTreeNode; if (diffTrees.length > 1) { diffTree = { - kind: "", - name: "DiffTree", + kind: '', + name: 'DiffTree', parent: undefined, children: diffTrees, - stableId: "DiffTree", + stableId: 'DiffTree', }; } else { diffTree = diffTrees[0]; @@ -143,7 +142,8 @@ export class TreeGenerator { private flattenChildren(children: Array) { for (let i = 0; i < children.length; i++) { const child = children[i]; - const childIsVisibleNode = child.isVisible && UiTreeUtils.isVisibleNode(child.kind, child.type); + const childIsVisibleNode = + child.isVisible && UiTreeUtils.isVisibleNode(child.kind, child.type); const showInOnlyVisibleView = this.isOnlyVisibleView && childIsVisibleNode; const passVisibleCheck = !this.isOnlyVisibleView || showInOnlyVisibleView; if (this.filterMatches(child) && passVisibleCheck) { @@ -163,10 +163,7 @@ export class TreeGenerator { tree: TraceTreeNode, parentFilterMatch: boolean ): HierarchyTreeNode | null { - return this.applyChecks( - tree, - parentFilterMatch - ); + return this.applyChecks(tree, parentFilterMatch); } private updateTreeWithRelZParentChips(tree: HierarchyTreeNode): HierarchyTreeNode { @@ -189,18 +186,20 @@ export class TreeGenerator { private addChips(tree: HierarchyTreeNode): HierarchyTreeNode { if (tree.hwcCompositionType == HwcCompositionType.CLIENT) { tree.chips.push(GPU_CHIP); - } else if ((tree.hwcCompositionType == HwcCompositionType.DEVICE || - tree.hwcCompositionType == HwcCompositionType.SOLID_COLOR)) { + } else if ( + tree.hwcCompositionType == HwcCompositionType.DEVICE || + tree.hwcCompositionType == HwcCompositionType.SOLID_COLOR + ) { tree.chips.push(HWC_CHIP); } if (tree.isVisible && UiTreeUtils.isVisibleNode(tree.kind, tree.type)) { tree.chips.push(VISIBLE_CHIP); } if ( - tree.zOrderRelativeOfId !== undefined - && tree.zOrderRelativeOfId !== -1 - && !UiTreeUtils.isParentNode(tree.kind) - && !tree.isRootLayer + tree.zOrderRelativeOfId !== undefined && + tree.zOrderRelativeOfId !== -1 && + !UiTreeUtils.isParentNode(tree.kind) && + !tree.isRootLayer ) { tree.chips.push(RELATIVE_Z_CHIP); this.relZParentIds.push(`${tree.zOrderRelativeOfId}`); @@ -211,10 +210,7 @@ export class TreeGenerator { return tree; } - private applyChecks( - tree: TraceTreeNode, - parentFilterMatch: boolean - ): HierarchyTreeNode | null { + private applyChecks(tree: TraceTreeNode, parentFilterMatch: boolean): HierarchyTreeNode | null { let newTree = this.makeTreeNode(tree); // add id field to tree if id does not exist (e.g. for WM traces) @@ -234,7 +230,9 @@ export class TreeGenerator { } if (this.isOnlyVisibleView) { - newTree.showInOnlyVisibleView = UiTreeUtils.isParentNode(tree.kind) ? true : newTree.isVisible; + newTree.showInOnlyVisibleView = UiTreeUtils.isParentNode(tree.kind) + ? true + : newTree.isVisible; } newTree.children = []; @@ -270,7 +268,10 @@ export class TreeGenerator { return newTree; } - private generateIdToNodeMapping(node: TraceTreeNode, acc?: Map): Map { + private generateIdToNodeMapping( + node: TraceTreeNode, + acc?: Map + ): Map { acc = acc || new Map(); const nodeId: string = this.getNodeId!(node)!; @@ -301,11 +302,7 @@ export class TreeGenerator { } private makeTreeNode(node: TraceTreeNode): HierarchyTreeNode { - const clone = new HierarchyTreeNode( - node.name, - node.kind, - node.stableId, - ); + const clone = new HierarchyTreeNode(node.name, node.kind, node.stableId); if (node.shortName) clone.shortName = node.shortName; if (node.type) clone.type = node.type; if (node.id) clone.id = node.id; @@ -411,13 +408,16 @@ export class TreeGenerator { diffTrees.push(diffTree); } } else { - throw new Error("Both newTree and oldTree are undefined..."); + throw new Error('Both newTree and oldTree are undefined...'); } return diffTrees; } - private visitChildren(newTree: TraceTreeNode | null, oldTree: TraceTreeNode | null): Array { + private visitChildren( + newTree: TraceTreeNode | null, + oldTree: TraceTreeNode | null + ): Array { // Recursively traverse all children of new and old tree. const diffChildren = []; const numOfChildren = Math.max(newTree?.children?.length ?? 0, oldTree?.children?.length ?? 0); @@ -426,9 +426,11 @@ export class TreeGenerator { const oldChild = oldTree?.children ? oldTree.children[i] : null; const childDiffTrees = this.generateDiffTree( - newChild, oldChild, - newTree?.children ?? [], oldTree?.children ?? [], - ).filter(tree => tree != null); + newChild, + oldChild, + newTree?.children ?? [], + oldTree?.children ?? [] + ).filter((tree) => tree != null); diffChildren.push(...childDiffTrees); } @@ -439,7 +441,10 @@ export class TreeGenerator { return node ? node.stableId : null; } - private defaultModifiedCheck(newNode: TraceTreeNode | null, oldNode: TraceTreeNode | null): boolean { + private defaultModifiedCheck( + newNode: TraceTreeNode | null, + oldNode: TraceTreeNode | null + ): boolean { if (!newNode && !oldNode) { return false; } else if (newNode && UiTreeUtils.isParentNode(newNode.kind)) { diff --git a/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts b/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts index 2be56d749..1cfa64219 100644 --- a/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts +++ b/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts @@ -13,101 +13,105 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceTreeNode} from "common/trace/trace_tree_node"; -import {TreeUtils} from "common/utils/tree_utils"; -import {TreeTransformer} from "viewers/common/tree_transformer"; -import {DiffType, HierarchyTreeNode} from "viewers/common/ui_tree_utils"; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TreeUtils} from 'common/utils/tree_utils'; +import {TreeTransformer} from 'viewers/common/tree_transformer'; +import {DiffType, HierarchyTreeNode} from 'viewers/common/ui_tree_utils'; -describe("TreeTransformer", () => { +describe('TreeTransformer', () => { let entry: TraceTreeNode; let selectedTree: HierarchyTreeNode; beforeAll(async () => { entry = { id: 3, - name: "Child1", + name: 'Child1', stackId: 0, isVisible: true, - kind: "3", - stableId: "3 Child1", + kind: '3', + stableId: '3 Child1', proto: { barrierLayer: [], id: 3, parent: 1, - type: "ContainerLayer", + type: 'ContainerLayer', }, parent: undefined, - children: [{ - id: 2, - name: "Child2", - stackId: 0, - parent: undefined, - children: [], - kind: "2", - stableId: "2 Child2", - proto: { - barrierLayer: [], + children: [ + { id: 2, - parent: 3, - type: "ContainerLayer", + name: 'Child2', + stackId: 0, + parent: undefined, + children: [], + kind: '2', + stableId: '2 Child2', + proto: { + barrierLayer: [], + id: 2, + parent: 3, + type: 'ContainerLayer', + }, + isVisible: true, }, - isVisible: true, - }], + ], }; selectedTree = { id: 3, - name: "Child1", + name: 'Child1', stackId: 0, isVisible: true, - kind: "3", - stableId: "3 Child1", + kind: '3', + stableId: '3 Child1', showInFilteredView: true, skip: null, chips: [], - children: [{ - id: 2, - name: "Child2", - stackId: 0, - children: [], - kind: "2", - stableId: "2 Child2", - isVisible: true, - showInFilteredView: true, - chips: [], - }], + children: [ + { + id: 2, + name: 'Child2', + stackId: 0, + children: [], + kind: '2', + stableId: '2 Child2', + isVisible: true, + showInFilteredView: true, + chips: [], + }, + ], }; }); - it("creates ordinary properties tree without show diff enabled", () => { + it('creates ordinary properties tree without show diff enabled', () => { const expected = { - kind: "", - name: "Child1", - stableId: "3 Child1", + kind: '', + name: 'Child1', + stableId: '3 Child1', children: [ { - kind: "", - name: "id: 3", - stableId: "3 Child1.id", + kind: '', + name: 'id: 3', + stableId: '3 Child1.id', children: [], combined: true, - propertyKey: "id", - propertyValue: "3" + propertyKey: 'id', + propertyValue: '3', }, { - kind: "", - name: "type: ContainerLayer", - stableId: "3 Child1.type", + kind: '', + name: 'type: ContainerLayer', + stableId: '3 Child1.type', children: [], combined: true, - propertyKey: "type", - propertyValue: "ContainerLayer" + propertyKey: 'type', + propertyValue: 'ContainerLayer', }, ], - propertyKey: "Child1", - propertyValue: null + propertyKey: 'Child1', + propertyValue: null, }; - const filter = TreeUtils.makeNodeFilter(""); + const filter = TreeUtils.makeNodeFilter(''); const transformer = new TreeTransformer(selectedTree, filter) .setOnlyProtoDump(true) .setProperties(entry); @@ -116,39 +120,39 @@ describe("TreeTransformer", () => { expect(transformedTree).toEqual(expected); }); - it("creates properties tree with show diff enabled, comparing to a null previous entry", () => { + it('creates properties tree with show diff enabled, comparing to a null previous entry', () => { const expected = { - kind: "", - name: "Child1", - stableId: "3 Child1", + kind: '', + name: 'Child1', + stableId: '3 Child1', children: [ { - kind: "", - name: "id: 3", + kind: '', + name: 'id: 3', diffType: DiffType.ADDED, - stableId: "3 Child1.id", + stableId: '3 Child1.id', children: [], combined: true, - propertyKey: "id", - propertyValue: "3" + propertyKey: 'id', + propertyValue: '3', }, { - kind: "", - name: "type: ContainerLayer", + kind: '', + name: 'type: ContainerLayer', diffType: DiffType.ADDED, - stableId: "3 Child1.type", + stableId: '3 Child1.type', children: [], combined: true, - propertyKey: "type", - propertyValue: "ContainerLayer" + propertyKey: 'type', + propertyValue: 'ContainerLayer', }, ], diffType: DiffType.NONE, - propertyKey: "Child1", + propertyKey: 'Child1', propertyValue: null, }; - const filter = TreeUtils.makeNodeFilter(""); + const filter = TreeUtils.makeNodeFilter(''); const transformer = new TreeTransformer(selectedTree, filter) .setIsShowDiff(true) .setOnlyProtoDump(true) diff --git a/tools/winscope-ng/src/viewers/common/tree_transformer.ts b/tools/winscope-ng/src/viewers/common/tree_transformer.ts index c6ad1353a..d374cfe93 100644 --- a/tools/winscope-ng/src/viewers/common/tree_transformer.ts +++ b/tools/winscope-ng/src/viewers/common/tree_transformer.ts @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter"; -import {TraceTreeNode} from "common/trace/trace_tree_node"; -import {TreeNode, FilterType} from "common/utils/tree_utils"; +import ObjectFormatter from 'common/trace/flickerlib/ObjectFormatter'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {FilterType, TreeNode} from 'common/utils/tree_utils'; import { - PropertiesTreeNode, DiffType, - Terminal, HierarchyTreeNode, - PropertiesDump -} from "./ui_tree_utils"; + PropertiesDump, + PropertiesTreeNode, + Terminal, +} from './ui_tree_utils'; interface TransformOptions { freeze: boolean; @@ -46,7 +46,9 @@ export class TreeTransformer { private options?: TreeTransformerOptions; private onlyProtoDump = false; private transformOptions: TransformOptions = { - keepOriginal: false, freeze: true, metadataKey: null, + keepOriginal: false, + freeze: true, + metadataKey: null, }; constructor(selectedTree: HierarchyTreeNode, filter: FilterType) { @@ -83,20 +85,27 @@ export class TreeTransformer { const currFlickerItem = this.getOriginalFlickerItem(currentEntry, this.stableId); const target = currFlickerItem ? currFlickerItem.obj ?? currFlickerItem : null; ObjectFormatter.displayDefaults = this.isShowDefaults; - this.properties = this.onlyProtoDump ? this.getProtoDumpPropertiesForDisplay(target) : this.getPropertiesForDisplay(target); + this.properties = this.onlyProtoDump + ? this.getProtoDumpPropertiesForDisplay(target) + : this.getPropertiesForDisplay(target); return this; } - public setDiffProperties(previousEntry: TraceTreeNode | null): TreeTransformer { + public setDiffProperties(previousEntry: TraceTreeNode | null): TreeTransformer { if (this.isShowDiff) { const prevFlickerItem = this.findFlickerItem(previousEntry, this.stableId); const target = prevFlickerItem ? prevFlickerItem.obj ?? prevFlickerItem : null; - this.compareWithProperties = this.onlyProtoDump ? this.getProtoDumpPropertiesForDisplay(target) : this.getPropertiesForDisplay(target); + this.compareWithProperties = this.onlyProtoDump + ? this.getProtoDumpPropertiesForDisplay(target) + : this.getPropertiesForDisplay(target); } return this; } - public getOriginalFlickerItem(entry: TraceTreeNode | null, stableId: string): TraceTreeNode | null { + public getOriginalFlickerItem( + entry: TraceTreeNode | null, + stableId: string + ): TraceTreeNode | null { return this.findFlickerItem(entry, stableId); } @@ -116,7 +125,10 @@ export class TreeTransformer { return ObjectFormatter.format(entry); } - private findFlickerItem(entryFlickerItem: TraceTreeNode | null, stableId: string): TraceTreeNode | null { + private findFlickerItem( + entryFlickerItem: TraceTreeNode | null, + stableId: string + ): TraceTreeNode | null { if (!entryFlickerItem) { return null; } @@ -139,16 +151,20 @@ export class TreeTransformer { return null; } - public transform(): PropertiesTreeNode { const {formatter} = this.options!; if (!formatter) { - throw new Error("Missing formatter, please set with setOptions()"); + throw new Error('Missing formatter, please set with setOptions()'); } - const transformedTree = this.transformTree(this.properties, this.rootName, - this.compareWithProperties, this.rootName, - this.stableId, this.transformOptions); + const transformedTree = this.transformTree( + this.properties, + this.rootName, + this.compareWithProperties, + this.rootName, + this.stableId, + this.transformOptions + ); return transformedTree; } @@ -158,21 +174,22 @@ export class TreeTransformer { compareWithProperties: PropertiesDump | null | Terminal, compareWithName: string | Terminal, stableId: string, - transformOptions: TransformOptions, + transformOptions: TransformOptions ): PropertiesTreeNode { const originalProperties = properties; - const metadata = this.getMetadata( - originalProperties, transformOptions.metadataKey - ); + const metadata = this.getMetadata(originalProperties, transformOptions.metadataKey); const children: any[] = []; if (properties === null) { - properties = "null"; + properties = 'null'; } if (!this.isTerminal(properties)) { - const transformedProperties = this.transformProperties(properties, transformOptions.metadataKey); + const transformedProperties = this.transformProperties( + properties, + transformOptions.metadataKey + ); properties = transformedProperties.properties; } @@ -185,16 +202,25 @@ export class TreeTransformer { } for (const key in properties) { - if (!(properties instanceof Terminal)/* && properties[key]*/) { + if (!(properties instanceof Terminal) /* && properties[key]*/) { let compareWithChild = new Terminal(); let compareWithChildName = new Terminal(); - if (compareWithProperties && !(compareWithProperties instanceof Terminal) && compareWithProperties[key]) { + if ( + compareWithProperties && + !(compareWithProperties instanceof Terminal) && + compareWithProperties[key] + ) { compareWithChild = compareWithProperties[key]; compareWithChildName = key; } - const child = this.transformTree(properties[key], key, - compareWithChild, compareWithChildName, - `${stableId}.${key}`, transformOptions); + const child = this.transformTree( + properties[key], + key, + compareWithChild, + compareWithChildName, + `${stableId}.${key}`, + transformOptions + ); children.push(child); } @@ -202,28 +228,34 @@ export class TreeTransformer { // Takes care of adding deleted items to final tree for (const key in compareWithProperties) { - if (properties && !(properties instanceof Terminal) && !properties[key] && - !(compareWithProperties instanceof Terminal) && compareWithProperties[key]) { - const child = this.transformTree(new Terminal(), new Terminal(), - compareWithProperties[key], key, - `${stableId}.${key}`, transformOptions); + if ( + properties && + !(properties instanceof Terminal) && + !properties[key] && + !(compareWithProperties instanceof Terminal) && + compareWithProperties[key] + ) { + const child = this.transformTree( + new Terminal(), + new Terminal(), + compareWithProperties[key], + key, + `${stableId}.${key}`, + transformOptions + ); children.push(child); } } let transformedProperties: any; - if ( - children.length == 1 && - children[0].children?.length == 0 && - !children[0].combined - ) { + if (children.length == 1 && children[0].children?.length == 0 && !children[0].combined) { // Merge leaf key value pairs. const child = children[0]; transformedProperties = { - kind: "", - name: (this.isTerminal(name) ? compareWithName : name) + ": " + child.name, + kind: '', + name: (this.isTerminal(name) ? compareWithName : name) + ': ' + child.name, stableId, children: child.children, combined: true, @@ -234,7 +266,7 @@ export class TreeTransformer { } } else { transformedProperties = { - kind: "", + kind: '', name, stableId, children, @@ -263,8 +295,10 @@ export class TreeTransformer { transformedProperties.propertyValue = this.getPropertyValue(transformedProperties); } - if (!this.filterMatches(transformedProperties) && - !this.hasChildMatchingFilter(transformedProperties?.children)) { + if ( + !this.filterMatches(transformedProperties) && + !this.hasChildMatchingFilter(transformedProperties?.children) + ) { transformedProperties.propertyKey = new Terminal(); } return transformOptions.freeze ? Object.freeze(transformedProperties) : transformedProperties; @@ -274,7 +308,7 @@ export class TreeTransformer { if (!children || children.length === 0) return false; let match = false; - for (let i=0; iitem) ?? false; } - private transformProperties(properties: PropertiesDump, metadataKey: string | null): PropertiesTreeNode { + private transformProperties( + properties: PropertiesDump, + metadataKey: string | null + ): PropertiesTreeNode { const {skip, formatter} = this.options!; const transformedProperties: PropertiesTreeNode = { properties: {}, @@ -330,19 +366,19 @@ export class TreeTransformer { transformedProperties.properties[formatted] = new Terminal(); } else if (Array.isArray(properties)) { properties.forEach((e, i) => { - transformedProperties.properties["" + i] = e; + transformedProperties.properties['' + i] = e; }); - } else if (typeof properties == "string") { + } else if (typeof properties == 'string') { // Object is a primitive type — has no children. Set to terminal // to differentiate between null object and Terminal element. transformedProperties.properties[properties] = new Terminal(); - } else if (typeof properties == "number" || typeof properties == "boolean") { + } else if (typeof properties == 'number' || typeof properties == 'boolean') { // Similar to above — primitive type node has no children. - transformedProperties.properties["" + properties] = new Terminal(); - } else if (properties && typeof properties == "object") { + transformedProperties.properties['' + properties] = new Terminal(); + } else if (properties && typeof properties == 'object') { // Empty objects if (Object.keys(properties).length == 0) { - transformedProperties.properties["[empty]"] = new Terminal(); + transformedProperties.properties['[empty]'] = new Terminal(); } else { // Non empty objects Object.keys(properties).forEach((key) => { @@ -374,7 +410,7 @@ export class TreeTransformer { private compatibleStableId(item: HierarchyTreeNode): string { // For backwards compatibility // (the only item that doesn't have a unique stable ID in the tree) - if (item.stableId === "winToken|-|") { + if (item.stableId === 'winToken|-|') { return item.stableId + item.children[0].stableId; } return item.stableId; diff --git a/tools/winscope-ng/src/viewers/common/ui_tree_utils.ts b/tools/winscope-ng/src/viewers/common/ui_tree_utils.ts index 87b698a56..73e2ef686 100644 --- a/tools/winscope-ng/src/viewers/common/ui_tree_utils.ts +++ b/tools/winscope-ng/src/viewers/common/ui_tree_utils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import Chip from "./chip"; +import Chip from './chip'; export type UiTreeNode = HierarchyTreeNode | PropertiesTreeNode; @@ -67,21 +67,20 @@ export interface PropertiesTreeNode { } //TODO: make specific export const DiffType = { - NONE: "none", - ADDED: "added", - DELETED: "deleted", - ADDED_MOVE: "addedMove", - DELETED_MOVE: "deletedMove", - MODIFIED: "modified", + NONE: 'none', + ADDED: 'added', + DELETED: 'deleted', + ADDED_MOVE: 'addedMove', + DELETED_MOVE: 'deletedMove', + MODIFIED: 'modified', }; export class Terminal {} -export class UiTreeUtils -{ +export class UiTreeUtils { public static diffClass(item: UiTreeNode): string { const diffType = item.diffType; - return diffType ?? ""; + return diffType ?? ''; } public static isHighlighted(item: UiTreeNode, highlightedItems: Array) { @@ -89,7 +88,7 @@ export class UiTreeUtils } public static isVisibleNode(kind: string, type?: string) { - return kind === "WindowState" || kind === "Activity" || type?.includes("Layer"); + return kind === 'WindowState' || kind === 'Activity' || type?.includes('Layer'); } public static isParentNode(kind: string) { @@ -97,10 +96,10 @@ export class UiTreeUtils } private static readonly PARENT_NODE_KINDS = [ - "entry", - "WindowManagerState", - "InputMethodClient entry", - "InputMethodService entry", - "InputMethodManagerService entry" + 'entry', + 'WindowManagerState', + 'InputMethodClient entry', + 'InputMethodService entry', + 'InputMethodManagerService entry', ]; } diff --git a/tools/winscope-ng/src/viewers/common/user_options.ts b/tools/winscope-ng/src/viewers/common/user_options.ts index 9da222512..d5c2bdb8d 100644 --- a/tools/winscope-ng/src/viewers/common/user_options.ts +++ b/tools/winscope-ng/src/viewers/common/user_options.ts @@ -15,8 +15,8 @@ */ export interface UserOptions { [key: string]: { - name: string, - enabled: boolean, - tooltip?: string - } -} \ No newline at end of file + name: string; + enabled: boolean; + tooltip?: string; + }; +} diff --git a/tools/winscope-ng/src/viewers/common/viewer_events.ts b/tools/winscope-ng/src/viewers/common/viewer_events.ts index d7265da8c..fd109da39 100644 --- a/tools/winscope-ng/src/viewers/common/viewer_events.ts +++ b/tools/winscope-ng/src/viewers/common/viewer_events.ts @@ -14,12 +14,12 @@ * limitations under the License. */ export const ViewerEvents = { - HierarchyPinnedChange: "HierarchyPinnedChange", - HighlightedChange: "HighlightedChange", - HierarchyUserOptionsChange: "HierarchyUserOptionsChange", - HierarchyFilterChange: "HierarchyFilterChange", - SelectedTreeChange: "SelectedTreeChange", - PropertiesUserOptionsChange: "PropertiesUserOptionsChange", - PropertiesFilterChange: "PropertiesFilterChange", - AdditionalPropertySelected: "AdditionalPropertySelected" + HierarchyPinnedChange: 'HierarchyPinnedChange', + HighlightedChange: 'HighlightedChange', + HierarchyUserOptionsChange: 'HierarchyUserOptionsChange', + HierarchyFilterChange: 'HierarchyFilterChange', + SelectedTreeChange: 'SelectedTreeChange', + PropertiesUserOptionsChange: 'PropertiesUserOptionsChange', + PropertiesFilterChange: 'PropertiesFilterChange', + AdditionalPropertySelected: 'AdditionalPropertySelected', }; diff --git a/tools/winscope-ng/src/viewers/common/viewer_input_method.ts b/tools/winscope-ng/src/viewers/common/viewer_input_method.ts index 4e25b059b..9b0a37273 100644 --- a/tools/winscope-ng/src/viewers/common/viewer_input_method.ts +++ b/tools/winscope-ng/src/viewers/common/viewer_input_method.ts @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {View, Viewer, ViewType} from "viewers/viewer"; -import {ViewerEvents} from "viewers/common/viewer_events"; -import {PresenterInputMethod} from "viewers/common/presenter_input_method"; -import {ImeUiData} from "viewers/common/ime_ui_data"; +import {TraceType} from 'common/trace/trace_type'; +import {ImeUiData} from 'viewers/common/ime_ui_data'; +import {PresenterInputMethod} from 'viewers/common/presenter_input_method'; +import {ViewerEvents} from 'viewers/common/viewer_events'; +import {View, Viewer} from 'viewers/viewer'; abstract class ViewerInputMethod implements Viewer { constructor(storage: Storage) { - this.htmlElement = document.createElement("viewer-input-method"); + this.htmlElement = document.createElement('viewer-input-method'); this.presenter = this.initialisePresenter(storage); this.addViewerEventListeners(); } @@ -42,14 +42,30 @@ abstract class ViewerInputMethod implements Viewer { }; protected addViewerEventListeners() { - this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => this.presenter.updatePinnedItems(((event as CustomEvent).detail.pinnedItem))); - this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`)); - this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions)); - this.htmlElement.addEventListener(ViewerEvents.HierarchyFilterChange, (event) => this.presenter.filterHierarchyTree((event as CustomEvent).detail.filterString)); - this.htmlElement.addEventListener(ViewerEvents.PropertiesUserOptionsChange, (event) => this.presenter.updatePropertiesTree((event as CustomEvent).detail.userOptions)); - this.htmlElement.addEventListener(ViewerEvents.PropertiesFilterChange, (event) => this.presenter.filterPropertiesTree((event as CustomEvent).detail.filterString)); - this.htmlElement.addEventListener(ViewerEvents.SelectedTreeChange, (event) => this.presenter.newPropertiesTree((event as CustomEvent).detail.selectedItem)); - this.htmlElement.addEventListener(ViewerEvents.AdditionalPropertySelected, (event) => this.presenter.newAdditionalPropertiesTree((event as CustomEvent).detail.selectedItem)); + this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => + this.presenter.updatePinnedItems((event as CustomEvent).detail.pinnedItem) + ); + this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => + this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`) + ); + this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => + this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions) + ); + this.htmlElement.addEventListener(ViewerEvents.HierarchyFilterChange, (event) => + this.presenter.filterHierarchyTree((event as CustomEvent).detail.filterString) + ); + this.htmlElement.addEventListener(ViewerEvents.PropertiesUserOptionsChange, (event) => + this.presenter.updatePropertiesTree((event as CustomEvent).detail.userOptions) + ); + this.htmlElement.addEventListener(ViewerEvents.PropertiesFilterChange, (event) => + this.presenter.filterPropertiesTree((event as CustomEvent).detail.filterString) + ); + this.htmlElement.addEventListener(ViewerEvents.SelectedTreeChange, (event) => + this.presenter.newPropertiesTree((event as CustomEvent).detail.selectedItem) + ); + this.htmlElement.addEventListener(ViewerEvents.AdditionalPropertySelected, (event) => + this.presenter.newAdditionalPropertiesTree((event as CustomEvent).detail.selectedItem) + ); } protected abstract initialisePresenter(storage: Storage): PresenterInputMethod; diff --git a/tools/winscope-ng/src/viewers/components/coordinates_table.component.spec.ts b/tools/winscope-ng/src/viewers/components/coordinates_table.component.spec.ts index 10f9c61c3..3789d0874 100644 --- a/tools/winscope-ng/src/viewers/components/coordinates_table.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/coordinates_table.component.spec.ts @@ -13,20 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { CoordinatesTableComponent } from "./coordinates_table.component"; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {CoordinatesTableComponent} from './coordinates_table.component'; -describe("CoordinatesTableComponent", () => { +describe('CoordinatesTableComponent', () => { let fixture: ComponentFixture; let component: CoordinatesTableComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - declarations: [ - CoordinatesTableComponent - ], - schemas: [] + declarations: [CoordinatesTableComponent], + schemas: [], }).compileComponents(); }); @@ -36,7 +34,7 @@ describe("CoordinatesTableComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/coordinates_table.component.ts b/tools/winscope-ng/src/viewers/components/coordinates_table.component.ts index 3092969d1..004c11271 100644 --- a/tools/winscope-ng/src/viewers/components/coordinates_table.component.ts +++ b/tools/winscope-ng/src/viewers/components/coordinates_table.component.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; +import {Component, Input} from '@angular/core'; @Component({ - selector: "coordinates-table", + selector: 'coordinates-table', template: `

null

@@ -67,15 +67,18 @@ import { Component, Input } from "@angular/core"; .header-row td { color: gray; } - ` + `, ], }) - export class CoordinatesTableComponent { @Input() coordinates!: any; hasCoordinates() { - return this.coordinates.left || this.coordinates.top || - this.coordinates.right || this.coordinates.bottom; + return ( + this.coordinates.left || + this.coordinates.top || + this.coordinates.right || + this.coordinates.bottom + ); } } diff --git a/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts b/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts index 964cbf81e..17905eece 100644 --- a/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts @@ -13,36 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed, ComponentFixtureAutoDetect} from "@angular/core/testing"; -import { HierarchyComponent } from "./hierarchy.component"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; -import { PersistentStore } from "common/utils/persistent_store"; -import { CommonModule } from "@angular/common"; -import { MatInputModule } from "@angular/material/input"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatCheckboxModule } from "@angular/material/checkbox"; -import { MatDividerModule } from "@angular/material/divider"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; -import { TreeComponent } from "viewers/components/tree.component"; -import { TreeNodeComponent } from "viewers/components/tree_node.component"; -import { TreeNodeDataViewComponent } from "viewers/components/tree_node_data_view.component"; +import {CommonModule} from '@angular/common'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatInputModule} from '@angular/material/input'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {TreeComponent} from 'viewers/components/tree.component'; +import {TreeNodeComponent} from 'viewers/components/tree_node.component'; +import {TreeNodeDataViewComponent} from 'viewers/components/tree_node_data_view.component'; +import {HierarchyComponent} from './hierarchy.component'; -describe("HierarchyComponent", () => { +describe('HierarchyComponent', () => { let fixture: ComponentFixture; let component: HierarchyComponent; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], declarations: [ HierarchyComponent, TreeComponent, TreeNodeComponent, - TreeNodeDataViewComponent + TreeNodeDataViewComponent, ], imports: [ CommonModule, @@ -50,24 +48,25 @@ describe("HierarchyComponent", () => { MatDividerModule, MatInputModule, MatFormFieldModule, - BrowserAnimationsModule + BrowserAnimationsModule, ], - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(HierarchyComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; - component.tree = new HierarchyTreeBuilder().setName("Root node").setChildren([ - new HierarchyTreeBuilder().setName("Child node").build() - ]).build(); + component.tree = new HierarchyTreeBuilder() + .setName('Root node') + .setChildren([new HierarchyTreeBuilder().setName('Child node').build()]) + .build(); component.store = new PersistentStore(); component.userOptions = { onlyVisible: { - name: "Only visible", - enabled: false + name: 'Only visible', + enabled: false, }, }; component.pinnedItems = [component.tree]; @@ -75,24 +74,24 @@ describe("HierarchyComponent", () => { fixture.detectChanges(); }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("renders title", () => { - const title = htmlElement.querySelector(".hierarchy-title"); + it('renders title', () => { + const title = htmlElement.querySelector('.hierarchy-title'); expect(title).toBeTruthy(); }); - it("renders view controls", () => { - const viewControls = htmlElement.querySelector(".view-controls"); + it('renders view controls', () => { + const viewControls = htmlElement.querySelector('.view-controls'); expect(viewControls).toBeTruthy(); }); - it("renders initial tree elements", async () => { - const treeView = htmlElement.querySelector("tree-view"); + it('renders initial tree elements', async () => { + const treeView = htmlElement.querySelector('tree-view'); expect(treeView).toBeTruthy(); - expect(treeView!.innerHTML).toContain("Root node"); - expect(treeView!.innerHTML).toContain("Child node"); + expect(treeView!.innerHTML).toContain('Root node'); + expect(treeView!.innerHTML).toContain('Child node'); }); }); diff --git a/tools/winscope-ng/src/viewers/components/hierarchy.component.ts b/tools/winscope-ng/src/viewers/components/hierarchy.component.ts index 8ac7b2011..9633fbbfc 100644 --- a/tools/winscope-ng/src/viewers/components/hierarchy.component.ts +++ b/tools/winscope-ng/src/viewers/components/hierarchy.component.ts @@ -13,29 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input, Inject, ElementRef } from "@angular/core"; -import { UserOptions } from "viewers/common/user_options"; -import { PersistentStore } from "common/utils/persistent_store"; -import { UiTreeUtils, HierarchyTreeNode, UiTreeNode } from "viewers/common/ui_tree_utils"; -import { nodeStyles } from "viewers/components/styles/node.styles"; -import { ViewerEvents } from "viewers/common/viewer_events"; -import { TraceType } from "common/trace/trace_type"; -import { TableProperties } from "viewers/common/table_properties"; +import {Component, ElementRef, Inject, Input} from '@angular/core'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {TableProperties} from 'viewers/common/table_properties'; +import {HierarchyTreeNode, UiTreeNode, UiTreeUtils} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {ViewerEvents} from 'viewers/common/viewer_events'; +import {nodeStyles} from 'viewers/components/styles/node.styles'; @Component({ - selector: "hierarchy-view", + selector: 'hierarchy-view', template: `

Hierarchy

Filter... - +
@@ -44,13 +39,13 @@ import { TableProperties } from "viewers/common/table_properties"; color="primary" [(ngModel)]="userOptions[option].enabled" (ngModelChange)="updateTree()" - >{{userOptions[option].name}} + >{{ userOptions[option].name }}
+ [properties]="tableProperties">
+ (click)="onPinnedNodeClick($event, pinnedItem)">
@@ -80,8 +74,7 @@ import { TableProperties } from "viewers/common/table_properties"; [pinnedItems]="pinnedItems" (highlightedItemChange)="highlightedItemChange($event)" (pinnedItemChange)="pinnedItemChange($event)" - (selectedTreeChange)="selectedTreeChange($event)" - > + (selectedTreeChange)="selectedTreeChange($event)"> `, styles: [ @@ -125,13 +118,12 @@ import { TableProperties } from "viewers/common/table_properties"; overflow: auto; } `, - nodeStyles + nodeStyles, ], }) - export class HierarchyComponent { objectKeys = Object.keys; - filterString = ""; + filterString = ''; diffClass = UiTreeUtils.diffClass; isHighlighted = UiTreeUtils.isHighlighted; @@ -143,17 +135,15 @@ export class HierarchyComponent { @Input() store!: PersistentStore; @Input() userOptions: UserOptions = {}; - constructor( - @Inject(ElementRef) private elementRef: ElementRef, - ) {} + constructor(@Inject(ElementRef) private elementRef: ElementRef) {} public isFlattened() { - return this.userOptions["flat"]?.enabled; + return this.userOptions['flat']?.enabled; } public onPinnedNodeClick(event: MouseEvent, pinnedItem: HierarchyTreeNode) { event.preventDefault(); - if (window.getSelection()?.type === "range") { + if (window.getSelection()?.type === 'range') { return; } if (pinnedItem.id) this.highlightedItemChange(`${pinnedItem.id}`); @@ -161,32 +151,26 @@ export class HierarchyComponent { } public updateTree() { - const event: CustomEvent = new CustomEvent( - ViewerEvents.HierarchyUserOptionsChange, - { - bubbles: true, - detail: { userOptions: this.userOptions } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.HierarchyUserOptionsChange, { + bubbles: true, + detail: {userOptions: this.userOptions}, + }); this.elementRef.nativeElement.dispatchEvent(event); } public filterTree() { - const event: CustomEvent = new CustomEvent( - ViewerEvents.HierarchyFilterChange, - { - bubbles: true, - detail: { filterString: this.filterString } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.HierarchyFilterChange, { + bubbles: true, + detail: {filterString: this.filterString}, + }); this.elementRef.nativeElement.dispatchEvent(event); } public highlightedItemChange(newId: string) { - const event: CustomEvent = new CustomEvent( - ViewerEvents.HighlightedChange, - { - bubbles: true, - detail: { id: newId } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, { + bubbles: true, + detail: {id: newId}, + }); this.elementRef.nativeElement.dispatchEvent(event); } @@ -194,12 +178,10 @@ export class HierarchyComponent { if (!(item instanceof HierarchyTreeNode)) { return; } - const event: CustomEvent = new CustomEvent( - ViewerEvents.SelectedTreeChange, - { - bubbles: true, - detail: { selectedItem: item } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.SelectedTreeChange, { + bubbles: true, + detail: {selectedItem: item}, + }); this.elementRef.nativeElement.dispatchEvent(event); } @@ -207,12 +189,10 @@ export class HierarchyComponent { if (!(item instanceof HierarchyTreeNode)) { return; } - const event: CustomEvent = new CustomEvent( - ViewerEvents.HierarchyPinnedChange, - { - bubbles: true, - detail: { pinnedItem: item } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.HierarchyPinnedChange, { + bubbles: true, + detail: {pinnedItem: item}, + }); this.elementRef.nativeElement.dispatchEvent(event); } } diff --git a/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.spec.ts b/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.spec.ts index 5cc2ec563..c9b21fa56 100644 --- a/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.spec.ts @@ -13,24 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { ImeAdditionalPropertiesComponent } from "./ime_additional_properties.component"; -import { MatDividerModule } from "@angular/material/divider"; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatDividerModule} from '@angular/material/divider'; +import {ImeAdditionalPropertiesComponent} from './ime_additional_properties.component'; -describe("ImeAdditionalPropertiesComponent", () => { +describe('ImeAdditionalPropertiesComponent', () => { let fixture: ComponentFixture; let component: ImeAdditionalPropertiesComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - imports: [ - MatDividerModule - ], - declarations: [ - ImeAdditionalPropertiesComponent - ], - schemas: [] + imports: [MatDividerModule], + declarations: [ImeAdditionalPropertiesComponent], + schemas: [], }).compileComponents(); }); @@ -40,7 +36,7 @@ describe("ImeAdditionalPropertiesComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.ts b/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.ts index 9f5adac67..6a60f89be 100644 --- a/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.ts +++ b/tools/winscope-ng/src/viewers/components/ime_additional_properties.component.ts @@ -13,33 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, ElementRef, Inject, Input } from "@angular/core"; -import { ImeAdditionalProperties } from "viewers/common/ime_additional_properties"; -import { UiTreeUtils } from "viewers/common/ui_tree_utils"; -import { ViewerEvents } from "viewers/common/viewer_events"; +import {Component, ElementRef, Inject, Input} from '@angular/core'; +import {ImeAdditionalProperties} from 'viewers/common/ime_additional_properties'; +import {UiTreeUtils} from 'viewers/common/ui_tree_utils'; +import {ViewerEvents} from 'viewers/common/viewer_events'; @Component({ - selector: "ime-additional-properties", + selector: 'ime-additional-properties', template: `

WM & SF Properties

- There is no corresponding WM / SF additionalProperties for this IME entry – - no WM / SF entry is recorded before this IME entry in time. - View later frames for WM & SF properties. + There is no corresponding WM / SF additionalProperties for this IME entry – no WM / SF + entry is recorded before this IME entry in time. View later frames for WM & SF properties.

WMState

@@ -54,23 +53,30 @@ import { ViewerEvents } from "viewers/common/viewer_events";

Source Frame:

- +

Source Visible: &ngsp; {{ wmInsetsSourceProviderSourceVisibleOrNull() }}

Source Visible Frame:

- +

Position: &ngsp; @@ -90,11 +96,13 @@ import { ViewerEvents } from "viewers/common/viewer_events";

@@ -107,11 +115,11 @@ import { ViewerEvents } from "viewers/common/viewer_events";
@@ -124,11 +132,13 @@ import { ViewerEvents } from "viewers/common/viewer_events";
@@ -145,19 +155,19 @@ import { ViewerEvents } from "viewers/common/viewer_events";

WMState

-

{{ - additionalProperties.wm.name - }}

+

+ {{ additionalProperties.wm.name }} +

There is no corresponding WMState entry.

@@ -166,9 +176,9 @@ import { ViewerEvents } from "viewers/common/viewer_events";

SFLayer

-

{{ - additionalProperties.sf.name - }}

+

+ {{ additionalProperties.sf.name }} +

There is no corresponding SFLayer entry.

@@ -212,17 +222,17 @@ import { ViewerEvents } from "viewers/common/viewer_events";

InputMethod Surface: &ngsp; - {{ additionalProperties.sf.inputMethodSurface?.isInputMethodSurfaceVisible ?? false}} + {{ additionalProperties.sf.inputMethodSurface?.isInputMethodSurfaceVisible ?? false }}

@@ -240,16 +250,17 @@ import { ViewerEvents } from "viewers/common/viewer_events";

ScreenBounds:

- +

Rect:

@@ -304,18 +315,15 @@ import { ViewerEvents } from "viewers/common/viewer_events"; flex: 1; padding: 0 5px; } - ` + `, ], }) - export class ImeAdditionalPropertiesComponent { @Input() additionalProperties!: ImeAdditionalProperties; @Input() isImeManagerService?: boolean; @Input() highlightedItems: Array = []; - constructor( - @Inject(ElementRef) private elementRef: ElementRef, - ) {} + constructor(@Inject(ElementRef) private elementRef: ElementRef) {} public isHighlighted(item: any) { return UiTreeUtils.isHighlighted(item, this.highlightedItems); @@ -332,96 +340,120 @@ export class ImeAdditionalPropertiesComponent { } public wmInsetsSourceProviderOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider ? - Object.assign({ "name": "Ime Insets Source Provider" }, - this.additionalProperties.wm.protoImeInsetsSourceProvider) : - null; + return this.additionalProperties.wm?.protoImeInsetsSourceProvider + ? Object.assign( + {name: 'Ime Insets Source Provider'}, + this.additionalProperties.wm.protoImeInsetsSourceProvider + ) + : null; } public wmControlTargetFrameOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.controlTarget?.windowFrames?.frame || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider + ?.controlTarget?.windowFrames?.frame || 'null' + ); } public wmInsetsSourceProviderPositionOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.control?.position || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.control + ?.position || 'null' + ); } public wmInsetsSourceProviderIsLeashReadyOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.isLeashReadyForDispatching || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider + ?.isLeashReadyForDispatching || 'null' + ); } public wmInsetsSourceProviderControllableOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.controllable || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider + ?.controllable || 'null' + ); } public wmInsetsSourceProviderSourceFrameOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.source?.frame || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source + ?.frame || 'null' + ); } public wmInsetsSourceProviderSourceVisibleOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.source?.visible || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source + ?.visible || 'null' + ); } public wmInsetsSourceProviderSourceVisibleFrameOrNull() { - return this.additionalProperties.wm?.protoImeInsetsSourceProvider - ?.insetsSourceProvider?.source?.visibleFrame || "null"; + return ( + this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source + ?.visibleFrame || 'null' + ); } public wmImeControlTargetOrNull() { - return this.additionalProperties?.wm?.protoImeControlTarget ? - Object.assign({ "name": "IME Control Target" }, - this.additionalProperties.wm.protoImeControlTarget) : - null; + return this.additionalProperties?.wm?.protoImeControlTarget + ? Object.assign( + {name: 'IME Control Target'}, + this.additionalProperties.wm.protoImeControlTarget + ) + : null; } public wmImeControlTargetTitleOrNull() { - return this.additionalProperties?.wm?.protoImeControlTarget?.windowContainer - ?.identifier?.title || "null"; + return ( + this.additionalProperties?.wm?.protoImeControlTarget?.windowContainer?.identifier?.title || + 'null' + ); } public wmImeInputTargetOrNull() { - return this.additionalProperties?.wm?.protoImeInputTarget ? - Object.assign({ "name": "IME Input Target" }, - this.additionalProperties.wm.protoImeInputTarget) : - null; + return this.additionalProperties?.wm?.protoImeInputTarget + ? Object.assign({name: 'IME Input Target'}, this.additionalProperties.wm.protoImeInputTarget) + : null; } public wmImeInputTargetTitleOrNull() { - return this.additionalProperties?.wm?.protoImeInputTarget?.windowContainer - ?.identifier?.title || "null"; + return ( + this.additionalProperties?.wm?.protoImeInputTarget?.windowContainer?.identifier?.title || + 'null' + ); } public wmImeLayeringTargetOrNull() { - return this.additionalProperties?.wm?.protoImeLayeringTarget ? - Object.assign({ "name": "IME Layering Target" }, - this.additionalProperties.wm.protoImeLayeringTarget) : - null; + return this.additionalProperties?.wm?.protoImeLayeringTarget + ? Object.assign( + {name: 'IME Layering Target'}, + this.additionalProperties.wm.protoImeLayeringTarget + ) + : null; } public wmImeLayeringTargetTitleOrNull() { - return this.additionalProperties?.wm?.protoImeLayeringTarget?.windowContainer - ?.identifier?.title || "null"; + return ( + this.additionalProperties?.wm?.protoImeLayeringTarget?.windowContainer?.identifier?.title || + 'null' + ); } public sfImeContainerScreenBoundsOrNull() { - return this.additionalProperties.sf?.inputMethodSurface?.screenBounds || "null"; + return this.additionalProperties.sf?.inputMethodSurface?.screenBounds || 'null'; } public sfImeContainerRectOrNull() { - return this.additionalProperties.sf?.inputMethodSurface?.rect || "null"; + return this.additionalProperties.sf?.inputMethodSurface?.rect || 'null'; } public isAllPropertiesNull() { if (this.isImeManagerService) { return !this.additionalProperties.wm; } else { - return !(this.additionalProperties.wm || - this.additionalProperties.sf); + return !(this.additionalProperties.wm || this.additionalProperties.sf); } } @@ -434,12 +466,10 @@ export class ImeAdditionalPropertiesComponent { } private updateHighlightedItems(newId: string) { - const event: CustomEvent = new CustomEvent( - ViewerEvents.HighlightedChange, - { - bubbles: true, - detail: { id: newId } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, { + bubbles: true, + detail: {id: newId}, + }); this.elementRef.nativeElement.dispatchEvent(event); } @@ -448,12 +478,10 @@ export class ImeAdditionalPropertiesComponent { name: name, proto: item, }; - const event: CustomEvent = new CustomEvent( - ViewerEvents.AdditionalPropertySelected, - { - bubbles: true, - detail: { selectedItem: itemWrapper } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.AdditionalPropertySelected, { + bubbles: true, + detail: {selectedItem: itemWrapper}, + }); this.elementRef.nativeElement.dispatchEvent(event); } } diff --git a/tools/winscope-ng/src/viewers/components/properties.component.spec.ts b/tools/winscope-ng/src/viewers/components/properties.component.spec.ts index 197205562..1e34f1ab9 100644 --- a/tools/winscope-ng/src/viewers/components/properties.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/properties.component.spec.ts @@ -13,42 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed, ComponentFixtureAutoDetect} from "@angular/core/testing"; -import { PropertiesComponent } from "./properties.component"; -import { CommonModule } from "@angular/common"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; -import { MatInputModule } from "@angular/material/input"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatCheckboxModule } from "@angular/material/checkbox"; -import { MatDividerModule } from "@angular/material/divider"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { PropertyGroupsComponent } from "./property_groups.component"; -import { TreeComponent } from "./tree.component"; +import {CommonModule} from '@angular/common'; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatInputModule} from '@angular/material/input'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {PropertiesComponent} from './properties.component'; +import {PropertyGroupsComponent} from './property_groups.component'; +import {TreeComponent} from './tree.component'; -describe("PropertiesComponent", () => { +describe('PropertiesComponent', () => { let fixture: ComponentFixture; let component: PropertiesComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - declarations: [ - PropertiesComponent, - PropertyGroupsComponent, - TreeComponent - ], + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + declarations: [PropertiesComponent, PropertyGroupsComponent, TreeComponent], imports: [ CommonModule, MatInputModule, MatFormFieldModule, MatCheckboxModule, MatDividerModule, - BrowserAnimationsModule + BrowserAnimationsModule, ], - schemas: [NO_ERRORS_SCHEMA] + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -60,32 +54,32 @@ describe("PropertiesComponent", () => { component.selectedFlickerItem = null; component.userOptions = { showDefaults: { - name: "Show defaults", - enabled: false + name: 'Show defaults', + enabled: false, }, }; }); - it("can be created", () => { + it('can be created', () => { fixture.detectChanges(); expect(component).toBeTruthy(); }); - it("creates title", () => { + it('creates title', () => { fixture.detectChanges(); - const title = htmlElement.querySelector(".properties-title"); + const title = htmlElement.querySelector('.properties-title'); expect(title).toBeTruthy(); }); - it("creates view controls", () => { + it('creates view controls', () => { fixture.detectChanges(); - const viewControls = htmlElement.querySelector(".view-controls"); + const viewControls = htmlElement.querySelector('.view-controls'); expect(viewControls).toBeTruthy(); }); - it("creates initial tree elements", () => { + it('creates initial tree elements', () => { fixture.detectChanges(); - const tree = htmlElement.querySelector(".tree-wrapper"); + const tree = htmlElement.querySelector('.tree-wrapper'); expect(tree).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/properties.component.ts b/tools/winscope-ng/src/viewers/components/properties.component.ts index ced3b6271..b57b2d169 100644 --- a/tools/winscope-ng/src/viewers/components/properties.component.ts +++ b/tools/winscope-ng/src/viewers/components/properties.component.ts @@ -13,29 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input, Inject, ElementRef } from "@angular/core"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { UserOptions } from "viewers/common/user_options"; -import { ViewerEvents } from "viewers/common/viewer_events"; -import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils"; +import {Component, ElementRef, Inject, Input} from '@angular/core'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {PropertiesTreeNode, Terminal} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {ViewerEvents} from 'viewers/common/viewer_events'; @Component({ - selector: "properties-view", + selector: 'properties-view', template: ` -
+

Properties

Filter... - +
@@ -46,21 +40,24 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils"; [(ngModel)]="userOptions[option].enabled" (ngModelChange)="updateTree()" [matTooltip]="userOptions[option].tooltip ?? ''" - >{{userOptions[option].name}} + >{{ userOptions[option].name }}
+ [item]="selectedFlickerItem">
-

Properties - Proto Dump

+

+ Properties - Proto Dump +

+ [isAlwaysCollapsed]="true">
`, @@ -114,15 +110,14 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils"; } .tree-wrapper { - overflow: auto + overflow: auto; } `, ], }) - export class PropertiesComponent { objectKeys = Object.keys; - filterString = ""; + filterString = ''; @Input() userOptions: UserOptions = {}; @Input() propertiesTree: PropertiesTreeNode = {}; @@ -130,39 +125,38 @@ export class PropertiesComponent { @Input() displayPropertyGroups = false; @Input() isProtoDump = false; - constructor( - @Inject(ElementRef) private elementRef: ElementRef, - ) {} + constructor(@Inject(ElementRef) private elementRef: ElementRef) {} public filterTree() { - const event: CustomEvent = new CustomEvent( - ViewerEvents.PropertiesFilterChange, - { - bubbles: true, - detail: { filterString: this.filterString } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.PropertiesFilterChange, { + bubbles: true, + detail: {filterString: this.filterString}, + }); this.elementRef.nativeElement.dispatchEvent(event); } public updateTree() { - const event: CustomEvent = new CustomEvent( - ViewerEvents.PropertiesUserOptionsChange, - { - bubbles: true, - detail: { userOptions: this.userOptions } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.PropertiesUserOptionsChange, { + bubbles: true, + detail: {userOptions: this.userOptions}, + }); this.elementRef.nativeElement.dispatchEvent(event); } public showNode(item: any) { - return !(item instanceof Terminal) - && !(item.name instanceof Terminal) - && !(item.propertyKey instanceof Terminal); + return ( + !(item instanceof Terminal) && + !(item.name instanceof Terminal) && + !(item.propertyKey instanceof Terminal) + ); } public isLeaf(item: any) { - return !item.children || item.children.length === 0 - || item.children.filter((c: any) => !(c instanceof Terminal)).length === 0; + return ( + !item.children || + item.children.length === 0 || + item.children.filter((c: any) => !(c instanceof Terminal)).length === 0 + ); } public itemIsSelected() { diff --git a/tools/winscope-ng/src/viewers/components/properties_table.component.spec.ts b/tools/winscope-ng/src/viewers/components/properties_table.component.spec.ts index 21dbb10ba..f1d6f1ac6 100644 --- a/tools/winscope-ng/src/viewers/components/properties_table.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/properties_table.component.spec.ts @@ -13,20 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { PropertiesTableComponent } from "./properties_table.component"; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {PropertiesTableComponent} from './properties_table.component'; -describe("PropertiesTableComponent", () => { +describe('PropertiesTableComponent', () => { let fixture: ComponentFixture; let component: PropertiesTableComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - declarations: [ - PropertiesTableComponent - ], - schemas: [] + declarations: [PropertiesTableComponent], + schemas: [], }).compileComponents(); }); @@ -36,7 +34,7 @@ describe("PropertiesTableComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/properties_table.component.ts b/tools/winscope-ng/src/viewers/components/properties_table.component.ts index f70513c3d..9235abf47 100644 --- a/tools/winscope-ng/src/viewers/components/properties_table.component.ts +++ b/tools/winscope-ng/src/viewers/components/properties_table.component.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; -import { TableProperties } from "viewers/common/table_properties"; +import {Component, Input} from '@angular/core'; +import {TableProperties} from 'viewers/common/table_properties'; @Component({ - selector: "properties-table", + selector: 'properties-table', template: `
@@ -37,7 +37,8 @@ import { TableProperties } from "viewers/common/table_properties"; border-collapse: collapse; } - .table-cell-name, .table-cell-value { + .table-cell-name, + .table-cell-value { padding: 1px 5px; border: 1px solid var(--border-color); overflow-wrap: anywhere; @@ -47,13 +48,11 @@ import { TableProperties } from "viewers/common/table_properties"; width: 20%; background-color: rgba(158, 192, 200, 0.281); } - ` + `, ], }) - export class PropertiesTableComponent { objectEntries = Object.entries; @Input() properties!: TableProperties; - } diff --git a/tools/winscope-ng/src/viewers/components/property_groups.component.spec.ts b/tools/winscope-ng/src/viewers/components/property_groups.component.spec.ts index ed7aedc40..3a47adf4b 100644 --- a/tools/winscope-ng/src/viewers/components/property_groups.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/property_groups.component.spec.ts @@ -13,56 +13,50 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatTooltipModule } from "@angular/material/tooltip"; -import { PropertyGroupsComponent } from "./property_groups.component"; -import { LayerBuilder } from "test/unit/layer_builder"; -import { TransformMatrixComponent } from "./transform_matrix.component"; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatTooltipModule} from '@angular/material/tooltip'; +import {LayerBuilder} from 'test/unit/layer_builder'; +import {PropertyGroupsComponent} from './property_groups.component'; +import {TransformMatrixComponent} from './transform_matrix.component'; -describe("PropertyGroupsComponent", () => { +describe('PropertyGroupsComponent', () => { let fixture: ComponentFixture; let component: PropertyGroupsComponent; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ - MatDividerModule, - MatTooltipModule - ], - declarations: [ - PropertyGroupsComponent, - TransformMatrixComponent - ], - schemas: [] + imports: [MatDividerModule, MatTooltipModule], + declarations: [PropertyGroupsComponent, TransformMatrixComponent], + schemas: [], }).compileComponents(); fixture = TestBed.createComponent(PropertyGroupsComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("it renders verbose flags if available", async () => { + it('it renders verbose flags if available', async () => { const layer = new LayerBuilder().setFlags(3).build(); component.item = layer; fixture.detectChanges(); - const flags = htmlElement.querySelector(".flags"); + const flags = htmlElement.querySelector('.flags'); expect(flags).toBeTruthy(); - expect(flags!.innerHTML).toMatch("Flags:.*HIDDEN|OPAQUE \\(0x3\\)"); + expect(flags!.innerHTML).toMatch('Flags:.*HIDDEN|OPAQUE \\(0x3\\)'); }); - it("it renders numeric flags if verbose flags not available", async () => { + it('it renders numeric flags if verbose flags not available', async () => { const layer = new LayerBuilder().setFlags(0).build(); component.item = layer; fixture.detectChanges(); - const flags = htmlElement.querySelector(".flags"); + const flags = htmlElement.querySelector('.flags'); expect(flags).toBeTruthy(); - expect(flags!.innerHTML).toMatch("Flags:.*0"); + expect(flags!.innerHTML).toMatch('Flags:.*0'); }); }); diff --git a/tools/winscope-ng/src/viewers/components/property_groups.component.ts b/tools/winscope-ng/src/viewers/components/property_groups.component.ts index c794d6608..b81235479 100644 --- a/tools/winscope-ng/src/viewers/components/property_groups.component.ts +++ b/tools/winscope-ng/src/viewers/components/property_groups.component.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; -import { Layer } from "common/trace/flickerlib/common"; +import {Component, Input} from '@angular/core'; +import {Layer} from 'common/trace/flickerlib/common'; @Component({ - selector: "property-groups", + selector: 'property-groups', template: `

Visibility

@@ -40,21 +40,27 @@ import { Layer } from "common/trace/flickerlib/common";

Calculated

Transform:

- +

Crop: + >Crop: &ngsp; {{ item.bounds }} +

+

Final Bounds: + >Final Bounds: &ngsp; {{ item.screenBounds }}

@@ -62,14 +68,13 @@ import { Layer } from "common/trace/flickerlib/common";

Requested

Transform:

- +

Crop: &ngsp; - {{ item.crop - ? item.crop - : "[empty]" - }} + {{ item.crop ? item.crop : '[empty]' }}

@@ -93,7 +98,8 @@ import { Layer } from "common/trace/flickerlib/common"; matTooltip="Rotates or flips the buffer in place. Used with display transform hint to cancel out any buffer transformation when sending to HWC." - >Transform: + >Transform: &ngsp; {{ item.bufferTransform }}

@@ -104,13 +110,13 @@ import { Layer } from "common/trace/flickerlib/common"; class="mat-body-2" matTooltip="Scales buffer to the frame by overriding the requested transform for this item." - >Destination Frame: + >Destination Frame: &ngsp; {{ getDestinationFrame() }}

- Destination Frame ignored because item has eIgnoreDestinationFrame - flag set. + Destination Frame ignored because item has eIgnoreDestinationFrame flag set.

@@ -128,13 +134,10 @@ import { Layer } from "common/trace/flickerlib/common"; class="mat-body-2" matTooltip="item is z-ordered relative to its relative parents but its bounds and other properties are inherited from its parents." - >relative parent: + >relative parent: &ngsp; - {{ - item.zOrderRelativeOfId == -1 - ? "none" - : item.zOrderRelativeOfId - }} + {{ item.zOrderRelativeOfId == -1 ? 'none' : item.zOrderRelativeOfId }}

@@ -164,18 +167,15 @@ import { Layer } from "common/trace/flickerlib/common"; matTooltip="Crop used to define the bounds of the corner radii. If the bounds are greater than the item bounds then the rounded corner will not be visible." - >Corner Radius Crop: + >Corner Radius Crop: &ngsp; {{ item.cornerRadiusCrop }}

Blur: &ngsp; - {{ - item.proto?.backgroundBlurRadius - ? item.proto?.backgroundBlurRadius - : 0 - }} px + {{ item.proto?.backgroundBlurRadius ? item.proto?.backgroundBlurRadius : 0 }} px

@@ -188,20 +188,15 @@ import { Layer } from "common/trace/flickerlib/common";

Shadow: &ngsp; - {{ - item.proto?.requestedShadowRadius - ? item.proto?.requestedShadowRadius - : 0 - }} px + {{ item.proto?.requestedShadowRadius ? item.proto?.requestedShadowRadius : 0 }} px

Corner Radius: &ngsp; {{ - item.proto?.requestedCornerRadius - ? formatFloat(item.proto?.requestedCornerRadius) - : 0 - }} px + item.proto?.requestedCornerRadius ? formatFloat(item.proto?.requestedCornerRadius) : 0 + }} + px

@@ -211,7 +206,9 @@ import { Layer } from "common/trace/flickerlib/common";

To Display Transform:

- +

Touchable Region: &ngsp; @@ -244,8 +241,7 @@ import { Layer } from "common/trace/flickerlib/common";

Input channel: - &ngsp; - not set + &ngsp; not set

@@ -278,10 +274,9 @@ import { Layer } from "common/trace/flickerlib/common"; .column-header { color: gray; } - ` + `, ], }) - export class PropertyGroupsComponent { @Input() item!: Layer; @@ -293,8 +288,7 @@ export class PropertyGroupsComponent { const frame = this.item.proto?.destinationFrame; if (frame) { return ` left: ${frame.left}, top: ${frame.top}, right: ${frame.right}, bottom: ${frame.bottom}`; - } - else return ""; + } else return ''; } public hasIgnoreDestinationFrame() { @@ -305,40 +299,43 @@ export class PropertyGroupsComponent { return Math.round(num * 100) / 100; } - public summary(): TreeSummary { const summary = []; if (this.item?.visibilityReason?.length > 0) { - let reason = ""; + let reason = ''; if (Array.isArray(this.item.visibilityReason)) { - reason = this.item.visibilityReason.join(", "); + reason = this.item.visibilityReason.join(', '); } else { reason = this.item.visibilityReason; } - summary.push({key: "Invisible due to", value: reason}); + summary.push({key: 'Invisible due to', value: reason}); } if (this.item?.occludedBy?.length > 0) { - summary.push({key: "Occluded by", value: this.item.occludedBy.map((it: any) => it.id).join(", ")}); + summary.push({ + key: 'Occluded by', + value: this.item.occludedBy.map((it: any) => it.id).join(', '), + }); } if (this.item?.partiallyOccludedBy?.length > 0) { summary.push({ - key: "Partially occluded by", - value: this.item.partiallyOccludedBy.map((it: any) => it.id).join(", "), + key: 'Partially occluded by', + value: this.item.partiallyOccludedBy.map((it: any) => it.id).join(', '), }); } if (this.item?.coveredBy?.length > 0) { - summary.push({key: "Covered by", value: this.item.coveredBy.map((it: any) => it.id).join(", ")}); + summary.push({ + key: 'Covered by', + value: this.item.coveredBy.map((it: any) => it.id).join(', '), + }); } return summary; } - } - -type TreeSummary = Array<{key: string, value: string}> \ No newline at end of file +type TreeSummary = Array<{key: string; value: string}>; diff --git a/tools/winscope-ng/src/viewers/components/rects/canvas.ts b/tools/winscope-ng/src/viewers/components/rects/canvas.ts index 9884aaa2a..91c5e54b2 100644 --- a/tools/winscope-ng/src/viewers/components/rects/canvas.ts +++ b/tools/winscope-ng/src/viewers/components/rects/canvas.ts @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Rectangle} from "viewers/common/rectangle"; -import * as THREE from "three"; -import {CSS2DObject, CSS2DRenderer} from "three/examples/jsm/renderers/CSS2DRenderer"; -import {ViewerEvents} from "viewers/common/viewer_events"; -import {Circle3D, ColorType, Label3D, Point3D, Rect3D, Scene3D, Transform3D} from "./types3d"; +import * as THREE from 'three'; +import {CSS2DObject, CSS2DRenderer} from 'three/examples/jsm/renderers/CSS2DRenderer'; +import {Rectangle} from 'viewers/common/rectangle'; +import {ViewerEvents} from 'viewers/common/viewer_events'; +import {Circle3D, ColorType, Label3D, Point3D, Rect3D, Scene3D, Transform3D} from './types3d'; export class Canvas { private static readonly TARGET_SCENE_DIAGONAL = 4; - private static readonly RECT_COLOR_HIGHLIGHTED = new THREE.Color(0xD2E3FC); + private static readonly RECT_COLOR_HIGHLIGHTED = new THREE.Color(0xd2e3fc); private static readonly RECT_EDGE_COLOR = 0x000000; private static readonly RECT_EDGE_COLOR_ROUNDED = 0x848884; private static readonly LABEL_CIRCLE_COLOR = 0x000000; @@ -47,8 +47,8 @@ export class Canvas { draw(scene: Scene3D) { // Must set 100% width and height so the HTML element expands to the parent's // boundaries and the correct clientWidth and clientHeight values can be read - this.canvasRects.style.width = "100%"; - this.canvasRects.style.height = "100%"; + this.canvasRects.style.width = '100%'; + this.canvasRects.style.height = '100%'; let widthAspectRatioAdjustFactor: number; let heightAspectRatioAdjustFactor: number; @@ -67,19 +67,23 @@ export class Canvas { const panFactorY = scene.camera.panScreenDistance.dy / this.canvasRects.clientHeight; this.scene = new THREE.Scene(); - const scaleFactor = Canvas.TARGET_SCENE_DIAGONAL / scene.boundingBox.diagonal * scene.camera.zoomFactor; + const scaleFactor = + (Canvas.TARGET_SCENE_DIAGONAL / scene.boundingBox.diagonal) * scene.camera.zoomFactor; this.scene.scale.set(scaleFactor, -scaleFactor, scaleFactor); this.scene.translateX(scaleFactor * -scene.boundingBox.center.x + cameraWidth * panFactorX); this.scene.translateY(scaleFactor * scene.boundingBox.center.y - cameraHeight * panFactorY); this.scene.translateZ(scaleFactor * -scene.boundingBox.center.z); this.camera = new THREE.OrthographicCamera( - - cameraWidth / 2, cameraWidth / 2, - cameraHeight / 2, - cameraHeight / 2, - 0, 100, + -cameraWidth / 2, + cameraWidth / 2, + cameraHeight / 2, + -cameraHeight / 2, + 0, + 100 ); - const rotationAngleX = scene.camera.rotationFactor * Math.PI * 45 / 360; + const rotationAngleX = (scene.camera.rotationFactor * Math.PI * 45) / 360; const rotationAngleY = rotationAngleX * 1.5; const cameraPosition = new THREE.Vector3(0, 0, Canvas.TARGET_SCENE_DIAGONAL); cameraPosition.applyAxisAngle(new THREE.Vector3(1, 0, 0), -rotationAngleX); @@ -91,7 +95,7 @@ export class Canvas { this.renderer = new THREE.WebGLRenderer({ antialias: true, canvas: this.canvasRects, - alpha: true + alpha: true, }); this.labelRenderer = new CSS2DRenderer({element: this.canvasLabels}); @@ -110,7 +114,7 @@ export class Canvas { this.labelRenderer.render(this.scene, this.camera); } - public getClickedRectId(x: number, y: number, z: number): undefined|string { + public getClickedRectId(x: number, y: number, z: number): undefined | string { const clickPosition = new THREE.Vector3(x, y, z); const raycaster = new THREE.Raycaster(); raycaster.setFromCamera(clickPosition, this.camera!); @@ -123,7 +127,7 @@ export class Canvas { private drawRects(rects: Rect3D[]) { this.clickableObjects = []; - rects.forEach(rect => { + rects.forEach((rect) => { const rectMesh = this.makeRectMesh(rect); const transform = this.toMatrix4(rect.transform); rectMesh.applyMatrix4(transform); @@ -147,7 +151,7 @@ export class Canvas { }); const lineGeometry = new THREE.BufferGeometry().setFromPoints(linePoints); const lineMaterial = new THREE.LineBasicMaterial({ - color: label.isHighlighted ? Canvas.LABEL_LINE_COLOR_HIGHLIGHTED : Canvas.LABEL_LINE_COLOR + color: label.isHighlighted ? Canvas.LABEL_LINE_COLOR_HIGHLIGHTED : Canvas.LABEL_LINE_COLOR, }); const line = new THREE.Line(lineGeometry, lineMaterial); this.scene?.add(line); @@ -158,31 +162,31 @@ export class Canvas { private drawLabelTextHtml(label: Label3D) { // Add rectangle label - const spanText: HTMLElement = document.createElement("span"); + const spanText: HTMLElement = document.createElement('span'); spanText.innerText = label.text; - spanText.className = "mat-body-1"; + spanText.className = 'mat-body-1'; // Hack: transparent/placeholder text used to push the visible text towards left // (towards negative x) and properly align it with the label's vertical segment - const spanPlaceholder: HTMLElement = document.createElement("span"); + const spanPlaceholder: HTMLElement = document.createElement('span'); spanPlaceholder.innerText = label.text; - spanPlaceholder.className = "mat-body-1"; - spanPlaceholder.style.opacity = "0"; + spanPlaceholder.className = 'mat-body-1'; + spanPlaceholder.style.opacity = '0'; - const div: HTMLElement = document.createElement("div"); - div.className = "rect-label"; - div.style.display = "inline"; + const div: HTMLElement = document.createElement('div'); + div.className = 'rect-label'; + div.style.display = 'inline'; div.appendChild(spanText); div.appendChild(spanPlaceholder); - div.style.marginTop = "5px"; + div.style.marginTop = '5px'; if (label.isHighlighted) { - div.style.color = "gray"; + div.style.color = 'gray'; } - div.style.pointerEvents = "auto"; - div.style.cursor = "pointer"; - div.addEventListener( - "click", (event) => this.propagateUpdateHighlightedItems(event, label.rectId) + div.style.pointerEvents = 'auto'; + div.style.cursor = 'pointer'; + div.addEventListener('click', (event) => + this.propagateUpdateHighlightedItems(event, label.rectId) ); const labelCss = new CSS2DObject(div); @@ -193,16 +197,26 @@ export class Canvas { private toMatrix4(transform: Transform3D): THREE.Matrix4 { return new THREE.Matrix4().set( - transform.dsdx, transform.dsdy, 0, transform.tx, - transform.dtdx, transform.dtdy, 0, transform.ty, - 0, 0, 1, 0, - 0, 0, 0, 1, + transform.dsdx, + transform.dsdy, + 0, + transform.tx, + transform.dtdx, + transform.dtdy, + 0, + transform.ty, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 ); } - private makeRectMesh( - rect: Rect3D - ): THREE.Mesh { + private makeRectMesh(rect: Rect3D): THREE.Mesh { const rectShape = this.createRectShape(rect); const rectGeometry = new THREE.ShapeGeometry(rectShape); const rectBorders = this.createRectBorders(rect, rectGeometry); @@ -219,7 +233,8 @@ export class Canvas { color: this.getColor(rect), opacity: opacity, transparent: true, - })); + }) + ); mesh.add(rectBorders); mesh.position.x = 0; @@ -231,8 +246,8 @@ export class Canvas { } private createRectShape(rect: Rect3D): THREE.Shape { - const bottomLeft: Point3D = { x: rect.topLeft.x, y: rect.bottomRight.y, z: rect.topLeft.z }; - const topRight: Point3D = { x: rect.bottomRight.x, y: rect.topLeft.y, z: rect.bottomRight.z }; + const bottomLeft: Point3D = {x: rect.topLeft.x, y: rect.bottomRight.y, z: rect.topLeft.z}; + const topRight: Point3D = {x: rect.bottomRight.x, y: rect.topLeft.y, z: rect.bottomRight.z}; // Create (rounded) rect shape return new THREE.Shape() @@ -240,11 +255,21 @@ export class Canvas { .lineTo(bottomLeft.x, bottomLeft.y - rect.cornerRadius) .quadraticCurveTo(bottomLeft.x, bottomLeft.y, bottomLeft.x + rect.cornerRadius, bottomLeft.y) .lineTo(rect.bottomRight.x - rect.cornerRadius, rect.bottomRight.y) - .quadraticCurveTo(rect.bottomRight.x, rect.bottomRight.y, rect.bottomRight.x, rect.bottomRight.y - rect.cornerRadius) + .quadraticCurveTo( + rect.bottomRight.x, + rect.bottomRight.y, + rect.bottomRight.x, + rect.bottomRight.y - rect.cornerRadius + ) .lineTo(topRight.x, topRight.y + rect.cornerRadius) .quadraticCurveTo(topRight.x, topRight.y, topRight.x - rect.cornerRadius, topRight.y) .lineTo(rect.topLeft.x + rect.cornerRadius, rect.topLeft.y) - .quadraticCurveTo(rect.topLeft.x, rect.topLeft.y, rect.topLeft.x, rect.topLeft.y + rect.cornerRadius); + .quadraticCurveTo( + rect.topLeft.x, + rect.topLeft.y, + rect.topLeft.x, + rect.topLeft.y + rect.cornerRadius + ); } private getColor(rect: Rect3D): THREE.Color { @@ -281,24 +306,22 @@ export class Canvas { if (rect.cornerRadius) { edgeMaterial = new THREE.LineBasicMaterial({ color: Canvas.RECT_EDGE_COLOR_ROUNDED, - linewidth: 1 + linewidth: 1, }); } else { - edgeMaterial = new THREE.LineBasicMaterial({ - color: Canvas.RECT_EDGE_COLOR, - linewidth: 1 - }); + edgeMaterial = new THREE.LineBasicMaterial({ + color: Canvas.RECT_EDGE_COLOR, + linewidth: 1, + }); } - const lineSegments = new THREE.LineSegments( - edgeGeo, edgeMaterial - ); + const lineSegments = new THREE.LineSegments(edgeGeo, edgeMaterial); lineSegments.computeLineDistances(); return lineSegments; } private makeLabelCircleMesh(circle: Circle3D): THREE.Mesh { const geometry = new THREE.CircleGeometry(circle.radius, 20); - const material = new THREE.MeshBasicMaterial({ color: Canvas.LABEL_CIRCLE_COLOR }); + const material = new THREE.MeshBasicMaterial({color: Canvas.LABEL_CIRCLE_COLOR}); const mesh = new THREE.Mesh(geometry, material); mesh.position.set(circle.center.x, circle.center.y, circle.center.z); return mesh; @@ -306,16 +329,14 @@ export class Canvas { private propagateUpdateHighlightedItems(event: MouseEvent, newId: string) { event.preventDefault(); - const highlightedChangeEvent: CustomEvent = new CustomEvent( - ViewerEvents.HighlightedChange, - { - bubbles: true, - detail: { id: newId } - }); + const highlightedChangeEvent: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, { + bubbles: true, + detail: {id: newId}, + }); event.target?.dispatchEvent(highlightedChangeEvent); } private clearLabels() { - this.canvasLabels.innerHTML = ""; + this.canvasLabels.innerHTML = ''; } } diff --git a/tools/winscope-ng/src/viewers/components/rects/mapper3d.ts b/tools/winscope-ng/src/viewers/components/rects/mapper3d.ts index 1d366b0f9..c1dcc5089 100644 --- a/tools/winscope-ng/src/viewers/components/rects/mapper3d.ts +++ b/tools/winscope-ng/src/viewers/components/rects/mapper3d.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {Rectangle, Size} from "viewers/common/rectangle"; +import {Rectangle, Size} from 'viewers/common/rectangle'; import { Box3D, ColorType, @@ -23,8 +23,8 @@ import { Point3D, Rect3D, Scene3D, - Transform3D -} from "./types3d"; + Transform3D, +} from './types3d'; class Mapper3D { private static readonly CAMERA_ROTATION_FACTOR_INIT = 1; @@ -43,7 +43,7 @@ class Mapper3D { tx: 0, dtdx: 0, dtdy: 1, - ty: 0 + ty: 0, }; private rects: Rectangle[] = []; @@ -141,21 +141,21 @@ class Mapper3D { panScreenDistance: this.panScreenDistance, }, rects: rects3d, - labels: labels3d + labels: labels3d, }; return scene; } private selectRectsToDraw(rects: Rectangle[]): Rectangle[] { - rects = rects.filter(rect => rect.displayId == this.currentDisplayId); + rects = rects.filter((rect) => rect.displayId == this.currentDisplayId); if (this.showOnlyVisibleMode) { - rects = rects.filter(rect => rect.isVisible || rect.isDisplay); + rects = rects.filter((rect) => rect.isVisible || rect.isDisplay); } if (!this.showVirtualMode) { - rects = rects.filter(rect => !rect.isVirtual); + rects = rects.filter((rect) => !rect.isVirtual); } return rects; @@ -167,7 +167,7 @@ class Mapper3D { let nonVisibleRectsSoFar = 0; let nonVisibleRectsTotal = 0; - rects2d.forEach(rect => { + rects2d.forEach((rect) => { if (rect.isVisible) { ++visibleRectsTotal; } else { @@ -182,21 +182,21 @@ class Mapper3D { const rects3d = rects2d.map((rect2d): Rect3D => { z -= Mapper3D.Z_SPACING_MAX * this.zSpacingFactor; - const darkFactor = rect2d.isVisible ? - (visibleRectsTotal - visibleRectsSoFar++) / visibleRectsTotal : - (nonVisibleRectsTotal - nonVisibleRectsSoFar++) / nonVisibleRectsTotal; + const darkFactor = rect2d.isVisible + ? (visibleRectsTotal - visibleRectsSoFar++) / visibleRectsTotal + : (nonVisibleRectsTotal - nonVisibleRectsSoFar++) / nonVisibleRectsTotal; const rect = { id: rect2d.id, topLeft: { x: rect2d.topLeft.x, y: rect2d.topLeft.y, - z: z + z: z, }, bottomRight: { x: rect2d.bottomRight.x, y: rect2d.bottomRight.y, - z: z + z: z, }, isOversized: false, cornerRadius: rect2d.cornerRadius, @@ -253,19 +253,18 @@ class Mapper3D { maxHeight = Math.max( ...displays.map((rect2d): number => Math.abs(rect2d.topLeft.y - rect2d.bottomRight.y)) ); - } return { width: maxWidth, - height: maxHeight - } + height: maxHeight, + }; } private cropOversizedRect(rect3d: Rect3D, maxDisplaySize: Size): Rect3D { // Arbitrary max size for a rect (2x the maximum display) let maxDimension = Number.MAX_VALUE; if (maxDisplaySize.height > 0) { - maxDimension = Math.max(maxDisplaySize.width, maxDisplaySize.height) * 2 + maxDimension = Math.max(maxDisplaySize.width, maxDisplaySize.height) * 2; } const height = Math.abs(rect3d.topLeft.y - rect3d.bottomRight.y); @@ -273,13 +272,13 @@ class Mapper3D { if (width > maxDimension) { rect3d.isOversized = true; - rect3d.topLeft.x = (maxDimension - (maxDisplaySize.width / 2)) * -1, - rect3d.bottomRight.x = maxDimension + (rect3d.topLeft.x = (maxDimension - maxDisplaySize.width / 2) * -1), + (rect3d.bottomRight.x = maxDimension); } if (height > maxDimension) { rect3d.isOversized = true; - rect3d.topLeft.y = (maxDimension - (maxDisplaySize.height / 2)) * -1 - rect3d.bottomRight.y = maxDimension + rect3d.topLeft.y = (maxDimension - maxDisplaySize.height / 2) * -1; + rect3d.bottomRight.y = maxDimension; } return rect3d; @@ -288,9 +287,12 @@ class Mapper3D { private computeLabels(rects2d: Rectangle[], rects3d: Rect3D[]): Label3D[] { const labels3d: Label3D[] = []; - let labelY = Math.max(...rects3d.map(rect => { - return this.matMultiply(rect.transform, rect.bottomRight).y; - })) + Mapper3D.LABEL_FIRST_Y_OFFSET; + let labelY = + Math.max( + ...rects3d.map((rect) => { + return this.matMultiply(rect.transform, rect.bottomRight).y; + }) + ) + Mapper3D.LABEL_FIRST_Y_OFFSET; rects2d.forEach((rect2d, index) => { if (!rect2d.label) { @@ -299,13 +301,21 @@ class Mapper3D { const rect3d = rects3d[index]; - const bottomLeft: Point3D = { x: rect3d.topLeft.x, y: rect3d.bottomRight.y, z: rect3d.topLeft.z }; - const topRight: Point3D = { x: rect3d.bottomRight.x, y: rect3d.topLeft.y, z: rect3d.bottomRight.z }; + const bottomLeft: Point3D = { + x: rect3d.topLeft.x, + y: rect3d.bottomRight.y, + z: rect3d.topLeft.z, + }; + const topRight: Point3D = { + x: rect3d.bottomRight.x, + y: rect3d.topLeft.y, + z: rect3d.bottomRight.z, + }; const lineStarts = [ this.matMultiply(rect3d.transform, rect3d.topLeft), this.matMultiply(rect3d.transform, rect3d.bottomRight), this.matMultiply(rect3d.transform, bottomLeft), - this.matMultiply(rect3d.transform, topRight) + this.matMultiply(rect3d.transform, topRight), ]; let maxIndex = 0; for (let i = 1; i < lineStarts.length; i++) { @@ -319,7 +329,7 @@ class Mapper3D { const lineEnd: Point3D = { x: lineStart.x, y: labelY, - z: lineStart.z + z: lineStart.z, }; const isHighlighted = this.highlightedRectIds.includes(rect2d.id); @@ -337,7 +347,7 @@ class Mapper3D { textCenter: lineEnd, text: rect2d.label, isHighlighted: isHighlighted, - rectId: rect2d.id + rectId: rect2d.id, }; labels3d.push(label3d); @@ -361,8 +371,8 @@ class Mapper3D { width: 1, height: 1, depth: 1, - center: { x: 0, y: 0, z: 0 }, - diagonal: Math.sqrt(3) + center: {x: 0, y: 0, z: 0}, + diagonal: Math.sqrt(3), }; } @@ -382,7 +392,7 @@ class Mapper3D { maxZ = Math.max(maxZ, point.z); }; - rects.forEach(rect => { + rects.forEach((rect) => { /*const topLeft: Point3D = { x: rect.center.x - rect.width / 2, y: rect.center.y + rect.height / 2, @@ -397,8 +407,8 @@ class Mapper3D { updateMinMaxCoordinates(rect.bottomRight); }); - labels.forEach(label => { - label.linePoints.forEach(point => { + labels.forEach((label) => { + label.linePoints.forEach((point) => { updateMinMaxCoordinates(point); }); }); @@ -406,7 +416,7 @@ class Mapper3D { const center: Point3D = { x: (minX + maxX) / 2, y: (minY + maxY) / 2, - z: (minZ + maxZ) / 2 + z: (minZ + maxZ) / 2, }; const width = maxX - minX; @@ -418,9 +428,9 @@ class Mapper3D { height: height, depth: depth, center: center, - diagonal: Math.sqrt(width * width + height * height + depth * depth) + diagonal: Math.sqrt(width * width + height * height + depth * depth), }; } } -export { Mapper3D }; +export {Mapper3D}; diff --git a/tools/winscope-ng/src/viewers/components/rects/rects.component.spec.ts b/tools/winscope-ng/src/viewers/components/rects/rects.component.spec.ts index 4d47e3a41..01f97c73c 100644 --- a/tools/winscope-ng/src/viewers/components/rects/rects.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/rects/rects.component.spec.ts @@ -13,33 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CommonModule } from "@angular/common"; -import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { Rectangle } from "viewers/common/rectangle"; -import { RectsComponent } from "viewers/components/rects/rects.component"; -import { MatCheckboxModule } from "@angular/material/checkbox"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatSliderModule } from "@angular/material/slider"; -import { MatRadioModule } from "@angular/material/radio"; -import {CUSTOM_ELEMENTS_SCHEMA, SimpleChange} from "@angular/core"; -import { Canvas } from "./canvas"; +import {CommonModule} from '@angular/common'; +import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatRadioModule} from '@angular/material/radio'; +import {MatSliderModule} from '@angular/material/slider'; +import {Rectangle} from 'viewers/common/rectangle'; +import {RectsComponent} from 'viewers/components/rects/rects.component'; +import {Canvas} from './canvas'; -describe("RectsComponent", () => { +describe('RectsComponent', () => { let component: RectsComponent; let fixture: ComponentFixture; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ - CommonModule, - MatCheckboxModule, - MatDividerModule, - MatSliderModule, - MatRadioModule - ], + imports: [CommonModule, MatCheckboxModule, MatDividerModule, MatSliderModule, MatRadioModule], declarations: [RectsComponent], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(RectsComponent); @@ -48,32 +42,32 @@ describe("RectsComponent", () => { fixture.detectChanges(); }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("renders rotation slider", () => { - const slider = htmlElement.querySelector("mat-slider.slider-rotation"); + it('renders rotation slider', () => { + const slider = htmlElement.querySelector('mat-slider.slider-rotation'); expect(slider).toBeTruthy(); }); - it("renders separation slider", () => { - const slider = htmlElement.querySelector("mat-slider.slider-spacing"); + it('renders separation slider', () => { + const slider = htmlElement.querySelector('mat-slider.slider-spacing'); expect(slider).toBeTruthy(); }); - it("renders canvas", () => { - const rectsCanvas = htmlElement.querySelector(".canvas-rects"); + it('renders canvas', () => { + const rectsCanvas = htmlElement.querySelector('.canvas-rects'); expect(rectsCanvas).toBeTruthy(); }); - it("draws scene when input data changes", async () => { - spyOn(Canvas.prototype, "draw").and.callThrough(); + it('draws scene when input data changes', async () => { + spyOn(Canvas.prototype, 'draw').and.callThrough(); const inputRect: Rectangle = { - topLeft: {x:0, y:0}, - bottomRight: {x:1, y:-1}, - label: "rectangle1", + topLeft: {x: 0, y: 0}, + bottomRight: {x: 1, y: -1}, + label: 'rectangle1', transform: { matrix: { dsdx: 1, @@ -81,17 +75,17 @@ describe("RectsComponent", () => { dtdx: 0, dtdy: 1, tx: 0, - ty: 0 - } + ty: 0, + }, }, isVisible: true, isDisplay: false, ref: null, - id: "test-id-1234", + id: 'test-id-1234', displayId: 0, isVirtual: false, isClickable: false, - cornerRadius: 0 + cornerRadius: 0, }; expect(Canvas.prototype.draw).toHaveBeenCalledTimes(0); @@ -101,23 +95,23 @@ describe("RectsComponent", () => { expect(Canvas.prototype.draw).toHaveBeenCalledTimes(2); }); - it("draws scene when rotation slider changes", () => { - spyOn(Canvas.prototype, "draw").and.callThrough(); - const slider = htmlElement.querySelector(".slider-rotation"); + it('draws scene when rotation slider changes', () => { + spyOn(Canvas.prototype, 'draw').and.callThrough(); + const slider = htmlElement.querySelector('.slider-rotation'); expect(Canvas.prototype.draw).toHaveBeenCalledTimes(0); - slider?.dispatchEvent(new MouseEvent("mousedown")); + slider?.dispatchEvent(new MouseEvent('mousedown')); expect(Canvas.prototype.draw).toHaveBeenCalledTimes(1); }); - it("draws scene when spacing slider changes", () => { - spyOn(Canvas.prototype, "draw").and.callThrough(); - const slider = htmlElement.querySelector(".slider-spacing"); + it('draws scene when spacing slider changes', () => { + spyOn(Canvas.prototype, 'draw').and.callThrough(); + const slider = htmlElement.querySelector('.slider-spacing'); expect(Canvas.prototype.draw).toHaveBeenCalledTimes(0); - slider?.dispatchEvent(new MouseEvent("mousedown")); + slider?.dispatchEvent(new MouseEvent('mousedown')); expect(Canvas.prototype.draw).toHaveBeenCalledTimes(1); }); }); diff --git a/tools/winscope-ng/src/viewers/components/rects/rects.component.ts b/tools/winscope-ng/src/viewers/components/rects/rects.component.ts index 9978df709..f9cebd16f 100644 --- a/tools/winscope-ng/src/viewers/components/rects/rects.component.ts +++ b/tools/winscope-ng/src/viewers/components/rects/rects.component.ts @@ -13,52 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Component, Input, OnDestroy, Inject, ElementRef, OnInit, HostListener} from "@angular/core"; -import {Rectangle, Point} from "viewers/common/rectangle"; -import {Canvas} from "./canvas"; -import {ViewerEvents} from "viewers/common/viewer_events"; -import {Mapper3D} from "./mapper3d"; -import {Distance2D} from "./types3d"; +import {Component, ElementRef, HostListener, Inject, Input, OnDestroy, OnInit} from '@angular/core'; +import {Rectangle} from 'viewers/common/rectangle'; +import {ViewerEvents} from 'viewers/common/viewer_events'; +import {Canvas} from './canvas'; +import {Mapper3D} from './mapper3d'; +import {Distance2D} from './types3d'; @Component({ - selector: "rects-view", + selector: 'rects-view', template: `
-

{{title}}

+

{{ title }}

Only visible + color="primary" + [checked]="mapper3d.getShowOnlyVisibleMode()" + (change)="onShowOnlyVisibleModeChange($event.checked!)" + >Only visible Show virtual + color="primary" + [disabled]="mapper3d.getShowOnlyVisibleMode()" + [checked]="mapper3d.getShowVirtualMode()" + (change)="onShowVirtualModeChange($event.checked!)" + >Show virtual
@@ -66,48 +59,44 @@ import {Distance2D} from "./types3d";

Rotation

+ class="slider-rotation" + step="0.02" + min="0" + max="1" + aria-label="units" + [value]="mapper3d.getCameraRotationFactor()" + (input)="onRotationSliderChange($event.value!)" + color="primary">

Spacing

+ class="slider-spacing" + step="0.02" + min="0.02" + max="1" + aria-label="units" + [value]="mapper3d.getZSpacingFactor()" + (input)="onSeparationSliderChange($event.value!)" + color="primary">
- + -
-
+
-
+
+ *ngFor="let displayId of internalDisplayIds" + color="primary" + mat-raised-button + (click)="onDisplayIdChange(displayId)"> + {{ displayId }} +
`, @@ -117,7 +106,8 @@ import {Distance2D} from "./types3d"; display: flex; flex-direction: column; } - .top-view-controls, .slider-view-controls { + .top-view-controls, + .slider-view-controls { display: flex; flex-direction: row; flex-wrap: wrap; @@ -171,12 +161,11 @@ import {Distance2D} from "./types3d"; flex-wrap: wrap; column-gap: 10px; } - ` - ] + `, + ], }) - export class RectsComponent implements OnInit, OnDestroy { - @Input() title = "title"; + @Input() title = 'title'; @Input() set rects(rects: Rectangle[]) { this.internalRects = rects; this.drawScene(); @@ -208,9 +197,7 @@ export class RectsComponent implements OnInit, OnDestroy { private mouseMoveListener = (event: MouseEvent) => this.onMouseMove(event); private mouseUpListener = (event: MouseEvent) => this.onMouseUp(event); - constructor( - @Inject(ElementRef) private elementRef: ElementRef, - ) { + constructor(@Inject(ElementRef) private elementRef: ElementRef) { this.mapper3d = new Mapper3D(); this.resizeObserver = new ResizeObserver((entries) => { this.drawScene(); @@ -218,14 +205,14 @@ export class RectsComponent implements OnInit, OnDestroy { } ngOnInit() { - const canvasContainer = this.elementRef.nativeElement.querySelector(".canvas-container"); + const canvasContainer = this.elementRef.nativeElement.querySelector('.canvas-container'); this.resizeObserver.observe(canvasContainer); - this.canvasRects = canvasContainer.querySelector(".canvas-rects")! as HTMLCanvasElement; - this.canvasLabels = canvasContainer.querySelector(".canvas-labels"); + this.canvasRects = canvasContainer.querySelector('.canvas-rects')! as HTMLCanvasElement; + this.canvasLabels = canvasContainer.querySelector('.canvas-labels'); this.canvas = new Canvas(this.canvasRects, this.canvasLabels!); - this.canvasRects.addEventListener("mousedown", event => this.onCanvasMouseDown(event)); + this.canvasRects.addEventListener('mousedown', (event) => this.onCanvasMouseDown(event)); this.mapper3d.setCurrentDisplayId(this.internalDisplayIds[0] ?? 0); this.drawScene(); @@ -250,7 +237,7 @@ export class RectsComponent implements OnInit, OnDestroy { this.drawScene(); } - @HostListener("wheel", ["$event"]) + @HostListener('wheel', ['$event']) public onScroll(event: WheelEvent) { if (event.deltaY > 0) { this.doZoomOut(); @@ -260,8 +247,8 @@ export class RectsComponent implements OnInit, OnDestroy { } public onCanvasMouseDown(event: MouseEvent) { - document.addEventListener("mousemove", this.mouseMoveListener); - document.addEventListener("mouseup", this.mouseUpListener); + document.addEventListener('mousemove', this.mouseMoveListener); + document.addEventListener('mouseup', this.mouseUpListener); } public onMouseMove(event: MouseEvent) { @@ -271,8 +258,8 @@ export class RectsComponent implements OnInit, OnDestroy { } public onMouseUp(event: MouseEvent) { - document.removeEventListener("mousemove", this.mouseMoveListener); - document.removeEventListener("mouseup", this.mouseUpListener); + document.removeEventListener('mousemove', this.mouseMoveListener); + document.removeEventListener('mouseup', this.mouseUpListener); } public onZoomInClick() { @@ -301,11 +288,11 @@ export class RectsComponent implements OnInit, OnDestroy { public onRectClick(event: MouseEvent) { event.preventDefault(); - const canvas = (event.target as Element); + const canvas = event.target as Element; const canvasOffset = canvas.getBoundingClientRect(); - const x = ((event.clientX-canvasOffset.left)/canvas.clientWidth) * 2 - 1; - const y = -((event.clientY-canvasOffset.top)/canvas.clientHeight) * 2 + 1; + const x = ((event.clientX - canvasOffset.left) / canvas.clientWidth) * 2 - 1; + const y = -((event.clientY - canvasOffset.top) / canvas.clientHeight) * 2 + 1; const z = 0; const id = this.canvas?.getClickedRectId(x, y, z); @@ -334,12 +321,10 @@ export class RectsComponent implements OnInit, OnDestroy { } private notifyHighlightedItem(id: string) { - const event: CustomEvent = new CustomEvent( - ViewerEvents.HighlightedChange, - { - bubbles: true, - detail: { id: id } - }); + const event: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, { + bubbles: true, + detail: {id: id}, + }); this.elementRef.nativeElement.dispatchEvent(event); } } diff --git a/tools/winscope-ng/src/viewers/components/rects/types3d.ts b/tools/winscope-ng/src/viewers/components/rects/types3d.ts index 600e799e1..cb30635d3 100644 --- a/tools/winscope-ng/src/viewers/components/rects/types3d.ts +++ b/tools/winscope-ng/src/viewers/components/rects/types3d.ts @@ -17,18 +17,17 @@ export enum ColorType { VISIBLE, NOT_VISIBLE, - HIGHLIGHTED + HIGHLIGHTED, } -export class Distance2D{ - constructor(public dx: number, public dy: number) { - } +export class Distance2D { + constructor(public dx: number, public dy: number) {} } export interface Box3D { - width: number, - height: number, - depth: number, + width: number; + height: number; + depth: number; center: Point3D; diagonal: number; } diff --git a/tools/winscope-ng/src/viewers/components/styles/node.styles.ts b/tools/winscope-ng/src/viewers/components/styles/node.styles.ts index 32bc1c7c9..5898323c9 100644 --- a/tools/winscope-ng/src/viewers/components/styles/node.styles.ts +++ b/tools/winscope-ng/src/viewers/components/styles/node.styles.ts @@ -87,4 +87,4 @@ export const nodeInnerItemStyles = ` .expand-tree-btn.addedMove { background: #03ff35; } -`; \ No newline at end of file +`; diff --git a/tools/winscope-ng/src/viewers/components/styles/tree_node_data_view.styles.ts b/tools/winscope-ng/src/viewers/components/styles/tree_node_data_view.styles.ts index c79eb98d7..03e7251b7 100644 --- a/tools/winscope-ng/src/viewers/components/styles/tree_node_data_view.styles.ts +++ b/tools/winscope-ng/src/viewers/components/styles/tree_node_data_view.styles.ts @@ -59,4 +59,4 @@ export const treeNodePropertiesDataViewStyles = ` .value.false { color: #FF4136; } -`; \ No newline at end of file +`; diff --git a/tools/winscope-ng/src/viewers/components/transform_matrix.component.spec.ts b/tools/winscope-ng/src/viewers/components/transform_matrix.component.spec.ts index 45bfe61ac..78d7dbf34 100644 --- a/tools/winscope-ng/src/viewers/components/transform_matrix.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/transform_matrix.component.spec.ts @@ -13,25 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { TransformMatrixComponent } from "./transform_matrix.component"; -import { ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {TransformMatrixComponent} from './transform_matrix.component'; -describe("TransformMatrixComponent", () => { +describe('TransformMatrixComponent', () => { let fixture: ComponentFixture; let component: TransformMatrixComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - declarations: [ - TransformMatrixComponent - ], - schemas: [NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + declarations: [TransformMatrixComponent], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -41,7 +36,7 @@ describe("TransformMatrixComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/transform_matrix.component.ts b/tools/winscope-ng/src/viewers/components/transform_matrix.component.ts index a09462001..cc1955499 100644 --- a/tools/winscope-ng/src/viewers/components/transform_matrix.component.ts +++ b/tools/winscope-ng/src/viewers/components/transform_matrix.component.ts @@ -13,43 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; -import { Transform } from "common/trace/flickerlib/common"; +import {Component, Input} from '@angular/core'; +import {Transform} from 'common/trace/flickerlib/common'; @Component({ - selector: "transform-matrix", + selector: 'transform-matrix', template: ` -
-

- {{ formatFloat(transform.matrix.dsdx) }} -

-

- {{ formatFloat(transform.matrix.dsdy) }} -

-

- {{ formatFloat(transform.matrix.tx) }} -

+
+

+ {{ formatFloat(transform.matrix.dsdx) }} +

+

+ {{ formatFloat(transform.matrix.dsdy) }} +

+

+ {{ formatFloat(transform.matrix.tx) }} +

-

- {{ formatFloat(transform.matrix.dtdx) }} -

-

- {{ formatFloat(transform.matrix.dtdy) }} -

-

- {{ formatFloat(transform.matrix.ty) }} -

+

+ {{ formatFloat(transform.matrix.dtdx) }} +

+

+ {{ formatFloat(transform.matrix.dtdy) }} +

+

+ {{ formatFloat(transform.matrix.ty) }} +

-

- 0 -

-

- 0 -

-

- 1 -

-
+

0

+

0

+

1

+
`, styles: [ ` @@ -59,10 +53,9 @@ import { Transform } from "common/trace/flickerlib/common"; grid-template-columns: repeat(3, 1fr); text-align: center; } - ` + `, ], }) - export class TransformMatrixComponent { @Input() transform!: Transform; @Input() formatFloat!: (num: number) => number; diff --git a/tools/winscope-ng/src/viewers/components/tree.component.spec.ts b/tools/winscope-ng/src/viewers/components/tree.component.spec.ts index 19612ec68..a92bec298 100644 --- a/tools/winscope-ng/src/viewers/components/tree.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/tree.component.spec.ts @@ -13,26 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ComponentFixture, TestBed, ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { TreeComponent } from "./tree.component"; -import { Component, ViewChild, NO_ERRORS_SCHEMA } from "@angular/core"; -import { PersistentStore } from "common/utils/persistent_store"; -import { UiTreeNode } from "viewers/common/ui_tree_utils"; +import {Component, NO_ERRORS_SCHEMA, ViewChild} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {UiTreeNode} from 'viewers/common/ui_tree_utils'; +import {TreeComponent} from './tree.component'; -describe("TreeComponent", () => { +describe('TreeComponent', () => { let fixture: ComponentFixture; let component: TestHostComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - declarations: [ - TreeComponent, TestHostComponent - ], - schemas: [NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + declarations: [TreeComponent, TestHostComponent], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -42,36 +38,35 @@ describe("TreeComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { fixture.detectChanges(); expect(component).toBeTruthy(); }); @Component({ - selector: "host-component", + selector: 'host-component', template: ` - - ` + + `, }) class TestHostComponent { isFlattened = true; item: UiTreeNode = { simplifyNames: false, - kind: "entry", - name: "BaseLayerTraceEntry", - shortName: "BLTE", + kind: 'entry', + name: 'BaseLayerTraceEntry', + shortName: 'BLTE', chips: [], - children: [{kind: "3", stableId: "3", name: "Child1"}], + children: [{kind: '3', stableId: '3', name: 'Child1'}], }; store = new PersistentStore(); - diffClass = jasmine.createSpy().and.returnValue("none"); + diffClass = jasmine.createSpy().and.returnValue('none'); isHighlighted = jasmine.createSpy().and.returnValue(false); hasChildren = jasmine.createSpy().and.returnValue(true); diff --git a/tools/winscope-ng/src/viewers/components/tree.component.ts b/tools/winscope-ng/src/viewers/components/tree.component.ts index 7136c4e2a..64c2cad96 100644 --- a/tools/winscope-ng/src/viewers/components/tree.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree.component.ts @@ -13,14 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Component, Inject, Input, Output, ElementRef, EventEmitter, ChangeDetectionStrategy} from "@angular/core"; -import { PersistentStore } from "common/utils/persistent_store"; -import { nodeStyles, treeNodeDataViewStyles } from "viewers/components/styles/node.styles"; -import { UiTreeUtils, UiTreeNode, HierarchyTreeNode } from "viewers/common/ui_tree_utils"; -import { TraceType } from "common/trace/trace_type"; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + EventEmitter, + Inject, + Input, + Output, +} from '@angular/core'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {HierarchyTreeNode, UiTreeNode, UiTreeUtils} from 'viewers/common/ui_tree_utils'; +import {nodeStyles, treeNodeDataViewStyles} from 'viewers/components/styles/node.styles'; @Component({ - selector: "tree-view", + selector: 'tree-view', changeDetection: ChangeDetectionStrategy.OnPush, template: ` + (pinNodeChange)="propagateNewPinnedItem($event)"> -
+
+ *ngFor="let child of children(); trackBy: childTrackById" + class="childrenTree" + [item]="child" + [store]="store" + [showNode]="showNode" + [isLeaf]="isLeaf" + [dependencies]="dependencies" + [isFlattened]="isFlattened" + [useGlobalCollapsedState]="useGlobalCollapsedState" + [initialDepth]="initialDepth + 1" + [highlightedItems]="highlightedItems" + [pinnedItems]="pinnedItems" + (highlightedItemChange)="propagateNewHighlightedItem($event)" + (pinnedItemChange)="propagateNewPinnedItem($event)" + (selectedTreeChange)="propagateNewSelectedTree($event)" + [itemsClickable]="itemsClickable" + (hoverStart)="childHover = true" + (hoverEnd)="childHover = false">
`, - styles: [nodeStyles, treeNodeDataViewStyles] + styles: [nodeStyles, treeNodeDataViewStyles], }) - export class TreeComponent { diffClass = UiTreeUtils.diffClass; isHighlighted = UiTreeUtils.isHighlighted; @@ -112,21 +121,18 @@ export class TreeComponent { if (child.stableId !== undefined) { return child.stableId; } - if (!(child instanceof HierarchyTreeNode) - && typeof child.propertyKey === "string") { + if (!(child instanceof HierarchyTreeNode) && typeof child.propertyKey === 'string') { return child.propertyKey; } - throw Error("Missing stable id or property key on node"); + throw Error('Missing stable id or property key on node'); } - constructor( - @Inject(ElementRef) public elementRef: ElementRef - ) { - this.nodeElement = elementRef.nativeElement.querySelector(".node"); - this.nodeElement?.addEventListener("mousedown", this.nodeMouseDownEventListener); - this.nodeElement?.addEventListener("mouseenter", this.nodeMouseEnterEventListener); - this.nodeElement?.addEventListener("mouseleave", this.nodeMouseLeaveEventListener); + constructor(@Inject(ElementRef) public elementRef: ElementRef) { + this.nodeElement = elementRef.nativeElement.querySelector('.node'); + this.nodeElement?.addEventListener('mousedown', this.nodeMouseDownEventListener); + this.nodeElement?.addEventListener('mouseenter', this.nodeMouseEnterEventListener); + this.nodeElement?.addEventListener('mouseleave', this.nodeMouseLeaveEventListener); } ngOnInit() { @@ -136,20 +142,23 @@ export class TreeComponent { } ngOnChanges() { - if (this.item instanceof HierarchyTreeNode && UiTreeUtils.isHighlighted(this.item, this.highlightedItems)) { + if ( + this.item instanceof HierarchyTreeNode && + UiTreeUtils.isHighlighted(this.item, this.highlightedItems) + ) { this.selectedTreeChange.emit(this.item); } } ngOnDestroy() { - this.nodeElement?.removeEventListener("mousedown", this.nodeMouseDownEventListener); - this.nodeElement?.removeEventListener("mouseenter", this.nodeMouseEnterEventListener); - this.nodeElement?.removeEventListener("mouseleave", this.nodeMouseLeaveEventListener); + this.nodeElement?.removeEventListener('mousedown', this.nodeMouseDownEventListener); + this.nodeElement?.removeEventListener('mouseenter', this.nodeMouseEnterEventListener); + this.nodeElement?.removeEventListener('mouseleave', this.nodeMouseLeaveEventListener); } public onNodeClick(event: MouseEvent) { event.preventDefault(); - if (window.getSelection()?.type === "range") { + if (window.getSelection()?.type === 'range') { return; } @@ -163,10 +172,10 @@ export class TreeComponent { } public nodeOffsetStyle() { - const offset = this.levelOffset * (this.initialDepth) + "px"; + const offset = this.levelOffset * this.initialDepth + 'px'; return { - marginLeft: "-" + offset, + marginLeft: '-' + offset, paddingLeft: offset, }; } @@ -179,7 +188,7 @@ export class TreeComponent { public isPinned() { if (this.item instanceof HierarchyTreeNode) { - return this.pinnedItems?.map(item => `${item.stableId}`).includes(`${this.item.stableId}`); + return this.pinnedItems?.map((item) => `${item.stableId}`).includes(`${this.item.stableId}`); } return false; } @@ -214,8 +223,10 @@ export class TreeComponent { } if (this.useGlobalCollapsedState) { - return this.store.get(`collapsedState.item.${this.dependencies}.${this.item?.stableId}`)==="true" - ?? this.isCollapsedByDefault; + return ( + this.store.get(`collapsedState.item.${this.dependencies}.${this.item?.stableId}`) === + 'true' ?? this.isCollapsedByDefault + ); } return this.localCollapsedState; } @@ -228,19 +239,23 @@ export class TreeComponent { if (!this.item) { return false; } - const isParentEntryInFlatView = UiTreeUtils.isParentNode(this.item.kind ?? "") && this.isFlattened; + const isParentEntryInFlatView = + UiTreeUtils.isParentNode(this.item.kind ?? '') && this.isFlattened; return (!this.isFlattened || isParentEntryInFlatView) && !this.isLeaf(this.item); } private setCollapseValue(isCollapsed: boolean) { if (this.useGlobalCollapsedState) { - this.store.add(`collapsedState.item.${this.dependencies}.${this.item?.stableId}`, `${isCollapsed}`); + this.store.add( + `collapsedState.item.${this.dependencies}.${this.item?.stableId}`, + `${isCollapsed}` + ); } else { this.localCollapsedState = isCollapsed; } } - private nodeMouseDownEventListener = (event:MouseEvent) => { + private nodeMouseDownEventListener = (event: MouseEvent) => { if (event.detail > 1) { event.preventDefault(); return false; diff --git a/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts b/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts index 035319abf..c525a2912 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts @@ -13,24 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ComponentFixture, TestBed, ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { TreeNodeComponent } from "./tree_node.component"; -import { Component, ViewChild, NO_ERRORS_SCHEMA } from "@angular/core"; +import {Component, NO_ERRORS_SCHEMA, ViewChild} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {TreeNodeComponent} from './tree_node.component'; -describe("TreeNodeComponent", () => { +describe('TreeNodeComponent', () => { let fixture: ComponentFixture; let component: TestHostComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - declarations: [ - TreeNodeComponent, TestHostComponent - ], - schemas: [NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + declarations: [TreeNodeComponent, TestHostComponent], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -40,33 +36,32 @@ describe("TreeNodeComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { fixture.detectChanges(); expect(component).toBeTruthy(); }); @Component({ - selector: "host-component", + selector: 'host-component', template: ` - - ` + + `, }) class TestHostComponent { item = { simplifyNames: false, - kind: "entry", - name: "BaseLayerTraceEntry", - shortName: "BLTE", + kind: 'entry', + name: 'BaseLayerTraceEntry', + shortName: 'BLTE', chips: [], }; @ViewChild(TreeNodeComponent) public treeNodeComponent!: TreeNodeComponent; } -}); \ No newline at end of file +}); diff --git a/tools/winscope-ng/src/viewers/components/tree_node.component.ts b/tools/winscope-ng/src/viewers/components/tree_node.component.ts index 421472f42..b162a4b30 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node.component.ts @@ -13,20 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input, Output, EventEmitter } from "@angular/core"; -import { nodeInnerItemStyles } from "viewers/components/styles/node.styles"; -import { UiTreeUtils, UiTreeNode, DiffType, HierarchyTreeNode } from "viewers/common/ui_tree_utils"; +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {DiffType, HierarchyTreeNode, UiTreeNode, UiTreeUtils} from 'viewers/common/ui_tree_utils'; +import {nodeInnerItemStyles} from 'viewers/components/styles/node.styles'; @Component({ - selector: "tree-node", + selector: 'tree-node', template: ` - @@ -34,41 +30,29 @@ import { UiTreeUtils, UiTreeNode, DiffType, HierarchyTreeNode } from "viewers/co
-
- + + [item]="item">
`, - styles: [nodeInnerItemStyles] + styles: [nodeInnerItemStyles], }) - export class TreeNodeComponent { @Input() item!: UiTreeNode; @Input() isLeaf?: boolean; @@ -83,7 +67,7 @@ export class TreeNodeComponent { @Output() expandTreeChange = new EventEmitter(); @Output() pinNodeChange = new EventEmitter(); - collapseDiffClass = ""; + collapseDiffClass = ''; ngOnChanges() { this.collapseDiffClass = this.updateCollapseDiffClass(); @@ -94,7 +78,9 @@ export class TreeNodeComponent { } public showPinNodeIcon() { - return (!this.isPropertiesTreeNode() && !UiTreeUtils.isParentNode(this.item.kind ?? "")) ?? false; + return ( + (!this.isPropertiesTreeNode() && !UiTreeUtils.isParentNode(this.item.kind ?? '')) ?? false + ); } public toggleTree(event: MouseEvent) { @@ -124,7 +110,7 @@ export class TreeNodeComponent { public updateCollapseDiffClass() { if (this.isCollapsed) { - return ""; + return ''; } const childrenDiffClasses = this.getAllDiffTypesOfChildren(this.item); @@ -133,7 +119,7 @@ export class TreeNodeComponent { childrenDiffClasses.delete(undefined); if (childrenDiffClasses.size === 0) { - return ""; + return ''; } if (childrenDiffClasses.size === 1) { const diffType = childrenDiffClasses.values().next().value; diff --git a/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.spec.ts b/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.spec.ts index ea619dd99..fe4cbf61e 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.spec.ts @@ -13,25 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { TreeNodeDataViewComponent } from "./tree_node_data_view.component"; -import { ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { NO_ERRORS_SCHEMA } from "@angular/core"; +import {NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {TreeNodeDataViewComponent} from './tree_node_data_view.component'; -describe("TreeNodeDataViewComponent", () => { +describe('TreeNodeDataViewComponent', () => { let fixture: ComponentFixture; let component: TreeNodeDataViewComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - declarations: [ - TreeNodeDataViewComponent - ], - schemas: [NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + declarations: [TreeNodeDataViewComponent], + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -41,7 +36,7 @@ describe("TreeNodeDataViewComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts b/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts index 57d73798f..66c57ffc3 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts @@ -13,57 +13,60 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; -import { treeNodeDataViewStyles } from "viewers/components/styles/tree_node_data_view.styles"; -import { Terminal, HierarchyTreeNode, UiTreeNode } from "viewers/common/ui_tree_utils"; -import Chip from "viewers/common/chip"; +import {Component, Input} from '@angular/core'; +import Chip from 'viewers/common/chip'; +import {HierarchyTreeNode, Terminal, UiTreeNode} from 'viewers/common/ui_tree_utils'; +import {treeNodeDataViewStyles} from 'viewers/components/styles/tree_node_data_view.styles'; @Component({ - selector: "tree-node-data-view", + selector: 'tree-node-data-view', template: ` - {{item.kind}} + {{ item.kind }} &ngsp;-&ngsp; {{ itemShortName() }} - {{item.name}} -
{{chip.short}}
+ {{ item.name }} +
+ {{ chip.short }} +
`, - styles: [ treeNodeDataViewStyles ] + styles: [treeNodeDataViewStyles], }) - export class TreeNodeDataViewComponent { @Input() item!: UiTreeNode; public chips() { - return (this.item instanceof HierarchyTreeNode) ? this.item.chips : []; + return this.item instanceof HierarchyTreeNode ? this.item.chips : []; } public itemShortName() { - return (this.item instanceof HierarchyTreeNode && this.item.shortName) ? this.item.shortName : this.item.name; + return this.item instanceof HierarchyTreeNode && this.item.shortName + ? this.item.shortName + : this.item.name; } public itemTooltip() { if (this.item.name instanceof Terminal) { - return ""; + return ''; } - return this.item.name ?? ""; + return this.item.name ?? ''; } public showShortName() { - return (this.item instanceof HierarchyTreeNode) && this.item.simplifyNames && this.item.shortName && this.item.shortName !== this.item.name; + return ( + this.item instanceof HierarchyTreeNode && + this.item.simplifyNames && + this.item.shortName && + this.item.shortName !== this.item.name + ); } public chipClass(chip: Chip) { return [ - "tree-view-internal-chip", - "tree-view-chip", - "tree-view-chip" + "-" + - (chip.type.toString() || "default"), + 'tree-view-internal-chip', + 'tree-view-chip', + 'tree-view-chip' + '-' + (chip.type.toString() || 'default'), ]; } } diff --git a/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.spec.ts b/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.spec.ts index 1d913d4ce..9763b7a24 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.spec.ts @@ -13,23 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { TreeNodePropertiesDataViewComponent } from "./tree_node_properties_data_view.component"; -import { ComponentFixtureAutoDetect } from "@angular/core/testing"; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {TreeNodePropertiesDataViewComponent} from './tree_node_properties_data_view.component'; -describe("TreeNodePropertiesDataViewComponent", () => { +describe('TreeNodePropertiesDataViewComponent', () => { let fixture: ComponentFixture; let component: TreeNodePropertiesDataViewComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - declarations: [ - TreeNodePropertiesDataViewComponent - ], + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + declarations: [TreeNodePropertiesDataViewComponent], }).compileComponents(); }); @@ -39,7 +34,7 @@ describe("TreeNodePropertiesDataViewComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts b/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts index 8d1a234e5..61ba12920 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, Input } from "@angular/core"; -import { treeNodePropertiesDataViewStyles } from "viewers/components/styles/tree_node_data_view.styles"; -import { PropertiesTreeNode } from "viewers/common/ui_tree_utils"; +import {Component, Input} from '@angular/core'; +import {PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {treeNodePropertiesDataViewStyles} from 'viewers/components/styles/tree_node_data_view.styles'; @Component({ - selector: "tree-node-properties-data-view", + selector: 'tree-node-properties-data-view', template: `

{{ item.propertyKey }} @@ -28,9 +28,8 @@ import { PropertiesTreeNode } from "viewers/common/ui_tree_utils";

`, - styles: [ treeNodePropertiesDataViewStyles ] + styles: [treeNodePropertiesDataViewStyles], }) - export class TreeNodePropertiesDataViewComponent { @Input() item!: PropertiesTreeNode; @@ -39,20 +38,20 @@ export class TreeNodePropertiesDataViewComponent { return null; } - if (this.item.propertyValue == "null") { - return "null"; + if (this.item.propertyValue == 'null') { + return 'null'; } - if (this.item.propertyValue == "true") { - return "true"; + if (this.item.propertyValue == 'true') { + return 'true'; } - if (this.item.propertyValue == "false") { - return "false"; + if (this.item.propertyValue == 'false') { + return 'false'; } if (!isNaN(Number(this.item.propertyValue))) { - return "number"; + return 'number'; } return null; diff --git a/tools/winscope-ng/src/viewers/components/viewer_input_method.component.spec.ts b/tools/winscope-ng/src/viewers/components/viewer_input_method.component.spec.ts index af1791064..b8190beb4 100644 --- a/tools/winscope-ng/src/viewers/components/viewer_input_method.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/viewer_input_method.component.spec.ts @@ -13,35 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import { ViewerInputMethodComponent } from "./viewer_input_method.component"; -import { HierarchyComponent } from "viewers/components/hierarchy.component"; -import { PropertiesComponent } from "viewers/components/properties.component"; -import { MatDividerModule } from "@angular/material/divider"; -import { MatIconModule } from "@angular/material/icon"; -import { ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core"; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatIconModule} from '@angular/material/icon'; +import {HierarchyComponent} from 'viewers/components/hierarchy.component'; +import {PropertiesComponent} from 'viewers/components/properties.component'; +import {ViewerInputMethodComponent} from './viewer_input_method.component'; -describe("ViewerInputMethodComponent", () => { +describe('ViewerInputMethodComponent', () => { let fixture: ComponentFixture; let component: ViewerInputMethodComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - imports: [ - MatIconModule, - MatDividerModule - ], - declarations: [ - ViewerInputMethodComponent, - HierarchyComponent, - PropertiesComponent, - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + imports: [MatIconModule, MatDividerModule], + declarations: [ViewerInputMethodComponent, HierarchyComponent, PropertiesComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -51,17 +41,17 @@ describe("ViewerInputMethodComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("creates hierarchy view", () => { - const hierarchyView = htmlElement.querySelector(".hierarchy-view"); + it('creates hierarchy view', () => { + const hierarchyView = htmlElement.querySelector('.hierarchy-view'); expect(hierarchyView).toBeTruthy(); }); - it("creates properties view", () => { - const propertiesView = htmlElement.querySelector(".properties-view"); + it('creates properties view', () => { + const propertiesView = htmlElement.querySelector('.properties-view'); expect(propertiesView).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/components/viewer_input_method.component.ts b/tools/winscope-ng/src/viewers/components/viewer_input_method.component.ts index 8e5158bbf..e0803b64e 100644 --- a/tools/winscope-ng/src/viewers/components/viewer_input_method.component.ts +++ b/tools/winscope-ng/src/viewers/components/viewer_input_method.component.ts @@ -13,49 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - Component, - Input, -} from "@angular/core"; -import { TRACE_INFO } from "app/trace_info"; -import { TraceType } from "common/trace/trace_type"; -import { PersistentStore } from "common/utils/persistent_store"; -import { ImeUiData } from "viewers/common/ime_ui_data"; +import {Component, Input} from '@angular/core'; +import {TRACE_INFO} from 'app/trace_info'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {ImeUiData} from 'viewers/common/ime_ui_data'; @Component({ - selector: "viewer-input-method", + selector: 'viewer-input-method', template: ` -
-
- +
+
+ - - + + - - -
- - - - + +
+ + + + +
`, styles: [ ` @@ -65,7 +59,9 @@ import { ImeUiData } from "viewers/common/ime_ui_data"; flex-direction: column; } - .hierarchy-view, .ime-additional-properties, .properties-view { + .hierarchy-view, + .ime-additional-properties, + .properties-view { flex: 1; padding: 16px; display: flex; @@ -73,7 +69,7 @@ import { ImeUiData } from "viewers/common/ime_ui_data"; overflow: auto; } `, - ] + ], }) export class ViewerInputMethodComponent { @Input() inputData: ImeUiData | null = null; diff --git a/tools/winscope-ng/src/viewers/viewer.ts b/tools/winscope-ng/src/viewers/viewer.ts index bff070437..344cdd93e 100644 --- a/tools/winscope-ng/src/viewers/viewer.ts +++ b/tools/winscope-ng/src/viewers/viewer.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TraceType } from "common/trace/trace_type"; +import {TraceType} from 'common/trace/trace_type'; enum ViewType { TAB, - OVERLAY + OVERLAY, } class View { @@ -26,8 +26,7 @@ class View { public dependencies: TraceType[], public htmlElement: HTMLElement, public title: string - ) { - } + ) {} } interface Viewer { diff --git a/tools/winscope-ng/src/viewers/viewer_factory.ts b/tools/winscope-ng/src/viewers/viewer_factory.ts index fc35ecbc8..b3a00f0b5 100644 --- a/tools/winscope-ng/src/viewers/viewer_factory.ts +++ b/tools/winscope-ng/src/viewers/viewer_factory.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {Viewer} from "./viewer"; -import {ViewerInputMethodClients} from "./viewer_input_method_clients/viewer_input_method_clients"; -import {ViewerInputMethodService} from "./viewer_input_method_service/viewer_input_method_service"; -import {ViewerInputMethodManagerService} from "./viewer_input_method_manager_service/viewer_input_method_manager_service"; -import {ViewerProtoLog} from "./viewer_protolog/viewer_protolog"; -import {ViewerSurfaceFlinger} from "./viewer_surface_flinger/viewer_surface_flinger"; -import {ViewerWindowManager} from "./viewer_window_manager/viewer_window_manager"; -import {ViewerTransactions} from "./viewer_transactions/viewer_transactions"; -import {ViewerScreenRecording} from "./viewer_screen_recording/viewer_screen_recording"; +import {TraceType} from 'common/trace/trace_type'; +import {Viewer} from './viewer'; +import {ViewerInputMethodClients} from './viewer_input_method_clients/viewer_input_method_clients'; +import {ViewerInputMethodManagerService} from './viewer_input_method_manager_service/viewer_input_method_manager_service'; +import {ViewerInputMethodService} from './viewer_input_method_service/viewer_input_method_service'; +import {ViewerProtoLog} from './viewer_protolog/viewer_protolog'; +import {ViewerScreenRecording} from './viewer_screen_recording/viewer_screen_recording'; +import {ViewerSurfaceFlinger} from './viewer_surface_flinger/viewer_surface_flinger'; +import {ViewerTransactions} from './viewer_transactions/viewer_transactions'; +import {ViewerWindowManager} from './viewer_window_manager/viewer_window_manager'; class ViewerFactory { // Note: diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.spec.ts b/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.spec.ts index 0400e662f..bff48ddfd 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.spec.ts @@ -13,23 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TraceType } from "common/trace/trace_type"; -import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; -import { PresenterInputMethodClients } from "./presenter_input_method_clients"; -import { executePresenterInputMethodTests } from "viewers/common/presenter_input_method_test_utils"; +import {TraceType} from 'common/trace/trace_type'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {executePresenterInputMethodTests} from 'viewers/common/presenter_input_method_test_utils'; +import {PresenterInputMethodClients} from './presenter_input_method_clients'; -describe("PresenterInputMethodClients", () => { - describe("PresenterInputMethod tests:", () => { - const selectedTree = new HierarchyTreeBuilder() - .setId("entry").setStableId("entry").build(); +describe('PresenterInputMethodClients', () => { + describe('PresenterInputMethod tests:', () => { + const selectedTree = new HierarchyTreeBuilder().setId('entry').setStableId('entry').build(); executePresenterInputMethodTests( selectedTree, - "elapsed", + 'elapsed', [2, 1], true, PresenterInputMethodClients, - TraceType.INPUT_METHOD_CLIENTS, + TraceType.INPUT_METHOD_CLIENTS ); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.ts b/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.ts index 219c5863a..eb2aec1b5 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_clients/presenter_input_method_clients.ts @@ -1,4 +1,3 @@ - /* * Copyright (C) 2022 The Android Open Source Project * @@ -14,20 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PresenterInputMethod } from "viewers/common/presenter_input_method"; +import {PresenterInputMethod} from 'viewers/common/presenter_input_method'; export class PresenterInputMethodClients extends PresenterInputMethod { protected updateHierarchyTableProperties() { - return {...new ImClientsTableProperties( - this.entry?.obj?.client?.inputMethodManager?.curId, - this.entry?.obj?.client?.editorInfo?.packageName, - )}; + return { + ...new ImClientsTableProperties( + this.entry?.obj?.client?.inputMethodManager?.curId, + this.entry?.obj?.client?.editorInfo?.packageName + ), + }; } } class ImClientsTableProperties { - constructor( - public inputMethodId: string | undefined, - public packageName: string | undefined, - ) {} + constructor(public inputMethodId: string | undefined, public packageName: string | undefined) {} } diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_clients/viewer_input_method_clients.ts b/tools/winscope-ng/src/viewers/viewer_input_method_clients/viewer_input_method_clients.ts index bb4b33340..1171b14c0 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_clients/viewer_input_method_clients.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_clients/viewer_input_method_clients.ts @@ -13,14 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {PresenterInputMethodClients} from "./presenter_input_method_clients"; -import {ViewerInputMethod} from "viewers/common/viewer_input_method"; -import {View, ViewType} from "viewers/viewer"; +import {TraceType} from 'common/trace/trace_type'; +import {ViewerInputMethod} from 'viewers/common/viewer_input_method'; +import {View, ViewType} from 'viewers/viewer'; +import {PresenterInputMethodClients} from './presenter_input_method_clients'; class ViewerInputMethodClients extends ViewerInputMethod { override getViews(): View[] { - return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, "Input Method Clients")]; + return [ + new View(ViewType.TAB, this.getDependencies(), this.htmlElement, 'Input Method Clients'), + ]; } override getDependencies(): TraceType[] { diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.spec.ts b/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.spec.ts index f67b1de31..c92ba8145 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.spec.ts @@ -13,24 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TraceType } from "common/trace/trace_type"; -import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; -import { PresenterInputMethodManagerService } from "./presenter_input_method_manager_service"; -import { executePresenterInputMethodTests } from "viewers/common/presenter_input_method_test_utils"; -import { UnitTestUtils } from "test/unit/utils"; +import {TraceType} from 'common/trace/trace_type'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {executePresenterInputMethodTests} from 'viewers/common/presenter_input_method_test_utils'; +import {PresenterInputMethodManagerService} from './presenter_input_method_manager_service'; -describe("PresenterInputMethodManagerService", () => { - describe("PresenterInputMethod tests:", () => { +describe('PresenterInputMethodManagerService', () => { + describe('PresenterInputMethod tests:', () => { const selectedTree = new HierarchyTreeBuilder() - .setId("managerservice").setStableId("managerservice").build(); + .setId('managerservice') + .setStableId('managerservice') + .build(); executePresenterInputMethodTests( selectedTree, - "cur", + 'cur', [13, 8], false, PresenterInputMethodManagerService, - TraceType.INPUT_METHOD_MANAGER_SERVICE, + TraceType.INPUT_METHOD_MANAGER_SERVICE ); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.ts b/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.ts index d37826456..dc8d45eee 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/presenter_input_method_manager_service.ts @@ -1,4 +1,3 @@ - /* * Copyright (C) 2022 The Android Open Source Project * @@ -14,25 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PresenterInputMethod } from "viewers/common/presenter_input_method"; -import { ImeAdditionalProperties } from "viewers/common/ime_additional_properties"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { ImeUtils } from "viewers/common/ime_utils"; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {ImeAdditionalProperties} from 'viewers/common/ime_additional_properties'; +import {ImeUtils} from 'viewers/common/ime_utils'; +import {PresenterInputMethod} from 'viewers/common/presenter_input_method'; export class PresenterInputMethodManagerService extends PresenterInputMethod { protected updateHierarchyTableProperties() { - return {...new ImManagerServiceTableProperties( - this.entry?.obj?.inputMethodManagerService?.curMethodId, - this.entry?.obj?.inputMethodManagerService?.curFocusedWindowName, - this.entry?.obj?.inputMethodManagerService?.lastImeTargetWindowName, - this.entry?.obj?.inputMethodManagerService?.inputShown ?? false, - )}; + return { + ...new ImManagerServiceTableProperties( + this.entry?.obj?.inputMethodManagerService?.curMethodId, + this.entry?.obj?.inputMethodManagerService?.curFocusedWindowName, + this.entry?.obj?.inputMethodManagerService?.lastImeTargetWindowName, + this.entry?.obj?.inputMethodManagerService?.inputShown ?? false + ), + }; } - protected override getAdditionalProperties(wmEntry: TraceTreeNode | undefined, sfEntry: TraceTreeNode | undefined) { + protected override getAdditionalProperties( + wmEntry: TraceTreeNode | undefined, + sfEntry: TraceTreeNode | undefined + ) { return new ImeAdditionalProperties( wmEntry ? ImeUtils.processWindowManagerTraceEntry(wmEntry) : undefined, - undefined, + undefined ); } } @@ -42,6 +46,6 @@ class ImManagerServiceTableProperties { public inputMethodId: string | undefined, public curFocusedWindow: string | undefined, public lastImeTargetWindow: string | undefined, - public inputShown: boolean, + public inputShown: boolean ) {} } diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/viewer_input_method_manager_service.ts b/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/viewer_input_method_manager_service.ts index 36c5b0983..205b18a79 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/viewer_input_method_manager_service.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_manager_service/viewer_input_method_manager_service.ts @@ -13,18 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {PresenterInputMethodManagerService} from "./presenter_input_method_manager_service"; -import {ViewerInputMethod} from "viewers/common/viewer_input_method"; -import {View, ViewType} from "viewers/viewer"; +import {TraceType} from 'common/trace/trace_type'; +import {ViewerInputMethod} from 'viewers/common/viewer_input_method'; +import {View, ViewType} from 'viewers/viewer'; +import {PresenterInputMethodManagerService} from './presenter_input_method_manager_service'; class ViewerInputMethodManagerService extends ViewerInputMethod { override getViews(): View[] { return [ - new View(ViewType.TAB, + new View( + ViewType.TAB, this.getDependencies(), this.htmlElement, - "Input Method Manager Service") + 'Input Method Manager Service' + ), ]; } @@ -33,7 +35,11 @@ class ViewerInputMethodManagerService extends ViewerInputMethod { } override initialisePresenter(storage: Storage) { - return new PresenterInputMethodManagerService(this.imeUiCallback, this.getDependencies(), storage); + return new PresenterInputMethodManagerService( + this.imeUiCallback, + this.getDependencies(), + storage + ); } public static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_MANAGER_SERVICE]; diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.spec.ts b/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.spec.ts index a74c4cc20..4f75f1886 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.spec.ts @@ -13,24 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TraceType } from "common/trace/trace_type"; -import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; -import { PresenterInputMethodService } from "./presenter_input_method_service"; -import { executePresenterInputMethodTests } from "viewers/common/presenter_input_method_test_utils"; -import { UnitTestUtils } from "test/unit/utils"; +import {TraceType} from 'common/trace/trace_type'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {executePresenterInputMethodTests} from 'viewers/common/presenter_input_method_test_utils'; +import {PresenterInputMethodService} from './presenter_input_method_service'; -describe("PresenterInputMethodService", () => { - describe("PresenterInputMethod tests:", () => { - const selectedTree = new HierarchyTreeBuilder() - .setId("service").setStableId("service").build(); +describe('PresenterInputMethodService', () => { + describe('PresenterInputMethod tests:', () => { + const selectedTree = new HierarchyTreeBuilder().setId('service').setStableId('service').build(); executePresenterInputMethodTests( selectedTree, - "visib", + 'visib', [13, 3], true, PresenterInputMethodService, - TraceType.INPUT_METHOD_SERVICE, + TraceType.INPUT_METHOD_SERVICE ); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.ts b/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.ts index 85ffed0bc..0d7ca8353 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_service/presenter_input_method_service.ts @@ -1,4 +1,3 @@ - /* * Copyright (C) 2022 The Android Open Source Project * @@ -14,15 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PresenterInputMethod } from "viewers/common/presenter_input_method"; +import {PresenterInputMethod} from 'viewers/common/presenter_input_method'; export class PresenterInputMethodService extends PresenterInputMethod { protected updateHierarchyTableProperties() { - return {...new ImServiceTableProperties( - this.entry?.obj?.inputMethodService?.windowVisible ?? false, - this.entry?.obj?.inputMethodService?.decorViewVisible ?? false, - this.entry?.obj?.inputMethodService?.inputEditorInfo?.packageName, - )}; + return { + ...new ImServiceTableProperties( + this.entry?.obj?.inputMethodService?.windowVisible ?? false, + this.entry?.obj?.inputMethodService?.decorViewVisible ?? false, + this.entry?.obj?.inputMethodService?.inputEditorInfo?.packageName + ), + }; } } diff --git a/tools/winscope-ng/src/viewers/viewer_input_method_service/viewer_input_method_service.ts b/tools/winscope-ng/src/viewers/viewer_input_method_service/viewer_input_method_service.ts index c7e0e6e5a..405e6a1ae 100644 --- a/tools/winscope-ng/src/viewers/viewer_input_method_service/viewer_input_method_service.ts +++ b/tools/winscope-ng/src/viewers/viewer_input_method_service/viewer_input_method_service.ts @@ -13,20 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {PresenterInputMethodService} from "./presenter_input_method_service"; -import {ViewerInputMethod} from "viewers/common/viewer_input_method"; -import {View, ViewType} from "viewers/viewer"; +import {TraceType} from 'common/trace/trace_type'; +import {ViewerInputMethod} from 'viewers/common/viewer_input_method'; +import {View, ViewType} from 'viewers/viewer'; +import {PresenterInputMethodService} from './presenter_input_method_service'; class ViewerInputMethodService extends ViewerInputMethod { override getViews(): View[] { return [ - new View( - ViewType.TAB, - this.getDependencies(), - this.htmlElement, - "Input Method Service" - ) + new View(ViewType.TAB, this.getDependencies(), this.htmlElement, 'Input Method Service'), ]; } diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/events.ts b/tools/winscope-ng/src/viewers/viewer_protolog/events.ts index 773e9706a..0a1c45176 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/events.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/events.ts @@ -14,10 +14,10 @@ * limitations under the License. */ class Events { - public static LogLevelsFilterChanged = "ViewerProtoLogEvent_LogLevelsFilterChanged"; - public static TagsFilterChanged = "ViewerProtoLogEvent_TagsFilterChanged"; - public static SourceFilesFilterChanged = "ViewerProtoLogEvent_SourceFilesFilterChanged"; - public static SearchStringFilterChanged = "ViewerProtoLogEvent_SearchStringFilterChanged"; + public static LogLevelsFilterChanged = 'ViewerProtoLogEvent_LogLevelsFilterChanged'; + public static TagsFilterChanged = 'ViewerProtoLogEvent_TagsFilterChanged'; + public static SourceFilesFilterChanged = 'ViewerProtoLogEvent_SourceFilesFilterChanged'; + public static SearchStringFilterChanged = 'ViewerProtoLogEvent_SearchStringFilterChanged'; } export {Events}; diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/presenter.spec.ts b/tools/winscope-ng/src/viewers/viewer_protolog/presenter.spec.ts index 506b445c2..b6397f38e 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/presenter.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/presenter.spec.ts @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {LogMessage, ProtoLogTraceEntry} from "common/trace/protolog"; -import {TraceType} from "common/trace/trace_type"; -import {Presenter} from "./presenter"; -import {UiData} from "./ui_data"; +import {LogMessage, ProtoLogTraceEntry} from 'common/trace/protolog'; +import {TraceType} from 'common/trace/trace_type'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; -describe("ViewerProtoLogPresenter", () => { +describe('ViewerProtoLogPresenter', () => { let presenter: Presenter; let inputMessages: LogMessage[]; let inputTraceEntries: Map; - let outputUiData: undefined|UiData; + let outputUiData: undefined | UiData; beforeEach(async () => { inputMessages = [ - new LogMessage("text0", "time", "tag0", "level0", "sourcefile0", 10n), - new LogMessage("text1", "time", "tag1", "level1", "sourcefile1", 10n), - new LogMessage("text2", "time", "tag2", "level2", "sourcefile2", 10n), + new LogMessage('text0', 'time', 'tag0', 'level0', 'sourcefile0', 10n), + new LogMessage('text1', 'time', 'tag1', 'level1', 'sourcefile1', 10n), + new LogMessage('text2', 'time', 'tag2', 'level2', 'sourcefile2', 10n), ]; inputTraceEntries = new Map(); inputTraceEntries.set(TraceType.PROTO_LOG, [new ProtoLogTraceEntry(inputMessages, 0)]); @@ -40,7 +40,7 @@ describe("ViewerProtoLogPresenter", () => { }); }); - it("is robust to undefined trace entry", () => { + it('is robust to undefined trace entry', () => { presenter.notifyCurrentTraceEntries(new Map()); expect(outputUiData!.messages).toEqual([]); expect(outputUiData!.currentMessageIndex).toBeUndefined(); @@ -54,81 +54,81 @@ describe("ViewerProtoLogPresenter", () => { expect(outputUiData!.messages).toEqual(inputMessages); }); - it("processes current trace entries", () => { + it('processes current trace entries', () => { presenter.notifyCurrentTraceEntries(inputTraceEntries); - expect(outputUiData!.allLogLevels).toEqual(["level0", "level1", "level2"]); - expect(outputUiData!.allTags).toEqual(["tag0", "tag1", "tag2"]); - expect(outputUiData!.allSourceFiles).toEqual(["sourcefile0", "sourcefile1", "sourcefile2"]); + expect(outputUiData!.allLogLevels).toEqual(['level0', 'level1', 'level2']); + expect(outputUiData!.allTags).toEqual(['tag0', 'tag1', 'tag2']); + expect(outputUiData!.allSourceFiles).toEqual(['sourcefile0', 'sourcefile1', 'sourcefile2']); expect(outputUiData!.messages).toEqual(inputMessages); expect(outputUiData!.currentMessageIndex).toEqual(0); }); - it("updated displayed messages according to log levels filter", () => { + it('updated displayed messages according to log levels filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntries); expect(outputUiData!.messages).toEqual(inputMessages); presenter.onLogLevelsFilterChanged([]); expect(outputUiData!.messages).toEqual(inputMessages); - presenter.onLogLevelsFilterChanged(["level1"]); + presenter.onLogLevelsFilterChanged(['level1']); expect(outputUiData!.messages).toEqual([inputMessages[1]]); - presenter.onLogLevelsFilterChanged(["level0", "level1", "level2"]); + presenter.onLogLevelsFilterChanged(['level0', 'level1', 'level2']); expect(outputUiData!.messages).toEqual(inputMessages); }); - it("updates displayed messages according to tags filter", () => { + it('updates displayed messages according to tags filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntries); expect(outputUiData!.messages).toEqual(inputMessages); presenter.onTagsFilterChanged([]); expect(outputUiData!.messages).toEqual(inputMessages); - presenter.onTagsFilterChanged(["tag1"]); + presenter.onTagsFilterChanged(['tag1']); expect(outputUiData!.messages).toEqual([inputMessages[1]]); - presenter.onTagsFilterChanged(["tag0", "tag1", "tag2"]); + presenter.onTagsFilterChanged(['tag0', 'tag1', 'tag2']); expect(outputUiData!.messages).toEqual(inputMessages); }); - it("updates displayed messages according to source files filter", () => { + it('updates displayed messages according to source files filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntries); expect(outputUiData!.messages).toEqual(inputMessages); presenter.onSourceFilesFilterChanged([]); expect(outputUiData!.messages).toEqual(inputMessages); - presenter.onSourceFilesFilterChanged(["sourcefile1"]); + presenter.onSourceFilesFilterChanged(['sourcefile1']); expect(outputUiData!.messages).toEqual([inputMessages[1]]); - presenter.onSourceFilesFilterChanged(["sourcefile0", "sourcefile1", "sourcefile2"]); + presenter.onSourceFilesFilterChanged(['sourcefile0', 'sourcefile1', 'sourcefile2']); expect(outputUiData!.messages).toEqual(inputMessages); }); - it("updates displayed messages according to search string filter", () => { + it('updates displayed messages according to search string filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntries); expect(outputUiData!.messages).toEqual(inputMessages); - presenter.onSearchStringFilterChanged(""); + presenter.onSearchStringFilterChanged(''); expect(outputUiData!.messages).toEqual(inputMessages); - presenter.onSearchStringFilterChanged("text"); + presenter.onSearchStringFilterChanged('text'); expect(outputUiData!.messages).toEqual(inputMessages); - presenter.onSearchStringFilterChanged("text0"); + presenter.onSearchStringFilterChanged('text0'); expect(outputUiData!.messages).toEqual([inputMessages[0]]); - presenter.onSearchStringFilterChanged("text1"); + presenter.onSearchStringFilterChanged('text1'); expect(outputUiData!.messages).toEqual([inputMessages[1]]); }); - it("computes current message index", () => { + it('computes current message index', () => { presenter.notifyCurrentTraceEntries(inputTraceEntries); presenter.onLogLevelsFilterChanged([]); expect(outputUiData!.currentMessageIndex).toEqual(0); - presenter.onLogLevelsFilterChanged(["level0"]); + presenter.onLogLevelsFilterChanged(['level0']); expect(outputUiData!.currentMessageIndex).toEqual(0); presenter.onLogLevelsFilterChanged([]); @@ -139,13 +139,13 @@ describe("ViewerProtoLogPresenter", () => { presenter.onLogLevelsFilterChanged([]); expect(outputUiData!.currentMessageIndex).toEqual(1); - presenter.onLogLevelsFilterChanged(["level0"]); + presenter.onLogLevelsFilterChanged(['level0']); expect(outputUiData!.currentMessageIndex).toEqual(0); - presenter.onLogLevelsFilterChanged(["level1"]); + presenter.onLogLevelsFilterChanged(['level1']); expect(outputUiData!.currentMessageIndex).toEqual(0); - presenter.onLogLevelsFilterChanged(["level0", "level1"]); + presenter.onLogLevelsFilterChanged(['level0', 'level1']); expect(outputUiData!.currentMessageIndex).toEqual(1); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/presenter.ts b/tools/winscope-ng/src/viewers/viewer_protolog/presenter.ts index 1db0867dc..0de37cf9d 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/presenter.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/presenter.ts @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {UiData} from "./ui_data"; -import {ArrayUtils} from "common/utils/array_utils"; -import {LogMessage, ProtoLogTraceEntry} from "common/trace/protolog"; -import {TraceType} from "common/trace/trace_type"; +import {LogMessage, ProtoLogTraceEntry} from 'common/trace/protolog'; +import {TraceType} from 'common/trace/trace_type'; +import {ArrayUtils} from 'common/utils/array_utils'; +import {UiData} from './ui_data'; export class Presenter { - constructor( - notifyUiDataCallback: (data: UiData) => void) { + constructor(notifyUiDataCallback: (data: UiData) => void) { this.notifyUiDataCallback = notifyUiDataCallback; this.originalIndicesOfFilteredOutputMessages = []; this.uiData = UiData.EMPTY; @@ -72,36 +71,47 @@ export class Presenter { const allLogLevels = this.getUniqueMessageValues( this.entry!.messages, - (message: LogMessage) => message.level); + (message: LogMessage) => message.level + ); const allTags = this.getUniqueMessageValues( this.entry!.messages, - (message: LogMessage) => message.tag); + (message: LogMessage) => message.tag + ); const allSourceFiles = this.getUniqueMessageValues( this.entry!.messages, - (message: LogMessage) => message.at); + (message: LogMessage) => message.at + ); - let filteredMessagesAndOriginalIndex: [number, LogMessage][] = [...this.entry!.messages.entries()]; + let filteredMessagesAndOriginalIndex: [number, LogMessage][] = [ + ...this.entry!.messages.entries(), + ]; if (this.levels.length > 0) { - filteredMessagesAndOriginalIndex = - filteredMessagesAndOriginalIndex.filter(value => this.levels.includes(value[1].level)); + filteredMessagesAndOriginalIndex = filteredMessagesAndOriginalIndex.filter((value) => + this.levels.includes(value[1].level) + ); } if (this.tags.length > 0) { - filteredMessagesAndOriginalIndex = - filteredMessagesAndOriginalIndex.filter(value => this.tags.includes(value[1].tag)); + filteredMessagesAndOriginalIndex = filteredMessagesAndOriginalIndex.filter((value) => + this.tags.includes(value[1].tag) + ); } if (this.files.length > 0) { - filteredMessagesAndOriginalIndex = - filteredMessagesAndOriginalIndex.filter(value => this.files.includes(value[1].at)); + filteredMessagesAndOriginalIndex = filteredMessagesAndOriginalIndex.filter((value) => + this.files.includes(value[1].at) + ); } - filteredMessagesAndOriginalIndex = - filteredMessagesAndOriginalIndex.filter(value => value[1].text.includes(this.searchString)); + filteredMessagesAndOriginalIndex = filteredMessagesAndOriginalIndex.filter((value) => + value[1].text.includes(this.searchString) + ); - this.originalIndicesOfFilteredOutputMessages = filteredMessagesAndOriginalIndex.map(value => value[0]); - const filteredMessages = filteredMessagesAndOriginalIndex.map(value => value[1]); + this.originalIndicesOfFilteredOutputMessages = filteredMessagesAndOriginalIndex.map( + (value) => value[0] + ); + const filteredMessages = filteredMessagesAndOriginalIndex.map((value) => value[1]); this.uiData = new UiData(allLogLevels, allTags, allSourceFiles, filteredMessages, 0); } @@ -117,9 +127,12 @@ export class Presenter { ); } - private getUniqueMessageValues(messages: LogMessage[], getValue: (message :LogMessage) => string): string[] { + private getUniqueMessageValues( + messages: LogMessage[], + getValue: (message: LogMessage) => string + ): string[] { const uniqueValues = new Set(); - messages.forEach(message => { + messages.forEach((message) => { uniqueValues.add(getValue(message)); }); const result = [...uniqueValues]; @@ -135,5 +148,5 @@ export class Presenter { private tags: string[] = []; private files: string[] = []; private levels: string[] = []; - private searchString = ""; + private searchString = ''; } diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/ui_data.ts b/tools/winscope-ng/src/viewers/viewer_protolog/ui_data.ts index e5cef89da..d15a4e995 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/ui_data.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/ui_data.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {LogMessage} from "common/trace/protolog"; +import {LogMessage} from 'common/trace/protolog'; class UiData { constructor( @@ -21,8 +21,8 @@ class UiData { public allTags: string[], public allSourceFiles: string[], public messages: LogMessage[], - public currentMessageIndex: undefined|number) { - } + public currentMessageIndex: undefined | number + ) {} public static EMPTY = new UiData([], [], [], [], undefined); } diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.spec.ts b/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.spec.ts index ba4ec9377..e9dcbc3e3 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.spec.ts @@ -13,29 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ScrollingModule} from "@angular/cdk/scrolling"; -import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from "@angular/core/testing"; -import {ViewerProtologComponent} from "./viewer_protolog.component"; +import {ScrollingModule} from '@angular/cdk/scrolling'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {ViewerProtologComponent} from './viewer_protolog.component'; -import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core"; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core'; -describe("ViewerProtologComponent", () => { +describe('ViewerProtologComponent', () => { let fixture: ComponentFixture; let component: ViewerProtologComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - imports: [ - ScrollingModule - ], - declarations: [ - ViewerProtologComponent, - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + imports: [ScrollingModule], + declarations: [ViewerProtologComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -45,18 +39,18 @@ describe("ViewerProtologComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("creates message filters", () => { - expect(htmlElement.querySelector(".filters .log-level")).toBeTruthy(); - expect(htmlElement.querySelector(".filters .tag")).toBeTruthy(); - expect(htmlElement.querySelector(".filters .source-file")).toBeTruthy(); - expect(htmlElement.querySelector(".filters .text")).toBeTruthy(); + it('creates message filters', () => { + expect(htmlElement.querySelector('.filters .log-level')).toBeTruthy(); + expect(htmlElement.querySelector('.filters .tag')).toBeTruthy(); + expect(htmlElement.querySelector('.filters .source-file')).toBeTruthy(); + expect(htmlElement.querySelector('.filters .text')).toBeTruthy(); }); - it("renders log messages", () => { - expect(htmlElement.querySelector(".scroll-messages")).toBeTruthy(); + it('renders log messages', () => { + expect(htmlElement.querySelector('.scroll-messages')).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.ts b/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.ts index 815566b1a..ce2d28115 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.component.ts @@ -13,16 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {CdkVirtualScrollViewport} from "@angular/cdk/scrolling"; -import { - Component, ElementRef, Inject, Input, ViewChild -} from "@angular/core"; -import {MatSelectChange} from "@angular/material/select"; -import {Events} from "./events"; -import {UiData} from "./ui_data"; +import {CdkVirtualScrollViewport} from '@angular/cdk/scrolling'; +import {Component, ElementRef, Inject, Input, ViewChild} from '@angular/core'; +import {MatSelectChange} from '@angular/material/select'; +import {Events} from './events'; +import {UiData} from './ui_data'; @Component({ - selector: "viewer-protolog", + selector: 'viewer-protolog', template: `
@@ -30,9 +28,8 @@ import {UiData} from "./ui_data"; Log level - - {{level}} + + {{ level }} @@ -41,9 +38,8 @@ import {UiData} from "./ui_data"; Tags - - {{tag}} + + {{ tag }} @@ -52,9 +48,8 @@ import {UiData} from "./ui_data"; Source files - - {{file}} + + {{ file }} @@ -62,17 +57,30 @@ import {UiData} from "./ui_data";
Search text - +
-
-
{{message.time}}
-
{{message.level}}
-
{{message.tag}}
-
{{message.at}}
-
{{message.text}}
+
+
+ {{ message.time }} +
+
+ {{ message.level }} +
+
+ {{ message.tag }} +
+
+ {{ message.at }} +
+
+ {{ message.text }} +
@@ -104,7 +112,8 @@ import {UiData} from "./ui_data"; } .message.current-message { - background-color: #365179;color: white; + background-color: #365179; + color: white; } .time { @@ -143,7 +152,7 @@ import {UiData} from "./ui_data"; width: 100%; } `, - ] + ], }) export class ViewerProtologComponent { constructor(@Inject(ElementRef) elementRef: ElementRef) { @@ -179,18 +188,16 @@ export class ViewerProtologComponent { } private emitEvent(event: string, data: any) { - const customEvent = new CustomEvent( - event, - { - bubbles: true, - detail: data - }); + const customEvent = new CustomEvent(event, { + bubbles: true, + detail: data, + }); this.elementRef.nativeElement.dispatchEvent(customEvent); } @ViewChild(CdkVirtualScrollViewport) scrollComponent!: CdkVirtualScrollViewport; public uiData: UiData = UiData.EMPTY; - private searchString = ""; + private searchString = ''; private elementRef: ElementRef; } diff --git a/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.ts b/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.ts index ab25954fd..14092f0cb 100644 --- a/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.ts +++ b/tools/winscope-ng/src/viewers/viewer_protolog/viewer_protolog.ts @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {View, Viewer, ViewType} from "viewers/viewer"; -import {Presenter} from "./presenter"; -import {Events} from "./events"; -import {UiData} from "./ui_data"; +import {TraceType} from 'common/trace/trace_type'; +import {View, Viewer, ViewType} from 'viewers/viewer'; +import {Events} from './events'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; class ViewerProtoLog implements Viewer { constructor() { - this.htmlElement = document.createElement("viewer-protolog"); + this.htmlElement = document.createElement('viewer-protolog'); this.presenter = new Presenter((data: UiData) => { (this.htmlElement as any).inputData = data; @@ -46,7 +46,7 @@ class ViewerProtoLog implements Viewer { } public getViews(): View[] { - return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, "ProtoLog")]; + return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, 'ProtoLog')]; } public getDependencies(): TraceType[] { diff --git a/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.spec.ts b/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.spec.ts index dcd53065d..2ce5106f1 100644 --- a/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.spec.ts @@ -13,28 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; -import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from "@angular/core/testing"; -import {MatCardModule} from "@angular/material/card"; -import {ViewerScreenRecordingComponent} from "./viewer_screen_recording.component"; +import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatCardModule} from '@angular/material/card'; +import {ViewerScreenRecordingComponent} from './viewer_screen_recording.component'; -describe("ViewerScreenRecordingComponent", () => { +describe('ViewerScreenRecordingComponent', () => { let fixture: ComponentFixture; let component: ViewerScreenRecordingComponent; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - imports: [ - MatCardModule, - ], - declarations: [ - ViewerScreenRecordingComponent, - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + imports: [MatCardModule], + declarations: [ViewerScreenRecordingComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(ViewerScreenRecordingComponent); @@ -44,23 +38,23 @@ describe("ViewerScreenRecordingComponent", () => { fixture.detectChanges(); }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("can be minimized and maximized", () => { - const buttonMinimize = htmlElement.querySelector(".button-minimize"); - const videoContainer = htmlElement.querySelector(".video-container") as HTMLElement; + it('can be minimized and maximized', () => { + const buttonMinimize = htmlElement.querySelector('.button-minimize'); + const videoContainer = htmlElement.querySelector('.video-container') as HTMLElement; expect(buttonMinimize).toBeTruthy(); expect(videoContainer).toBeTruthy(); - expect(videoContainer!.style.height).toEqual(""); + expect(videoContainer!.style.height).toEqual(''); - buttonMinimize!.dispatchEvent(new Event("click")); + buttonMinimize!.dispatchEvent(new Event('click')); fixture.detectChanges(); - expect(videoContainer!.style.height).toEqual("0px"); + expect(videoContainer!.style.height).toEqual('0px'); - buttonMinimize!.dispatchEvent(new Event("click")); + buttonMinimize!.dispatchEvent(new Event('click')); fixture.detectChanges(); - expect(videoContainer!.style.height).toEqual(""); + expect(videoContainer!.style.height).toEqual(''); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.ts b/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.ts index e3de81d60..d4794562c 100644 --- a/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.component.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Component, ElementRef, Inject, Input} from "@angular/core"; -import {DomSanitizer, SafeUrl} from "@angular/platform-browser"; -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; +import {Component, ElementRef, Inject, Input} from '@angular/core'; +import {DomSanitizer, SafeUrl} from '@angular/platform-browser'; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; @Component({ - selector: "viewer-screen-recording", + selector: 'viewer-screen-recording', template: ` @@ -27,26 +27,23 @@ import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; Screen recording -
- - +
- + [src]="videoUrl" + cdkDragHandle> @@ -88,7 +85,8 @@ import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; flex-grow: 0; } - .video-container, video { + .video-container, + video { border: 1px solid var(--default-border); max-width: max(250px, 15vw); cursor: grab; @@ -100,18 +98,19 @@ import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; text-align: center; } `, - ] + ], }) class ViewerScreenRecordingComponent { constructor( @Inject(ElementRef) elementRef: ElementRef, - @Inject(DomSanitizer) sanitizer: DomSanitizer) { + @Inject(DomSanitizer) sanitizer: DomSanitizer + ) { this.elementRef = elementRef; this.sanitizer = sanitizer; } @Input() - public set currentTraceEntry(entry: undefined|ScreenRecordingTraceEntry) { + public set currentTraceEntry(entry: undefined | ScreenRecordingTraceEntry) { if (entry === undefined) { this.videoCurrentTime = undefined; return; @@ -128,8 +127,8 @@ class ViewerScreenRecordingComponent { this.isMinimized = !this.isMinimized; } - public videoUrl: undefined|SafeUrl = undefined; - public videoCurrentTime: number|undefined = undefined; + public videoUrl: undefined | SafeUrl = undefined; + public videoCurrentTime: number | undefined = undefined; public isMinimized = false; private elementRef: ElementRef; diff --git a/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.ts b/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.ts index 1f4334153..33340a13d 100644 --- a/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.ts +++ b/tools/winscope-ng/src/viewers/viewer_screen_recording/viewer_screen_recording.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {View, Viewer, ViewType} from "viewers/viewer"; -import {ScreenRecordingTraceEntry} from "common/trace/screen_recording"; +import {ScreenRecordingTraceEntry} from 'common/trace/screen_recording'; +import {TraceType} from 'common/trace/trace_type'; +import {View, Viewer, ViewType} from 'viewers/viewer'; class ViewerScreenRecording implements Viewer { constructor() { - this.htmlElement = document.createElement("viewer-screen-recording"); + this.htmlElement = document.createElement('viewer-screen-recording'); } public notifyCurrentTraceEntries(entries: Map): void { @@ -31,7 +31,9 @@ class ViewerScreenRecording implements Viewer { } public getViews(): View[] { - return [new View(ViewType.OVERLAY, this.getDependencies(), this.htmlElement, "ScreenRecording")]; + return [ + new View(ViewType.OVERLAY, this.getDependencies(), this.htmlElement, 'ScreenRecording'), + ]; } public getDependencies(): TraceType[] { diff --git a/tools/winscope-ng/src/viewers/viewer_stub.ts b/tools/winscope-ng/src/viewers/viewer_stub.ts index ac049fdca..2f7592dc3 100644 --- a/tools/winscope-ng/src/viewers/viewer_stub.ts +++ b/tools/winscope-ng/src/viewers/viewer_stub.ts @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Viewer, View, ViewType} from "./viewer"; +import {View, Viewer, ViewType} from './viewer'; class ViewerStub implements Viewer { constructor(title: string, viewContent?: string) { this.title = title; if (viewContent !== undefined) { - this.htmlElement = document.createElement("div"); + this.htmlElement = document.createElement('div'); this.htmlElement.innerText = viewContent; } else { this.htmlElement = undefined as unknown as HTMLElement; diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts index 20f18f2dd..336d37070 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Presenter} from "./presenter"; -import {UiData} from "./ui_data"; -import {UserOptions} from "viewers/common/user_options"; -import {TraceType} from "common/trace/trace_type"; -import {LayerTraceEntry} from "common/trace/flickerlib/common"; -import {HierarchyTreeNode, PropertiesTreeNode} from "viewers/common/ui_tree_utils"; -import {UnitTestUtils} from "test/unit/utils"; -import {HierarchyTreeBuilder} from "test/unit/hierarchy_tree_builder"; -import { MockStorage } from "test/unit/mock_storage"; +import {LayerTraceEntry} from 'common/trace/flickerlib/common'; +import {TraceType} from 'common/trace/trace_type'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {MockStorage} from 'test/unit/mock_storage'; +import {UnitTestUtils} from 'test/unit/utils'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; -describe("PresenterSurfaceFlinger", () => { +describe('PresenterSurfaceFlinger', () => { let presenter: Presenter; let uiData: UiData; let entries: Map; @@ -33,8 +33,14 @@ describe("PresenterSurfaceFlinger", () => { entries = new Map(); const entry: LayerTraceEntry = await UnitTestUtils.getLayerTraceEntry(); - selectedTree = new HierarchyTreeBuilder().setName("Dim layer#53").setStableId("EffectLayer 53 Dim layer#53") - .setFilteredView(true).setKind("53").setDiffType("EffectLayer").setId(53).build(); + selectedTree = new HierarchyTreeBuilder() + .setName('Dim layer#53') + .setStableId('EffectLayer 53 Dim layer#53') + .setFilteredView(true) + .setKind('53') + .setDiffType('EffectLayer') + .setId(53) + .build(); entries.set(TraceType.SURFACE_FLINGER, [entry, null]); }); @@ -45,22 +51,24 @@ describe("PresenterSurfaceFlinger", () => { }, new MockStorage()); }); - it("processes current trace entries", () => { + it('processes current trace entries', () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.rects.length).toBeGreaterThan(0); expect(uiData.highlightedItems?.length).toEqual(0); expect(uiData.displayIds).toContain(0); - const hierarchyOpts = uiData.hierarchyUserOptions ? - Object.keys(uiData.hierarchyUserOptions) : null; + const hierarchyOpts = uiData.hierarchyUserOptions + ? Object.keys(uiData.hierarchyUserOptions) + : null; expect(hierarchyOpts).toBeTruthy(); - const propertyOpts = uiData.propertiesUserOptions ? - Object.keys(uiData.propertiesUserOptions) : null; + const propertyOpts = uiData.propertiesUserOptions + ? Object.keys(uiData.propertiesUserOptions) + : null; expect(propertyOpts).toBeTruthy(); expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); - it("handles unavailable trace entry", () => { + it('handles unavailable trace entry', () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.tree).toBeDefined(); expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); @@ -70,49 +78,52 @@ describe("PresenterSurfaceFlinger", () => { expect(uiData.tree).toBeFalsy(); }); - it("creates input data for rects view", () => { + it('creates input data for rects view', () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.rects.length).toBeGreaterThan(0); expect(uiData.rects[0].topLeft).toEqual({x: 0, y: 0}); expect(uiData.rects[0].bottomRight).toEqual({x: 1080, y: 118}); }); - it("updates pinned items", () => { + it('updates pinned items', () => { expect(uiData.pinnedItems).toEqual([]); - const pinnedItem = new HierarchyTreeBuilder().setName("FirstPinnedItem") - .setStableId("TestItem 4").setLayerId(4).build(); + const pinnedItem = new HierarchyTreeBuilder() + .setName('FirstPinnedItem') + .setStableId('TestItem 4') + .setLayerId(4) + .build(); presenter.updatePinnedItems(pinnedItem); expect(uiData.pinnedItems).toContain(pinnedItem); }); - it("updates highlighted items", () => { + it('updates highlighted items', () => { expect(uiData.highlightedItems).toEqual([]); - const id = "4"; + const id = '4'; presenter.updateHighlightedItems(id); expect(uiData.highlightedItems).toContain(id); }); - it("updates hierarchy tree", () => { + it('updates hierarchy tree', () => { //change flat view to true const userOptions: UserOptions = { showDiff: { - name: "Show diff", - enabled: false + name: 'Show diff', + enabled: false, }, simplifyNames: { - name: "Simplify names", - enabled: true + name: 'Simplify names', + enabled: true, }, onlyVisible: { - name: "Only visible", - enabled: false + name: 'Only visible', + enabled: false, }, flat: { - name: "Flat", - enabled: true - } + name: 'Flat', + enabled: true, + }, }; presenter.notifyCurrentTraceEntries(entries); @@ -124,56 +135,55 @@ describe("PresenterSurfaceFlinger", () => { expect(uiData.tree?.children.length).toEqual(94); }); - it("filters hierarchy tree", () => { + it('filters hierarchy tree', () => { const userOptions: UserOptions = { showDiff: { - name: "Show diff", - enabled: false + name: 'Show diff', + enabled: false, }, simplifyNames: { - name: "Simplify names", - enabled: true + name: 'Simplify names', + enabled: true, }, onlyVisible: { - name: "Only visible", - enabled: false + name: 'Only visible', + enabled: false, }, flat: { - name: "Flat", - enabled: true - } + name: 'Flat', + enabled: true, + }, }; presenter.notifyCurrentTraceEntries(entries); presenter.updateHierarchyTree(userOptions); expect(uiData.tree?.children.length).toEqual(94); - presenter.filterHierarchyTree("Wallpaper"); + presenter.filterHierarchyTree('Wallpaper'); // All but four layers should be filtered out expect(uiData.tree?.children.length).toEqual(4); }); - - it("sets properties tree and associated ui data", () => { + it('sets properties tree and associated ui data', () => { presenter.notifyCurrentTraceEntries(entries); presenter.newPropertiesTree(selectedTree); // does not check specific tree values as tree transformation method may change expect(uiData.propertiesTree).toBeTruthy(); }); - it("updates properties tree", () => { + it('updates properties tree', () => { //change flat view to true const userOptions: UserOptions = { showDiff: { - name: "Show diff", - enabled: true + name: 'Show diff', + enabled: true, }, showDefaults: { - name: "Show defaults", + name: 'Show defaults', enabled: true, tooltip: ` If checked, shows the value of all properties. Otherwise, hides all properties whose value is the default for its data type. - ` + `, }, }; @@ -186,19 +196,21 @@ describe("PresenterSurfaceFlinger", () => { expect(uiData.propertiesTree?.diffType).toBeTruthy(); }); - it("filters properties tree", () => { + it('filters properties tree', () => { presenter.notifyCurrentTraceEntries(entries); presenter.newPropertiesTree(selectedTree); - let nonTerminalChildren = uiData.propertiesTree?.children?.filter( - (child: PropertiesTreeNode) => typeof child.propertyKey === "string" - ) ?? []; + let nonTerminalChildren = + uiData.propertiesTree?.children?.filter( + (child: PropertiesTreeNode) => typeof child.propertyKey === 'string' + ) ?? []; expect(nonTerminalChildren.length).toEqual(22); - presenter.filterPropertiesTree("bound"); + presenter.filterPropertiesTree('bound'); - nonTerminalChildren = uiData.propertiesTree?.children?.filter( - (child: PropertiesTreeNode) => typeof child.propertyKey === "string" - ) ?? []; + nonTerminalChildren = + uiData.propertiesTree?.children?.filter( + (child: PropertiesTreeNode) => typeof child.propertyKey === 'string' + ) ?? []; expect(nonTerminalChildren.length).toEqual(3); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts index 45767290a..d6c9ff00f 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { UiData } from "./ui_data"; -import { Rectangle, RectMatrix, RectTransform } from "viewers/common/rectangle"; -import { TraceType } from "common/trace/trace_type"; -import { TreeUtils, FilterType } from "common/utils/tree_utils"; -import { UserOptions } from "viewers/common/user_options"; -import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils"; -import { TreeGenerator } from "viewers/common/tree_generator"; -import { TreeTransformer } from "viewers/common/tree_transformer"; -import { Layer, LayerTraceEntry } from "common/trace/flickerlib/common"; -import { PersistentStoreProxy } from "common/utils/persistent_store_proxy"; +import {Layer, LayerTraceEntry} from 'common/trace/flickerlib/common'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStoreProxy} from 'common/utils/persistent_store_proxy'; +import {FilterType, TreeUtils} from 'common/utils/tree_utils'; +import {Rectangle, RectMatrix, RectTransform} from 'viewers/common/rectangle'; +import {TreeGenerator} from 'viewers/common/tree_generator'; +import {TreeTransformer} from 'viewers/common/tree_transformer'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {UiData} from './ui_data'; type NotifyViewCallbackType = (uiData: UiData) => void; @@ -35,8 +35,8 @@ export class Presenter { public updatePinnedItems(pinnedItem: HierarchyTreeNode) { const pinnedId = `${pinnedItem.id}`; - if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) { - this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId); + if (this.pinnedItems.map((item) => `${item.id}`).includes(pinnedId)) { + this.pinnedItems = this.pinnedItems.filter((pinned) => `${pinned.id}` != pinnedId); } else { this.pinnedItems.push(pinnedItem); } @@ -47,7 +47,7 @@ export class Presenter { public updateHighlightedItems(id: string) { if (this.highlightedItems.includes(id)) { - this.highlightedItems = this.highlightedItems.filter(hl => hl != id); + this.highlightedItems = this.highlightedItems.filter((hl) => hl != id); } else { this.highlightedItems = []; //if multi-select surfaces implemented, remove this line this.highlightedItems.push(id); @@ -104,22 +104,23 @@ export class Presenter { } private generateRects(): Rectangle[] { - const displayRects = this.entry.displays.map((display: any) => { - const rect = display.layerStackSpace; - rect.label = "Display"; - if (display.name) { - rect.label += ` - ${display.name}`; - } - rect.stableId = `Display - ${display.id}`; - rect.displayId = display.layerStackId; - rect.isDisplay = true; - rect.cornerRadius = 0; - rect.isVirtual = display.isVirtual ?? false; - rect.transform = { - matrix: display.transform.matrix - }; - return rect; - }) ?? []; + const displayRects = + this.entry.displays.map((display: any) => { + const rect = display.layerStackSpace; + rect.label = 'Display'; + if (display.name) { + rect.label += ` - ${display.name}`; + } + rect.stableId = `Display - ${display.id}`; + rect.displayId = display.layerStackId; + rect.isDisplay = true; + rect.cornerRadius = 0; + rect.isVirtual = display.isVirtual ?? false; + rect.transform = { + matrix: display.transform.matrix, + }; + return rect; + }) ?? []; this.displayIds = []; const rects = this.getLayersForRectsView() .sort(this.compareLayerZ) @@ -131,7 +132,7 @@ export class Presenter { this.displayIds.push(it.stackId); } rect.transform = { - matrix: rect.transform.matrix + matrix: rect.transform.matrix, }; return rect; }); @@ -139,11 +140,12 @@ export class Presenter { } private getLayersForRectsView(): Layer[] { - const onlyVisible = this.hierarchyUserOptions["onlyVisible"]?.enabled ?? false; + const onlyVisible = this.hierarchyUserOptions['onlyVisible']?.enabled ?? false; // Show only visible layers or Visible + Occluded layers. Don't show all layers // (flattenedLayers) because container layers are never meant to be displayed - return this.entry.flattenedLayers - .filter((it: any) => it.isVisible || (!onlyVisible && it.occludedBy.length > 0)); + return this.entry.flattenedLayers.filter( + (it: any) => it.isVisible || (!onlyVisible && it.occludedBy.length > 0) + ); } private compareLayerZ(a: Layer, b: Layer): number { @@ -159,7 +161,9 @@ export class Presenter { private updateSelectedTreeUiData() { if (this.selectedHierarchyTree) { - this.uiData.propertiesTree = this.getTreeWithTransformedProperties(this.selectedHierarchyTree); + this.uiData.propertiesTree = this.getTreeWithTransformedProperties( + this.selectedHierarchyTree + ); this.uiData.selectedLayer = this.selectedLayer; this.uiData.displayPropertyGroups = this.shouldDisplayPropertyGroups(this.selectedLayer); } @@ -172,15 +176,16 @@ export class Presenter { } const generator = new TreeGenerator(this.entry, this.hierarchyFilter, this.pinnedIds) - .setIsOnlyVisibleView(this.hierarchyUserOptions["onlyVisible"]?.enabled) - .setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled) - .setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled) + .setIsOnlyVisibleView(this.hierarchyUserOptions['onlyVisible']?.enabled) + .setIsSimplifyNames(this.hierarchyUserOptions['simplifyNames']?.enabled) + .setIsFlatView(this.hierarchyUserOptions['flat']?.enabled) .withUniqueNodeId(); let tree: HierarchyTreeNode | null; - if (!this.hierarchyUserOptions["showDiff"]?.enabled) { + if (!this.hierarchyUserOptions['showDiff']?.enabled) { tree = generator.generateTree(); } else { - tree = generator.compareWith(this.previousEntry) + tree = generator + .compareWith(this.previousEntry) .withModifiedCheck() .generateFinalTreeWithDiff(); } @@ -206,7 +211,7 @@ export class Presenter { dtdx: t.dtdx, dtdy: t.dtdy, tx: t.tx, - ty: t.ty + ty: t.ty, }; transform = { matrix: matrix, @@ -225,7 +230,7 @@ export class Presenter { displayId: rect.displayId ?? rect.ref.stackId, isVirtual: rect.isVirtual ?? false, isClickable: !(rect.isDisplay ?? false), - cornerRadius: rect.cornerRadius + cornerRadius: rect.cornerRadius, }; uiRects.push(newRect); }); @@ -234,7 +239,7 @@ export class Presenter { private updatePinnedIds(newId: string) { if (this.pinnedIds.includes(newId)) { - this.pinnedIds = this.pinnedIds.filter(pinned => pinned != newId); + this.pinnedIds = this.pinnedIds.filter((pinned) => pinned != newId); } else { this.pinnedIds.push(newId); } @@ -243,8 +248,8 @@ export class Presenter { private getTreeWithTransformedProperties(selectedTree: HierarchyTreeNode): PropertiesTreeNode { const transformer = new TreeTransformer(selectedTree, this.propertiesFilter) .setOnlyProtoDump(true) - .setIsShowDefaults(this.propertiesUserOptions["showDefaults"]?.enabled) - .setIsShowDiff(this.propertiesUserOptions["showDiff"]?.enabled) + .setIsShowDefaults(this.propertiesUserOptions['showDefaults']?.enabled) + .setIsShowDiff(this.propertiesUserOptions['showDiff']?.enabled) .setTransformerOptions({skip: selectedTree.skip}) .setProperties(this.entry) .setDiffProperties(this.previousEntry); @@ -269,8 +274,8 @@ export class Presenter { private readonly notifyViewCallback: NotifyViewCallbackType; private uiData: UiData; - private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter(""); - private propertiesFilter: FilterType = TreeUtils.makeNodeFilter(""); + private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter(''); + private propertiesFilter: FilterType = TreeUtils.makeNodeFilter(''); private highlightedItems: Array = []; private displayIds: Array = []; private pinnedItems: Array = []; @@ -279,38 +284,46 @@ export class Presenter { private selectedLayer: LayerTraceEntry | Layer | null = null; private previousEntry: LayerTraceEntry | null = null; private entry: LayerTraceEntry | null = null; - private hierarchyUserOptions: UserOptions = PersistentStoreProxy.new("SfHierarchyOptions", { - showDiff: { - name: "Show diff", // TODO: PersistentStoreObject.Ignored("Show diff") or something like that to instruct to not store this info - enabled: false + private hierarchyUserOptions: UserOptions = PersistentStoreProxy.new( + 'SfHierarchyOptions', + { + showDiff: { + name: 'Show diff', // TODO: PersistentStoreObject.Ignored("Show diff") or something like that to instruct to not store this info + enabled: false, + }, + simplifyNames: { + name: 'Simplify names', + enabled: true, + }, + onlyVisible: { + name: 'Only visible', + enabled: false, + }, + flat: { + name: 'Flat', + enabled: false, + }, }, - simplifyNames: { - name: "Simplify names", - enabled: true - }, - onlyVisible: { - name: "Only visible", - enabled: false - }, - flat: { - name: "Flat", - enabled: false - } - }, this.storage); + this.storage + ); - private propertiesUserOptions: UserOptions = PersistentStoreProxy.new("SfPropertyOptions", { - showDiff: { - name: "Show diff", - enabled: false - }, - showDefaults: { - name: "Show defaults", - enabled: false, - tooltip: ` + private propertiesUserOptions: UserOptions = PersistentStoreProxy.new( + 'SfPropertyOptions', + { + showDiff: { + name: 'Show diff', + enabled: false, + }, + showDefaults: { + name: 'Show defaults', + enabled: false, + tooltip: ` If checked, shows the value of all properties. Otherwise, hides all properties whose value is the default for its data type. - ` + `, + }, }, - }, this.storage); + this.storage + ); } diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts index 18bc9b2b1..e9b68e1ac 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils"; -import { UserOptions } from "viewers/common/user_options"; -import { Layer } from "common/trace/flickerlib/common"; -import { TraceType } from "common/trace/trace_type"; -import { Rectangle } from "viewers/common/rectangle"; +import {Layer} from 'common/trace/flickerlib/common'; +import {TraceType} from 'common/trace/trace_type'; +import {Rectangle} from 'viewers/common/rectangle'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; export class UiData { dependencies: Array; diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.spec.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.spec.ts index a4f86ed55..66c9030c9 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.spec.ts @@ -13,37 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {ViewerSurfaceFlingerComponent} from "./viewer_surface_flinger.component"; -import { HierarchyComponent } from "viewers/components/hierarchy.component"; -import { PropertiesComponent } from "viewers/components/properties.component"; -import { RectsComponent } from "viewers/components/rects/rects.component"; -import { MatIconModule } from "@angular/material/icon"; -import { MatDividerModule } from "@angular/material/divider"; -import { ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core"; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatIconModule} from '@angular/material/icon'; +import {HierarchyComponent} from 'viewers/components/hierarchy.component'; +import {PropertiesComponent} from 'viewers/components/properties.component'; +import {RectsComponent} from 'viewers/components/rects/rects.component'; +import {ViewerSurfaceFlingerComponent} from './viewer_surface_flinger.component'; -describe("ViewerSurfaceFlingerComponent", () => { +describe('ViewerSurfaceFlingerComponent', () => { let fixture: ComponentFixture; let component: ViewerSurfaceFlingerComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - imports: [ - MatIconModule, - MatDividerModule - ], + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + imports: [MatIconModule, MatDividerModule], declarations: [ ViewerSurfaceFlingerComponent, HierarchyComponent, PropertiesComponent, - RectsComponent + RectsComponent, ], - schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -53,22 +47,22 @@ describe("ViewerSurfaceFlingerComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("creates rects view", () => { - const rectsView = htmlElement.querySelector(".rects-view"); + it('creates rects view', () => { + const rectsView = htmlElement.querySelector('.rects-view'); expect(rectsView).toBeTruthy(); }); - it("creates hierarchy view", () => { - const hierarchyView = htmlElement.querySelector(".hierarchy-view"); + it('creates hierarchy view', () => { + const hierarchyView = htmlElement.querySelector('.hierarchy-view'); expect(hierarchyView).toBeTruthy(); }); - it("creates properties view", () => { - const propertiesView = htmlElement.querySelector(".properties-view"); + it('creates properties view', () => { + const propertiesView = htmlElement.querySelector('.properties-view'); expect(propertiesView).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts index 35bc1bd76..390ce3ffc 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts @@ -13,18 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - ChangeDetectionStrategy, - Component, - Input, -} from "@angular/core"; -import { UiData } from "./ui_data"; -import { TRACE_INFO } from "app/trace_info"; -import { TraceType } from "common/trace/trace_type"; -import { PersistentStore } from "common/utils/persistent_store"; +import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import {TRACE_INFO} from 'app/trace_info'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {UiData} from './ui_data'; @Component({ - selector: "viewer-surface-flinger", + selector: 'viewer-surface-flinger', changeDetection: ChangeDetectionStrategy.OnPush, template: `
@@ -33,8 +29,7 @@ import { PersistentStore } from "common/utils/persistent_store"; title="Layers" [rects]="inputData?.rects ?? []" [highlightedItems]="inputData?.highlightedItems ?? []" - [displayIds]="inputData?.displayIds ?? []" - > + [displayIds]="inputData?.displayIds ?? []"> + [userOptions]="inputData?.hierarchyUserOptions ?? {}"> + [isProtoDump]="true">
`, styles: [ ` - .rects-view, .hierarchy-view, .properties-view { + .rects-view, + .hierarchy-view, + .properties-view { flex: 1; padding: 16px; display: flex; @@ -66,7 +61,7 @@ import { PersistentStore } from "common/utils/persistent_store"; overflow: auto; } `, - ] + ], }) export class ViewerSurfaceFlingerComponent { @Input() inputData?: UiData; diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.ts index d605361f6..056a66ddc 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Presenter} from "./presenter"; -import {UiData} from "./ui_data"; -import {TraceType} from "common/trace/trace_type"; -import {View, Viewer, ViewType} from "viewers/viewer"; -import {ViewerEvents} from "viewers/common/viewer_events"; +import {TraceType} from 'common/trace/trace_type'; +import {ViewerEvents} from 'viewers/common/viewer_events'; +import {View, Viewer, ViewType} from 'viewers/viewer'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; class ViewerSurfaceFlinger implements Viewer { public static readonly DEPENDENCIES: TraceType[] = [TraceType.SURFACE_FLINGER]; @@ -25,19 +25,33 @@ class ViewerSurfaceFlinger implements Viewer { private presenter: Presenter; constructor(storage: Storage) { - this.htmlElement = document.createElement("viewer-surface-flinger"); + this.htmlElement = document.createElement('viewer-surface-flinger'); this.presenter = new Presenter((uiData: UiData) => { (this.htmlElement as any).inputData = uiData; }, storage); - this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => this.presenter.updatePinnedItems(((event as CustomEvent).detail.pinnedItem))); - this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`)); - this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions)); - this.htmlElement.addEventListener(ViewerEvents.HierarchyFilterChange, (event) => this.presenter.filterHierarchyTree((event as CustomEvent).detail.filterString)); - this.htmlElement.addEventListener(ViewerEvents.PropertiesUserOptionsChange, (event) => this.presenter.updatePropertiesTree((event as CustomEvent).detail.userOptions)); - this.htmlElement.addEventListener(ViewerEvents.PropertiesFilterChange, (event) => this.presenter.filterPropertiesTree((event as CustomEvent).detail.filterString)); - this.htmlElement.addEventListener(ViewerEvents.SelectedTreeChange, (event) => this.presenter.newPropertiesTree((event as CustomEvent).detail.selectedItem)); + this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => + this.presenter.updatePinnedItems((event as CustomEvent).detail.pinnedItem) + ); + this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => + this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`) + ); + this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => + this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions) + ); + this.htmlElement.addEventListener(ViewerEvents.HierarchyFilterChange, (event) => + this.presenter.filterHierarchyTree((event as CustomEvent).detail.filterString) + ); + this.htmlElement.addEventListener(ViewerEvents.PropertiesUserOptionsChange, (event) => + this.presenter.updatePropertiesTree((event as CustomEvent).detail.userOptions) + ); + this.htmlElement.addEventListener(ViewerEvents.PropertiesFilterChange, (event) => + this.presenter.filterPropertiesTree((event as CustomEvent).detail.filterString) + ); + this.htmlElement.addEventListener(ViewerEvents.SelectedTreeChange, (event) => + this.presenter.newPropertiesTree((event as CustomEvent).detail.selectedItem) + ); } public notifyCurrentTraceEntries(entries: Map): void { @@ -45,7 +59,7 @@ class ViewerSurfaceFlinger implements Viewer { } public getViews(): View[] { - return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, "Surface Flinger")]; + return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, 'Surface Flinger')]; } public getDependencies(): TraceType[] { diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/events.ts b/tools/winscope-ng/src/viewers/viewer_transactions/events.ts index c55529264..8161fe56b 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/events.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/events.ts @@ -15,13 +15,13 @@ */ class Events { - public static VSyncIdFilterChanged = "ViewerTransactionsEvent_VSyncIdFilterChanged"; - public static PidFilterChanged = "ViewerTransactionsEvent_PidFilterChanged"; - public static UidFilterChanged = "ViewerTransactionsEvent_UidFilterChanged"; - public static TypeFilterChanged = "ViewerTransactionsEvent_TypeFilterChanged"; - public static IdFilterChanged = "ViewerTransactionsEvent_IdFilterChanged"; - public static WhatSearchStringChanged = "ViewerTransactionsEvent_WhatSearchStringChanged"; - public static EntryClicked = "ViewerTransactionsEvent_EntryClicked"; + public static VSyncIdFilterChanged = 'ViewerTransactionsEvent_VSyncIdFilterChanged'; + public static PidFilterChanged = 'ViewerTransactionsEvent_PidFilterChanged'; + public static UidFilterChanged = 'ViewerTransactionsEvent_UidFilterChanged'; + public static TypeFilterChanged = 'ViewerTransactionsEvent_TypeFilterChanged'; + public static IdFilterChanged = 'ViewerTransactionsEvent_IdFilterChanged'; + public static WhatSearchStringChanged = 'ViewerTransactionsEvent_WhatSearchStringChanged'; + public static EntryClicked = 'ViewerTransactionsEvent_EntryClicked'; } export {Events}; diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/presenter.spec.ts b/tools/winscope-ng/src/viewers/viewer_transactions/presenter.spec.ts index 25f528472..ccdb969d4 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/presenter.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/presenter.spec.ts @@ -13,26 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {TraceType} from "common/trace/trace_type"; -import {Parser} from "parsers/parser"; -import {Presenter} from "./presenter"; -import {UnitTestUtils} from "test/unit/utils"; -import {UiData, UiDataEntryType} from "./ui_data"; -import {TransactionsTraceEntry} from "../../common/trace/transactions"; +import {Timestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {Parser} from 'parsers/parser'; +import {UnitTestUtils} from 'test/unit/utils'; +import {TransactionsTraceEntry} from '../../common/trace/transactions'; +import {Presenter} from './presenter'; +import {UiData, UiDataEntryType} from './ui_data'; -describe("ViewerTransactionsPresenter", () => { +describe('ViewerTransactionsPresenter', () => { let parser: Parser; let presenter: Presenter; let inputTraceEntryElapsed: TransactionsTraceEntry; let inputTraceEntriesElapsed: Map; let inputTraceEntryReal: TransactionsTraceEntry; let inputTraceEntriesReal: Map; - let outputUiData: undefined|UiData; + let outputUiData: undefined | UiData; const TOTAL_OUTPUT_ENTRIES = 1504; beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/Transactions.pb"); + parser = await UnitTestUtils.getParser('traces/elapsed_and_real_timestamp/Transactions.pb'); }); beforeEach(() => { @@ -53,18 +53,33 @@ describe("ViewerTransactionsPresenter", () => { }); }); - it("is robust to undefined trace entry", () => { + it('is robust to undefined trace entry', () => { inputTraceEntriesElapsed = new Map(); presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData).toEqual(UiData.EMPTY); }); - it("processes trace entry and computes output UI data", () => { + it('processes trace entry and computes output UI data', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); - expect(outputUiData!.allPids).toEqual(["N/A", "0", "515", "1593", "2022", "2322", "2463", "3300"]); - expect(outputUiData!.allUids).toEqual(["N/A", "1000", "1003", "10169", "10235", "10239"]); - expect(outputUiData!.allTypes).toEqual(["DISPLAY_CHANGED", "LAYER_ADDED", "LAYER_CHANGED", "LAYER_HANDLE_REMOVED", "LAYER_REMOVED"]); + expect(outputUiData!.allPids).toEqual([ + 'N/A', + '0', + '515', + '1593', + '2022', + '2322', + '2463', + '3300', + ]); + expect(outputUiData!.allUids).toEqual(['N/A', '1000', '1003', '10169', '10235', '10239']); + expect(outputUiData!.allTypes).toEqual([ + 'DISPLAY_CHANGED', + 'LAYER_ADDED', + 'LAYER_CHANGED', + 'LAYER_HANDLE_REMOVED', + 'LAYER_REMOVED', + ]); expect(outputUiData!.allIds.length).toEqual(115); expect(outputUiData!.entries.length).toEqual(TOTAL_OUTPUT_ENTRIES); @@ -83,178 +98,184 @@ describe("ViewerTransactionsPresenter", () => { expect(outputUiData!.entries.length).toEqual(TOTAL_OUTPUT_ENTRIES); }); - it("processes trace entry and updates current entry and scroll position", () => { + it('processes trace entry and updates current entry and scroll position', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData!.currentEntryIndex).toEqual(0); expect(outputUiData!.scrollToIndex).toEqual(0); - (inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0]).currentEntryIndex = 10; + (( + inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0] + )).currentEntryIndex = 10; presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData!.currentEntryIndex).toEqual(13); expect(outputUiData!.scrollToIndex).toEqual(13); }); - it("filters entries according to VSYNC ID filter", () => { + it('filters entries according to VSYNC ID filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); presenter.onVSyncIdFilterChanged([]); - expect(outputUiData!.entries.length) - .toEqual(TOTAL_OUTPUT_ENTRIES); + expect(outputUiData!.entries.length).toEqual(TOTAL_OUTPUT_ENTRIES); - presenter.onVSyncIdFilterChanged(["1"]); - expect(new Set(outputUiData!.entries.map(entry => entry.vsyncId))) - .toEqual(new Set([1])); + presenter.onVSyncIdFilterChanged(['1']); + expect(new Set(outputUiData!.entries.map((entry) => entry.vsyncId))).toEqual(new Set([1])); - presenter.onVSyncIdFilterChanged(["1", "3", "10"]); - expect(new Set(outputUiData!.entries.map(entry => entry.vsyncId))) - .toEqual(new Set([1, 3, 10])); + presenter.onVSyncIdFilterChanged(['1', '3', '10']); + expect(new Set(outputUiData!.entries.map((entry) => entry.vsyncId))).toEqual( + new Set([1, 3, 10]) + ); }); - it("filters entries according to PID filter", () => { + it('filters entries according to PID filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); presenter.onPidFilterChanged([]); - expect(new Set(outputUiData!.entries.map(entry => entry.pid))) - .toEqual(new Set(["N/A", "0", "515", "1593", "2022", "2322", "2463", "3300"])); + expect(new Set(outputUiData!.entries.map((entry) => entry.pid))).toEqual( + new Set(['N/A', '0', '515', '1593', '2022', '2322', '2463', '3300']) + ); - presenter.onPidFilterChanged(["0"]); - expect(new Set(outputUiData!.entries.map(entry => entry.pid))) - .toEqual(new Set(["0"])); + presenter.onPidFilterChanged(['0']); + expect(new Set(outputUiData!.entries.map((entry) => entry.pid))).toEqual(new Set(['0'])); - presenter.onPidFilterChanged(["0", "515"]); - expect(new Set(outputUiData!.entries.map(entry => entry.pid))) - .toEqual(new Set(["0", "515"])); + presenter.onPidFilterChanged(['0', '515']); + expect(new Set(outputUiData!.entries.map((entry) => entry.pid))).toEqual(new Set(['0', '515'])); }); - it("filters entries according to UID filter", () => { + it('filters entries according to UID filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); presenter.onUidFilterChanged([]); - expect(new Set(outputUiData!.entries.map(entry => entry.uid))) - .toEqual(new Set(["N/A", "1000", "1003", "10169", "10235", "10239"])); + expect(new Set(outputUiData!.entries.map((entry) => entry.uid))).toEqual( + new Set(['N/A', '1000', '1003', '10169', '10235', '10239']) + ); - presenter.onUidFilterChanged(["1000"]); - expect(new Set(outputUiData!.entries.map(entry => entry.uid))) - .toEqual(new Set(["1000"])); + presenter.onUidFilterChanged(['1000']); + expect(new Set(outputUiData!.entries.map((entry) => entry.uid))).toEqual(new Set(['1000'])); - presenter.onUidFilterChanged(["1000", "1003"]); - expect(new Set(outputUiData!.entries.map(entry => entry.uid))) - .toEqual(new Set(["1000", "1003"])); + presenter.onUidFilterChanged(['1000', '1003']); + expect(new Set(outputUiData!.entries.map((entry) => entry.uid))).toEqual( + new Set(['1000', '1003']) + ); }); - it("filters entries according to type filter", () => { + it('filters entries according to type filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); presenter.onTypeFilterChanged([]); - expect(new Set(outputUiData!.entries.map(entry => entry.type))) - .toEqual(new Set([ + expect(new Set(outputUiData!.entries.map((entry) => entry.type))).toEqual( + new Set([ UiDataEntryType.DisplayChanged, UiDataEntryType.LayerAdded, UiDataEntryType.LayerChanged, UiDataEntryType.LayerRemoved, - UiDataEntryType.LayerHandleRemoved - ])); + UiDataEntryType.LayerHandleRemoved, + ]) + ); presenter.onTypeFilterChanged([UiDataEntryType.LayerAdded]); - expect(new Set(outputUiData!.entries.map(entry => entry.type))) - .toEqual(new Set([UiDataEntryType.LayerAdded])); + expect(new Set(outputUiData!.entries.map((entry) => entry.type))).toEqual( + new Set([UiDataEntryType.LayerAdded]) + ); presenter.onTypeFilterChanged([UiDataEntryType.LayerAdded, UiDataEntryType.LayerRemoved]); - expect(new Set(outputUiData!.entries.map(entry => entry.type))) - .toEqual(new Set([UiDataEntryType.LayerAdded, UiDataEntryType.LayerRemoved])); + expect(new Set(outputUiData!.entries.map((entry) => entry.type))).toEqual( + new Set([UiDataEntryType.LayerAdded, UiDataEntryType.LayerRemoved]) + ); }); - it("filters entries according to ID filter", () => { + it('filters entries according to ID filter', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); presenter.onIdFilterChanged([]); - expect(new Set(outputUiData!.entries.map(entry => entry.id)).size) - .toBeGreaterThan(20); + expect(new Set(outputUiData!.entries.map((entry) => entry.id)).size).toBeGreaterThan(20); - presenter.onIdFilterChanged(["1"]); - expect(new Set(outputUiData!.entries.map(entry => entry.id))) - .toEqual(new Set(["1"])); + presenter.onIdFilterChanged(['1']); + expect(new Set(outputUiData!.entries.map((entry) => entry.id))).toEqual(new Set(['1'])); - presenter.onIdFilterChanged(["1", "3"]); - expect(new Set(outputUiData!.entries.map(entry => entry.id))) - .toEqual(new Set(["1", "3"])); + presenter.onIdFilterChanged(['1', '3']); + expect(new Set(outputUiData!.entries.map((entry) => entry.id))).toEqual(new Set(['1', '3'])); }); - it("filters entries according to \"what\" search string", () => { + it('filters entries according to "what" search string', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData!.entries.length).toEqual(TOTAL_OUTPUT_ENTRIES); - presenter.onWhatSearchStringChanged(""); + presenter.onWhatSearchStringChanged(''); expect(outputUiData!.entries.length).toEqual(TOTAL_OUTPUT_ENTRIES); - presenter.onWhatSearchStringChanged("Crop"); + presenter.onWhatSearchStringChanged('Crop'); expect(outputUiData!.entries.length).toBeLessThan(TOTAL_OUTPUT_ENTRIES); - presenter.onWhatSearchStringChanged("STRING_WITH_NO_MATCHES"); + presenter.onWhatSearchStringChanged('STRING_WITH_NO_MATCHES'); expect(outputUiData!.entries.length).toEqual(0); }); - it ("updates selected entry and properties tree when entry is clicked", () => { + it('updates selected entry and properties tree when entry is clicked', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData!.currentEntryIndex).toEqual(0); expect(outputUiData!.selectedEntryIndex).toBeUndefined(); expect(outputUiData!.scrollToIndex).toEqual(0); - expect(outputUiData!.currentPropertiesTree) - .toEqual(outputUiData!.entries[0].propertiesTree); + expect(outputUiData!.currentPropertiesTree).toEqual(outputUiData!.entries[0].propertiesTree); presenter.onEntryClicked(10); expect(outputUiData!.currentEntryIndex).toEqual(0); expect(outputUiData!.selectedEntryIndex).toEqual(10); expect(outputUiData!.scrollToIndex).toBeUndefined(); // no scrolling - expect(outputUiData!.currentPropertiesTree) - .toEqual(outputUiData!.entries[10].propertiesTree); + expect(outputUiData!.currentPropertiesTree).toEqual(outputUiData!.entries[10].propertiesTree); // remove selection when selected entry is clicked again presenter.onEntryClicked(10); expect(outputUiData!.currentEntryIndex).toEqual(0); expect(outputUiData!.selectedEntryIndex).toBeUndefined(); expect(outputUiData!.scrollToIndex).toBeUndefined(); // no scrolling - expect(outputUiData!.currentPropertiesTree) - .toEqual(outputUiData!.entries[0].propertiesTree); + expect(outputUiData!.currentPropertiesTree).toEqual(outputUiData!.entries[0].propertiesTree); }); - it("computes current entry index", () => { + it('computes current entry index', () => { presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData!.currentEntryIndex).toEqual(0); - (inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0]).currentEntryIndex = 10; + (( + inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0] + )).currentEntryIndex = 10; presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); expect(outputUiData!.currentEntryIndex).toEqual(13); }); - it("updates current entry index when filters change", () => { - (inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0]).currentEntryIndex = 10; + it('updates current entry index when filters change', () => { + (( + inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0] + )).currentEntryIndex = 10; presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); presenter.onPidFilterChanged([]); expect(outputUiData!.currentEntryIndex).toEqual(13); - presenter.onPidFilterChanged(["0"]); + presenter.onPidFilterChanged(['0']); expect(outputUiData!.currentEntryIndex).toEqual(10); - presenter.onPidFilterChanged(["0", "515"]); + presenter.onPidFilterChanged(['0', '515']); expect(outputUiData!.currentEntryIndex).toEqual(11); - presenter.onPidFilterChanged(["0", "515", "N/A"]); + presenter.onPidFilterChanged(['0', '515', 'N/A']); expect(outputUiData!.currentEntryIndex).toEqual(13); }); - it("formats real time", () => { - (inputTraceEntriesReal.get(TraceType.TRANSACTIONS)[0]).currentEntryIndex = 10; + it('formats real time', () => { + (( + inputTraceEntriesReal.get(TraceType.TRANSACTIONS)[0] + )).currentEntryIndex = 10; presenter.notifyCurrentTraceEntries(inputTraceEntriesReal); - expect(outputUiData!.entries[0].time).toEqual("2022-08-03T06:19:01.051480997"); + expect(outputUiData!.entries[0].time).toEqual('2022-08-03T06:19:01.051480997'); }); - it("formats elapsed time", () => { - (inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0]).currentEntryIndex = 10; + it('formats elapsed time', () => { + (( + inputTraceEntriesElapsed.get(TraceType.TRANSACTIONS)[0] + )).currentEntryIndex = 10; presenter.notifyCurrentTraceEntries(inputTraceEntriesElapsed); - expect(outputUiData!.entries[0].time).toEqual("2s450ms981445ns"); + expect(outputUiData!.entries[0].time).toEqual('2s450ms981445ns'); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/presenter.ts b/tools/winscope-ng/src/viewers/viewer_transactions/presenter.ts index 8fe35261f..aa30a534e 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/presenter.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/presenter.ts @@ -13,28 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {UiData, UiDataEntry, UiDataEntryType} from "./ui_data"; -import {ArrayUtils} from "common/utils/array_utils"; -import {TraceType} from "common/trace/trace_type"; -import {TransactionsTraceEntry} from "common/trace/transactions"; -import {PropertiesTreeGenerator} from "viewers/common/properties_tree_generator"; -import {PropertiesTreeNode} from "viewers/common/ui_tree_utils"; -import {TimeUtils} from "common/utils/time_utils"; -import { ElapsedTimestamp, RealTimestamp, TimestampType } from "common/trace/timestamp"; -import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter"; +import ObjectFormatter from 'common/trace/flickerlib/ObjectFormatter'; +import {ElapsedTimestamp, RealTimestamp, TimestampType} from 'common/trace/timestamp'; +import {TraceType} from 'common/trace/trace_type'; +import {TransactionsTraceEntry} from 'common/trace/transactions'; +import {ArrayUtils} from 'common/utils/array_utils'; +import {TimeUtils} from 'common/utils/time_utils'; +import {PropertiesTreeGenerator} from 'viewers/common/properties_tree_generator'; +import {PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UiData, UiDataEntry, UiDataEntryType} from './ui_data'; export class Presenter { private entry?: TransactionsTraceEntry; private originalIndicesOfUiDataEntries: number[]; private uiData: UiData; private readonly notifyUiDataCallback: (data: UiData) => void; - private static readonly VALUE_NA = "N/A"; + private static readonly VALUE_NA = 'N/A'; private vsyncIdFilter: string[] = []; private pidFilter: string[] = []; private uidFilter: string[] = []; private typeFilter: string[] = []; private idFilter: string[] = []; - private whatSearchString = ""; + private whatSearchString = ''; constructor(notifyUiDataCallback: (data: UiData) => void) { this.notifyUiDataCallback = notifyUiDataCallback; @@ -45,11 +45,12 @@ export class Presenter { //TODO: replace input with something like iterator/cursor (same for other viewers/presenters) public notifyCurrentTraceEntries(entries: Map): void { - this.entry = entries.get(TraceType.TRANSACTIONS) ? entries.get(TraceType.TRANSACTIONS)[0] : undefined; + this.entry = entries.get(TraceType.TRANSACTIONS) + ? entries.get(TraceType.TRANSACTIONS)[0] + : undefined; if (this.uiData === UiData.EMPTY) { this.computeUiData(); - } - else { + } else { // update only "position" data this.uiData.currentEntryIndex = this.computeCurrentEntryIndex(); this.uiData.selectedEntryIndex = undefined; @@ -57,7 +58,8 @@ export class Presenter { this.uiData.currentPropertiesTree = this.computeCurrentPropertiesTree( this.uiData.entries, this.uiData.currentEntryIndex, - this.uiData.selectedEntryIndex); + this.uiData.selectedEntryIndex + ); } this.notifyUiDataCallback(this.uiData); } @@ -101,8 +103,7 @@ export class Presenter { public onEntryClicked(index: number) { if (this.uiData.selectedEntryIndex === index) { this.uiData.selectedEntryIndex = undefined; // remove selection when clicked again - } - else { + } else { this.uiData.selectedEntryIndex = index; } @@ -111,7 +112,8 @@ export class Presenter { this.uiData.currentPropertiesTree = this.computeCurrentPropertiesTree( this.uiData.entries, this.uiData.currentEntryIndex, - this.uiData.selectedEntryIndex); + this.uiData.selectedEntryIndex + ); this.notifyUiDataCallback(this.uiData); } @@ -123,9 +125,8 @@ export class Presenter { const entries = this.makeUiDataEntries(this.entry!); - const allVSyncIds = this.getUniqueUiDataEntryValues( - entries, - (entry: UiDataEntry) => entry.vsyncId.toString() + const allVSyncIds = this.getUniqueUiDataEntryValues(entries, (entry: UiDataEntry) => + entry.vsyncId.toString() ); const allPids = this.getUniqueUiDataEntryValues(entries, (entry: UiDataEntry) => entry.pid); const allUids = this.getUniqueUiDataEntryValues(entries, (entry: UiDataEntry) => entry.uid); @@ -135,37 +136,40 @@ export class Presenter { let filteredEntries = entries; if (this.vsyncIdFilter.length > 0) { - filteredEntries = - filteredEntries.filter(entry => this.vsyncIdFilter.includes(entry.vsyncId.toString())); + filteredEntries = filteredEntries.filter((entry) => + this.vsyncIdFilter.includes(entry.vsyncId.toString()) + ); } if (this.pidFilter.length > 0) { - filteredEntries = - filteredEntries.filter(entry => this.pidFilter.includes(entry.pid)); + filteredEntries = filteredEntries.filter((entry) => this.pidFilter.includes(entry.pid)); } if (this.uidFilter.length > 0) { - filteredEntries = - filteredEntries.filter(entry => this.uidFilter.includes(entry.uid)); + filteredEntries = filteredEntries.filter((entry) => this.uidFilter.includes(entry.uid)); } if (this.typeFilter.length > 0) { - filteredEntries = - filteredEntries.filter(entry => this.typeFilter.includes(entry.type)); + filteredEntries = filteredEntries.filter((entry) => this.typeFilter.includes(entry.type)); } if (this.idFilter.length > 0) { - filteredEntries = - filteredEntries.filter(entry => this.idFilter.includes(entry.id)); + filteredEntries = filteredEntries.filter((entry) => this.idFilter.includes(entry.id)); } - filteredEntries = filteredEntries.filter(entry => entry.what.includes(this.whatSearchString)); + filteredEntries = filteredEntries.filter((entry) => entry.what.includes(this.whatSearchString)); - this.originalIndicesOfUiDataEntries = filteredEntries.map(entry => entry.originalIndexInTraceEntry); + this.originalIndicesOfUiDataEntries = filteredEntries.map( + (entry) => entry.originalIndexInTraceEntry + ); const currentEntryIndex = this.computeCurrentEntryIndex(); const selectedEntryIndex = undefined; - const currentPropertiesTree = this.computeCurrentPropertiesTree(filteredEntries, currentEntryIndex, selectedEntryIndex); + const currentPropertiesTree = this.computeCurrentPropertiesTree( + filteredEntries, + currentEntryIndex, + selectedEntryIndex + ); this.uiData = new UiData( allVSyncIds, @@ -177,10 +181,11 @@ export class Presenter { currentEntryIndex, selectedEntryIndex, currentEntryIndex, - currentPropertiesTree); + currentPropertiesTree + ); } - private computeCurrentEntryIndex(): undefined|number { + private computeCurrentEntryIndex(): undefined | number { if (!this.entry) { return undefined; } @@ -193,8 +198,9 @@ export class Presenter { private computeCurrentPropertiesTree( entries: UiDataEntry[], - currentEntryIndex: undefined|number, - selectedEntryIndex: undefined|number): undefined|PropertiesTreeNode { + currentEntryIndex: undefined | number, + selectedEntryIndex: undefined | number + ): undefined | PropertiesTreeNode { if (selectedEntryIndex !== undefined) { return entries[selectedEntryIndex].propertiesTree; } @@ -217,102 +223,122 @@ export class Presenter { for (const [originalIndex, entryProto] of entriesProto.entries()) { for (const transactionStateProto of entryProto.transactions) { for (const layerStateProto of transactionStateProto.layerChanges) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - transactionStateProto.pid.toString(), - transactionStateProto.uid.toString(), - UiDataEntryType.LayerChanged, - layerStateProto.layerId.toString(), - layerStateProto.what, - treeGenerator.generate("LayerState", ObjectFormatter.format(layerStateProto)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + transactionStateProto.pid.toString(), + transactionStateProto.uid.toString(), + UiDataEntryType.LayerChanged, + layerStateProto.layerId.toString(), + layerStateProto.what, + treeGenerator.generate('LayerState', ObjectFormatter.format(layerStateProto)) + ) + ); } for (const displayStateProto of transactionStateProto.displayChanges) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - transactionStateProto.pid.toString(), - transactionStateProto.uid.toString(), - UiDataEntryType.DisplayChanged, - displayStateProto.id.toString(), - displayStateProto.what, - treeGenerator.generate("DisplayState", ObjectFormatter.format(displayStateProto)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + transactionStateProto.pid.toString(), + transactionStateProto.uid.toString(), + UiDataEntryType.DisplayChanged, + displayStateProto.id.toString(), + displayStateProto.what, + treeGenerator.generate('DisplayState', ObjectFormatter.format(displayStateProto)) + ) + ); } } for (const layerCreationArgsProto of entryProto.addedLayers) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - Presenter.VALUE_NA, - Presenter.VALUE_NA, - UiDataEntryType.LayerAdded, - layerCreationArgsProto.layerId.toString(), - "", - treeGenerator.generate("LayerCreationArgs", ObjectFormatter.format(layerCreationArgsProto)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + Presenter.VALUE_NA, + Presenter.VALUE_NA, + UiDataEntryType.LayerAdded, + layerCreationArgsProto.layerId.toString(), + '', + treeGenerator.generate( + 'LayerCreationArgs', + ObjectFormatter.format(layerCreationArgsProto) + ) + ) + ); } for (const removedLayerId of entryProto.removedLayers) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - Presenter.VALUE_NA, - Presenter.VALUE_NA, - UiDataEntryType.LayerRemoved, - removedLayerId.toString(), - "", - treeGenerator.generate("RemovedLayerId", ObjectFormatter.format(removedLayerId)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + Presenter.VALUE_NA, + Presenter.VALUE_NA, + UiDataEntryType.LayerRemoved, + removedLayerId.toString(), + '', + treeGenerator.generate('RemovedLayerId', ObjectFormatter.format(removedLayerId)) + ) + ); } for (const displayStateProto of entryProto.addedDisplays) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - Presenter.VALUE_NA, - Presenter.VALUE_NA, - UiDataEntryType.DisplayAdded, - displayStateProto.id.toString(), - displayStateProto.what, - treeGenerator.generate("DisplayState", ObjectFormatter.format(displayStateProto)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + Presenter.VALUE_NA, + Presenter.VALUE_NA, + UiDataEntryType.DisplayAdded, + displayStateProto.id.toString(), + displayStateProto.what, + treeGenerator.generate('DisplayState', ObjectFormatter.format(displayStateProto)) + ) + ); } for (const removedDisplayId of entryProto.removedDisplays) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - Presenter.VALUE_NA, - Presenter.VALUE_NA, - UiDataEntryType.DisplayRemoved, - removedDisplayId.toString(), - "", - treeGenerator.generate("RemovedDisplayId", ObjectFormatter.format(removedDisplayId)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + Presenter.VALUE_NA, + Presenter.VALUE_NA, + UiDataEntryType.DisplayRemoved, + removedDisplayId.toString(), + '', + treeGenerator.generate('RemovedDisplayId', ObjectFormatter.format(removedDisplayId)) + ) + ); } for (const removedLayerHandleId of entryProto.removedLayerHandles) { - entries.push(new UiDataEntry( - originalIndex, - this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), - Number(entryProto.vsyncId), - Presenter.VALUE_NA, - Presenter.VALUE_NA, - UiDataEntryType.LayerHandleRemoved, - removedLayerHandleId.toString(), - "", - treeGenerator.generate("RemovedLayerHandleId", ObjectFormatter.format(removedLayerHandleId)) - )); + entries.push( + new UiDataEntry( + originalIndex, + this.formatTime(entryProto, timestampType, realToElapsedTimeOffsetNs), + Number(entryProto.vsyncId), + Presenter.VALUE_NA, + Presenter.VALUE_NA, + UiDataEntryType.LayerHandleRemoved, + removedLayerHandleId.toString(), + '', + treeGenerator.generate( + 'RemovedLayerHandleId', + ObjectFormatter.format(removedLayerHandleId) + ) + ) + ); } } ObjectFormatter.displayDefaults = formattingOptions; @@ -320,15 +346,24 @@ export class Presenter { return entries; } - private formatTime(entryProto: any, timestampType: TimestampType, realToElapsedTimeOffsetNs: bigint|undefined): string { + private formatTime( + entryProto: any, + timestampType: TimestampType, + realToElapsedTimeOffsetNs: bigint | undefined + ): string { if (timestampType === TimestampType.REAL && realToElapsedTimeOffsetNs !== undefined) { - return TimeUtils.format(new RealTimestamp(BigInt(entryProto.elapsedRealtimeNanos) + realToElapsedTimeOffsetNs)); + return TimeUtils.format( + new RealTimestamp(BigInt(entryProto.elapsedRealtimeNanos) + realToElapsedTimeOffsetNs) + ); } else { return TimeUtils.format(new ElapsedTimestamp(BigInt(entryProto.elapsedRealtimeNanos))); } } - private getUniqueUiDataEntryValues(entries: UiDataEntry[], getValue: (entry: UiDataEntry) => T): T[] { + private getUniqueUiDataEntryValues( + entries: UiDataEntry[], + getValue: (entry: UiDataEntry) => T + ): T[] { const uniqueValues = new Set(); entries.forEach((entry: UiDataEntry) => { uniqueValues.add(getValue(entry)); @@ -342,22 +377,18 @@ export class Presenter { if (aIsNumber && bIsNumber) { return Number(a) - Number(b); - } - else if (aIsNumber) { + } else if (aIsNumber) { return 1; // place number after strings in the result - } - else if (bIsNumber) { + } else if (bIsNumber) { return -1; // place number after strings in the result } // a and b are both strings if (a < b) { return -1; - } - else if (a > b) { + } else if (a > b) { return 1; - } - else { + } else { return 0; } }); diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/ui_data.ts b/tools/winscope-ng/src/viewers/viewer_transactions/ui_data.ts index 56679c270..14d19e0b5 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/ui_data.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/ui_data.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {PropertiesTreeNode} from "viewers/common/ui_tree_utils"; +import {PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; class UiData { constructor( @@ -23,11 +23,11 @@ class UiData { public allTypes: string[], public allIds: string[], public entries: UiDataEntry[], - public currentEntryIndex: undefined|number, - public selectedEntryIndex: undefined|number, - public scrollToIndex: undefined|number, - public currentPropertiesTree: undefined|PropertiesTreeNode) { - } + public currentEntryIndex: undefined | number, + public selectedEntryIndex: undefined | number, + public scrollToIndex: undefined | number, + public currentPropertiesTree: undefined | PropertiesTreeNode + ) {} public static EMPTY = new UiData( [], @@ -39,7 +39,8 @@ class UiData { undefined, undefined, undefined, - undefined); + undefined + ); } class UiDataEntry { @@ -53,18 +54,17 @@ class UiDataEntry { public id: string, public what: string, public propertiesTree?: PropertiesTreeNode - ) { - } + ) {} } class UiDataEntryType { - public static DisplayAdded = "DISPLAY_ADDED"; - public static DisplayRemoved = "DISPLAY_REMOVED"; - public static DisplayChanged = "DISPLAY_CHANGED"; - public static LayerAdded = "LAYER_ADDED"; - public static LayerRemoved = "LAYER_REMOVED"; - public static LayerChanged = "LAYER_CHANGED"; - public static LayerHandleRemoved = "LAYER_HANDLE_REMOVED"; + public static DisplayAdded = 'DISPLAY_ADDED'; + public static DisplayRemoved = 'DISPLAY_REMOVED'; + public static DisplayChanged = 'DISPLAY_CHANGED'; + public static LayerAdded = 'LAYER_ADDED'; + public static LayerRemoved = 'LAYER_REMOVED'; + public static LayerChanged = 'LAYER_CHANGED'; + public static LayerHandleRemoved = 'LAYER_HANDLE_REMOVED'; } export {UiData, UiDataEntry, UiDataEntryType}; diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.spec.ts b/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.spec.ts index 789b595a7..65eb3f9eb 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.spec.ts @@ -13,32 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ScrollingModule} from "@angular/cdk/scrolling"; -import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core"; -import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from "@angular/core/testing"; -import {MatDividerModule} from "@angular/material/divider"; -import {UiData, UiDataEntry} from "./ui_data"; -import {PropertiesTreeGenerator} from "viewers/common/properties_tree_generator"; -import {ViewerTransactionsComponent} from "./viewer_transactions.component"; +import {ScrollingModule} from '@angular/cdk/scrolling'; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatDividerModule} from '@angular/material/divider'; +import {PropertiesTreeGenerator} from 'viewers/common/properties_tree_generator'; +import {UiData, UiDataEntry} from './ui_data'; +import {ViewerTransactionsComponent} from './viewer_transactions.component'; -describe("ViewerTransactionsComponent", () => { +describe('ViewerTransactionsComponent', () => { let fixture: ComponentFixture; let component: ViewerTransactionsComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - imports: [ - MatDividerModule, - ScrollingModule - ], - declarations: [ - ViewerTransactionsComponent, - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + imports: [MatDividerModule, ScrollingModule], + declarations: [ViewerTransactionsComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], }).compileComponents(); fixture = TestBed.createComponent(ViewerTransactionsComponent); @@ -49,59 +42,50 @@ describe("ViewerTransactionsComponent", () => { fixture.detectChanges(); }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("renders filters", () => { - expect(htmlElement.querySelector(".entries .filters .pid")).toBeTruthy(); - expect(htmlElement.querySelector(".entries .filters .uid")).toBeTruthy(); - expect(htmlElement.querySelector(".entries .filters .type")).toBeTruthy(); - expect(htmlElement.querySelector(".entries .filters .id")).toBeTruthy(); + it('renders filters', () => { + expect(htmlElement.querySelector('.entries .filters .pid')).toBeTruthy(); + expect(htmlElement.querySelector('.entries .filters .uid')).toBeTruthy(); + expect(htmlElement.querySelector('.entries .filters .type')).toBeTruthy(); + expect(htmlElement.querySelector('.entries .filters .id')).toBeTruthy(); }); - it("renders entries", () => { - expect(htmlElement.querySelector(".scroll")).toBeTruthy(); + it('renders entries', () => { + expect(htmlElement.querySelector('.scroll')).toBeTruthy(); - const entry = htmlElement.querySelector(".scroll .entry"); + const entry = htmlElement.querySelector('.scroll .entry'); expect(entry).toBeTruthy(); - expect(entry!.innerHTML).toContain("TIME_VALUE"); - expect(entry!.innerHTML).toContain("-111"); - expect(entry!.innerHTML).toContain("PID_VALUE"); - expect(entry!.innerHTML).toContain("UID_VALUE"); - expect(entry!.innerHTML).toContain("TYPE_VALUE"); - expect(entry!.innerHTML).toContain("ID_VALUE"); - expect(entry!.innerHTML).toContain("flag1 | flag2 | ..."); + expect(entry!.innerHTML).toContain('TIME_VALUE'); + expect(entry!.innerHTML).toContain('-111'); + expect(entry!.innerHTML).toContain('PID_VALUE'); + expect(entry!.innerHTML).toContain('UID_VALUE'); + expect(entry!.innerHTML).toContain('TYPE_VALUE'); + expect(entry!.innerHTML).toContain('ID_VALUE'); + expect(entry!.innerHTML).toContain('flag1 | flag2 | ...'); }); - it("renders properties", () => { - expect(htmlElement.querySelector((".properties-tree"))).toBeTruthy(); + it('renders properties', () => { + expect(htmlElement.querySelector('.properties-tree')).toBeTruthy(); }); }); async function makeUiData(): Promise { - const propertiesTree = new PropertiesTreeGenerator().generate("ROOT", {"KEY": "VALUE"}); + const propertiesTree = new PropertiesTreeGenerator().generate('ROOT', {KEY: 'VALUE'}); const entry = new UiDataEntry( 0, - "TIME_VALUE", + 'TIME_VALUE', -111, - "PID_VALUE", - "UID_VALUE", - "TYPE_VALUE", - "ID_VALUE", - "flag1 | flag2 | ...", - propertiesTree); + 'PID_VALUE', + 'UID_VALUE', + 'TYPE_VALUE', + 'ID_VALUE', + 'flag1 | flag2 | ...', + propertiesTree + ); - return new UiData( - [], - [], - [], - [], - [], - [entry], - 0, - 0, - 0, - propertiesTree); + return new UiData([], [], [], [], [], [entry], 0, 0, 0, propertiesTree); } diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.ts b/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.ts index 6e1444714..71ee26514 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.component.ts @@ -13,30 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {CdkVirtualScrollViewport} from "@angular/cdk/scrolling"; -import { - Component, ElementRef, Inject, Input, ViewChild -} from "@angular/core"; -import {MatSelectChange} from "@angular/material/select"; -import {Events} from "./events"; -import {UiData} from "./ui_data"; +import {CdkVirtualScrollViewport} from '@angular/cdk/scrolling'; +import {Component, ElementRef, Inject, Input, ViewChild} from '@angular/core'; +import {MatSelectChange} from '@angular/material/select'; +import {Events} from './events'; +import {UiData} from './ui_data'; @Component({ - selector: "viewer-transactions", + selector: 'viewer-transactions', template: `
-
-
+
VSYNC ID - - - {{vsyncId}} + + + {{ vsyncId }} @@ -44,11 +39,9 @@ import {UiData} from "./ui_data";
PID - - - {{pid}} + + + {{ pid }} @@ -56,11 +49,9 @@ import {UiData} from "./ui_data";
UID - - - {{uid}} + + + {{ uid }} @@ -68,11 +59,9 @@ import {UiData} from "./ui_data";
Type - - - {{type}} + + + {{ type }} @@ -80,11 +69,9 @@ import {UiData} from "./ui_data";
LAYER/DISP ID - - - {{id}} + + + {{ id }} @@ -92,38 +79,38 @@ import {UiData} from "./ui_data";
Search text - +
-
+
- {{entry.time}} + {{ entry.time }}
- {{entry.vsyncId}} + {{ entry.vsyncId }}
- {{entry.pid}} + {{ entry.pid }}
- {{entry.uid}} + {{ entry.uid }}
- {{entry.type}} + {{ entry.type }}
- {{entry.id}} + {{ entry.id }}
- {{entry.what}} + {{ entry.what }}
@@ -134,10 +121,9 @@ import {UiData} from "./ui_data";

Properties - Proto Dump

+ *ngIf="uiData.currentPropertiesTree" + class="properties-tree" + [item]="uiData.currentPropertiesTree">
`, @@ -232,11 +218,11 @@ import {UiData} from "./ui_data"; max-height: 75vh; } `, - ] + ], }) class ViewerTransactionsComponent { public uiData: UiData = UiData.EMPTY; - public whatSearchString = ""; + public whatSearchString = ''; @ViewChild(CdkVirtualScrollViewport) private scrollComponent?: CdkVirtualScrollViewport; private elementRef: ElementRef; @@ -290,12 +276,10 @@ class ViewerTransactionsComponent { } private emitEvent(event: string, data: any) { - const customEvent = new CustomEvent( - event, - { - bubbles: true, - detail: data - }); + const customEvent = new CustomEvent(event, { + bubbles: true, + detail: data, + }); this.elementRef.nativeElement.dispatchEvent(customEvent); } } diff --git a/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.ts b/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.ts index ea85a32d4..917938bc3 100644 --- a/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.ts +++ b/tools/winscope-ng/src/viewers/viewer_transactions/viewer_transactions.ts @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {View, Viewer, ViewType} from "viewers/viewer"; -import {Presenter} from "./presenter"; -import {Events} from "./events"; -import {UiData} from "./ui_data"; +import {TraceType} from 'common/trace/trace_type'; +import {View, Viewer, ViewType} from 'viewers/viewer'; +import {Events} from './events'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; class ViewerTransactions implements Viewer { constructor() { - this.htmlElement = document.createElement("viewer-transactions"); + this.htmlElement = document.createElement('viewer-transactions'); this.presenter = new Presenter((data: UiData) => { (this.htmlElement as any).inputData = data; @@ -61,7 +61,7 @@ class ViewerTransactions implements Viewer { } public getViews(): View[] { - return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, "Transactions")]; + return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, 'Transactions')]; } public getDependencies(): TraceType[] { diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts index c7adf95a8..3a71fca86 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Presenter } from "./presenter"; -import { UiData } from "./ui_data"; -import { UserOptions } from "viewers/common/user_options"; -import { TraceType } from "common/trace/trace_type"; -import { WindowManagerState } from "common/trace/flickerlib/common"; -import { PropertiesTreeNode, HierarchyTreeNode } from "viewers/common/ui_tree_utils"; -import { UnitTestUtils } from "test/unit/utils"; -import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; -import { VISIBLE_CHIP } from "viewers/common/chip"; -import { MockStorage } from "test/unit/mock_storage"; +import {WindowManagerState} from 'common/trace/flickerlib/common'; +import {TraceType} from 'common/trace/trace_type'; +import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder'; +import {MockStorage} from 'test/unit/mock_storage'; +import {UnitTestUtils} from 'test/unit/utils'; +import {VISIBLE_CHIP} from 'viewers/common/chip'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; -describe("PresenterWindowManager", () => { +describe('PresenterWindowManager', () => { let presenter: Presenter; let uiData: UiData; let entries: Map; @@ -34,10 +34,17 @@ describe("PresenterWindowManager", () => { entries = new Map(); const entry: WindowManagerState = await UnitTestUtils.getWindowManagerState(); - selectedTree = new HierarchyTreeBuilder().setName("ScreenDecorOverlayBottom") - .setStableId("WindowState 2088ac1 ScreenDecorOverlayBottom").setKind("WindowState") - .setSimplifyNames(true).setShortName("ScreenDecorOverlayBottom").setLayerId(61) - .setFilteredView(true).setIsVisible(true).setChips([VISIBLE_CHIP]).build(); + selectedTree = new HierarchyTreeBuilder() + .setName('ScreenDecorOverlayBottom') + .setStableId('WindowState 2088ac1 ScreenDecorOverlayBottom') + .setKind('WindowState') + .setSimplifyNames(true) + .setShortName('ScreenDecorOverlayBottom') + .setLayerId(61) + .setFilteredView(true) + .setIsVisible(true) + .setChips([VISIBLE_CHIP]) + .build(); entries.set(TraceType.WINDOW_MANAGER, [entry, null]); }); @@ -48,14 +55,17 @@ describe("PresenterWindowManager", () => { }, new MockStorage()); }); - it("processes current trace entries", () => { + it('processes current trace entries', () => { presenter.notifyCurrentTraceEntries(entries); - const filteredUiDataRectLabels = uiData.rects?.filter(rect => rect.isVisible != undefined) - .map(rect => rect.label); - const hierarchyOpts = uiData.hierarchyUserOptions ? - Object.keys(uiData.hierarchyUserOptions) : null; - const propertyOpts = uiData.propertiesUserOptions ? - Object.keys(uiData.propertiesUserOptions) : null; + const filteredUiDataRectLabels = uiData.rects + ?.filter((rect) => rect.isVisible != undefined) + .map((rect) => rect.label); + const hierarchyOpts = uiData.hierarchyUserOptions + ? Object.keys(uiData.hierarchyUserOptions) + : null; + const propertyOpts = uiData.propertiesUserOptions + ? Object.keys(uiData.propertiesUserOptions) + : null; expect(uiData.highlightedItems?.length).toEqual(0); expect(filteredUiDataRectLabels?.length).toEqual(14); expect(uiData.displayIds).toContain(0); @@ -66,7 +76,7 @@ describe("PresenterWindowManager", () => { expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); - it("handles unavailable trace entry", () => { + it('handles unavailable trace entry', () => { presenter.notifyCurrentTraceEntries(entries); expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); const emptyEntries = new Map(); @@ -74,50 +84,53 @@ describe("PresenterWindowManager", () => { expect(uiData.tree).toBeFalsy(); }); - it("creates input data for rects view", () => { + it('creates input data for rects view', () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.rects.length).toBeGreaterThan(0); expect(uiData.rects[0].topLeft).toEqual({x: 0, y: 2326}); expect(uiData.rects[0].bottomRight).toEqual({x: 1080, y: 2400}); }); - it("updates pinned items", () => { + it('updates pinned items', () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.pinnedItems).toEqual([]); - const pinnedItem = new HierarchyTreeBuilder().setName("FirstPinnedItem") - .setStableId("TestItem 4").setLayerId(4).build(); + const pinnedItem = new HierarchyTreeBuilder() + .setName('FirstPinnedItem') + .setStableId('TestItem 4') + .setLayerId(4) + .build(); presenter.updatePinnedItems(pinnedItem); expect(uiData.pinnedItems).toContain(pinnedItem); }); - it("updates highlighted items", () => { + it('updates highlighted items', () => { expect(uiData.highlightedItems).toEqual([]); - const id = "4"; + const id = '4'; presenter.updateHighlightedItems(id); expect(uiData.highlightedItems).toContain(id); }); - it("updates hierarchy tree", () => { + it('updates hierarchy tree', () => { //change flat view to true const userOptions: UserOptions = { showDiff: { - name: "Show diff", - enabled: false + name: 'Show diff', + enabled: false, }, simplifyNames: { - name: "Simplify names", - enabled: true + name: 'Simplify names', + enabled: true, }, onlyVisible: { - name: "Only visible", - enabled: false + name: 'Only visible', + enabled: false, }, flat: { - name: "Flat", - enabled: true - } + name: 'Flat', + enabled: true, + }, }; presenter.notifyCurrentTraceEntries(entries); @@ -128,56 +141,55 @@ describe("PresenterWindowManager", () => { expect(uiData.tree?.children.length).toEqual(72); }); - it("filters hierarchy tree", () => { + it('filters hierarchy tree', () => { const userOptions: UserOptions = { showDiff: { - name: "Show diff", - enabled: false + name: 'Show diff', + enabled: false, }, simplifyNames: { - name: "Simplify names", - enabled: true + name: 'Simplify names', + enabled: true, }, onlyVisible: { - name: "Only visible", - enabled: false + name: 'Only visible', + enabled: false, }, flat: { - name: "Flat", - enabled: true - } + name: 'Flat', + enabled: true, + }, }; presenter.notifyCurrentTraceEntries(entries); presenter.updateHierarchyTree(userOptions); expect(uiData.tree?.children.length).toEqual(72); - presenter.filterHierarchyTree("ScreenDecor"); + presenter.filterHierarchyTree('ScreenDecor'); // All but two window states should be filtered out expect(uiData.tree?.children.length).toEqual(2); }); - - it("sets properties tree and associated ui data", () => { + it('sets properties tree and associated ui data', () => { presenter.notifyCurrentTraceEntries(entries); presenter.newPropertiesTree(selectedTree); // does not check specific tree values as tree transformation method may change expect(uiData.propertiesTree).toBeTruthy(); }); - it("updates properties tree", () => { + it('updates properties tree', () => { //change flat view to true const userOptions: UserOptions = { showDiff: { - name: "Show diff", - enabled: true + name: 'Show diff', + enabled: true, }, showDefaults: { - name: "Show defaults", + name: 'Show defaults', enabled: true, tooltip: ` If checked, shows the value of all properties. Otherwise, hides all properties whose value is the default for its data type. - ` + `, }, }; @@ -190,20 +202,22 @@ describe("PresenterWindowManager", () => { expect(uiData.propertiesTree?.diffType).toBeTruthy(); }); - it("filters properties tree", () => { + it('filters properties tree', () => { presenter.notifyCurrentTraceEntries(entries); presenter.newPropertiesTree(selectedTree); - let nonTerminalChildren = uiData.propertiesTree?.children?.filter( - (child: PropertiesTreeNode) => typeof child.propertyKey === "string" - ) ?? []; + let nonTerminalChildren = + uiData.propertiesTree?.children?.filter( + (child: PropertiesTreeNode) => typeof child.propertyKey === 'string' + ) ?? []; expect(nonTerminalChildren.length).toEqual(14); - presenter.filterPropertiesTree("visible"); + presenter.filterPropertiesTree('visible'); - nonTerminalChildren = uiData.propertiesTree?.children?.filter( - (child: PropertiesTreeNode) => typeof child.propertyKey === "string" - ) ?? []; + nonTerminalChildren = + uiData.propertiesTree?.children?.filter( + (child: PropertiesTreeNode) => typeof child.propertyKey === 'string' + ) ?? []; expect(nonTerminalChildren.length).toEqual(1); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts index 0bbd2e1fa..19bce92ce 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { UiData } from "./ui_data"; -import { Rectangle, RectMatrix, RectTransform } from "viewers/common/rectangle"; -import { TraceType } from "common/trace/trace_type"; -import { TraceTreeNode } from "common/trace/trace_tree_node"; -import { TreeUtils, FilterType } from "common/utils/tree_utils"; -import { UserOptions } from "viewers/common/user_options"; -import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils"; -import { TreeGenerator } from "viewers/common/tree_generator"; -import { TreeTransformer } from "viewers/common/tree_transformer"; -import DisplayContent from "common/trace/flickerlib/windows/DisplayContent"; -import { PersistentStoreProxy } from "common/utils/persistent_store_proxy"; +import DisplayContent from 'common/trace/flickerlib/windows/DisplayContent'; +import {TraceTreeNode} from 'common/trace/trace_tree_node'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStoreProxy} from 'common/utils/persistent_store_proxy'; +import {FilterType, TreeUtils} from 'common/utils/tree_utils'; +import {Rectangle, RectMatrix, RectTransform} from 'viewers/common/rectangle'; +import {TreeGenerator} from 'viewers/common/tree_generator'; +import {TreeTransformer} from 'viewers/common/tree_transformer'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; +import {UiData} from './ui_data'; type NotifyViewCallbackType = (uiData: UiData) => void; @@ -36,8 +36,8 @@ export class Presenter { public updatePinnedItems(pinnedItem: HierarchyTreeNode) { const pinnedId = `${pinnedItem.id}`; - if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) { - this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId); + if (this.pinnedItems.map((item) => `${item.id}`).includes(pinnedId)) { + this.pinnedItems = this.pinnedItems.filter((pinned) => `${pinned.id}` != pinnedId); } else { this.pinnedItems.push(pinnedItem); } @@ -48,7 +48,7 @@ export class Presenter { public updateHighlightedItems(id: string) { if (this.highlightedItems.includes(id)) { - this.highlightedItems = this.highlightedItems.filter(hl => hl != id); + this.highlightedItems = this.highlightedItems.filter((hl) => hl != id); } else { this.highlightedItems = []; //if multi-select implemented, remove this line this.highlightedItems.push(id); @@ -106,33 +106,37 @@ export class Presenter { } private generateRects(): Rectangle[] { - const displayRects: Rectangle[] = this.entry?.displays?.map((display: DisplayContent) => { - const rect = display.displayRect; - rect.label = `Display - ${display.title}`; - rect.stableId = display.stableId; - rect.displayId = display.id; - rect.isDisplay = true; - rect.isVirtual = false; - return rect; - }) ?? []; - this.displayIds = []; - const rects: Rectangle[] = this.entry?.windowStates - ?.sort((a: any, b: any) => b.computedZ - a.computedZ) - .map((it: any) => { - const rect = it.rect; - rect.id = it.layerId; - rect.displayId = it.displayId; - if (!this.displayIds.includes(it.displayId)) { - this.displayIds.push(it.displayId); - } + const displayRects: Rectangle[] = + this.entry?.displays?.map((display: DisplayContent) => { + const rect = display.displayRect; + rect.label = `Display - ${display.title}`; + rect.stableId = display.stableId; + rect.displayId = display.id; + rect.isDisplay = true; + rect.isVirtual = false; return rect; }) ?? []; + this.displayIds = []; + const rects: Rectangle[] = + this.entry?.windowStates + ?.sort((a: any, b: any) => b.computedZ - a.computedZ) + .map((it: any) => { + const rect = it.rect; + rect.id = it.layerId; + rect.displayId = it.displayId; + if (!this.displayIds.includes(it.displayId)) { + this.displayIds.push(it.displayId); + } + return rect; + }) ?? []; return this.rectsToUiData(rects.concat(displayRects)); } private updateSelectedTreeUiData() { if (this.selectedHierarchyTree) { - this.uiData.propertiesTree = this.getTreeWithTransformedProperties(this.selectedHierarchyTree); + this.uiData.propertiesTree = this.getTreeWithTransformedProperties( + this.selectedHierarchyTree + ); } this.notifyViewCallback(this.uiData); } @@ -143,15 +147,16 @@ export class Presenter { } const generator = new TreeGenerator(this.entry, this.hierarchyFilter, this.pinnedIds) - .setIsOnlyVisibleView(this.hierarchyUserOptions["onlyVisible"]?.enabled) - .setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled) - .setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled) + .setIsOnlyVisibleView(this.hierarchyUserOptions['onlyVisible']?.enabled) + .setIsSimplifyNames(this.hierarchyUserOptions['simplifyNames']?.enabled) + .setIsFlatView(this.hierarchyUserOptions['flat']?.enabled) .withUniqueNodeId(); let tree: HierarchyTreeNode | null; - if (!this.hierarchyUserOptions["showDiff"]?.enabled) { + if (!this.hierarchyUserOptions['showDiff']?.enabled) { tree = generator.generateTree(); } else { - tree = generator.compareWith(this.previousEntry) + tree = generator + .compareWith(this.previousEntry) .withModifiedCheck() .generateFinalTreeWithDiff(); } @@ -168,7 +173,7 @@ export class Presenter { tx: 0, dtdx: 0, dtdy: 1, - ty: 0 + ty: 0, }; rects.forEach((rect: any) => { const transform: RectTransform = { @@ -196,7 +201,7 @@ export class Presenter { private updatePinnedIds(newId: string) { if (this.pinnedIds.includes(newId)) { - this.pinnedIds = this.pinnedIds.filter(pinned => pinned != newId); + this.pinnedIds = this.pinnedIds.filter((pinned) => pinned != newId); } else { this.pinnedIds.push(newId); } @@ -208,8 +213,8 @@ export class Presenter { } const transformer = new TreeTransformer(selectedTree, this.propertiesFilter) .setOnlyProtoDump(true) - .setIsShowDefaults(this.propertiesUserOptions["showDefaults"]?.enabled) - .setIsShowDiff(this.propertiesUserOptions["showDiff"]?.enabled) + .setIsShowDefaults(this.propertiesUserOptions['showDefaults']?.enabled) + .setIsShowDiff(this.propertiesUserOptions['showDiff']?.enabled) .setTransformerOptions({skip: selectedTree.skip}) .setProperties(this.entry) .setDiffProperties(this.previousEntry); @@ -219,8 +224,8 @@ export class Presenter { private readonly notifyViewCallback: NotifyViewCallbackType; private uiData: UiData; - private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter(""); - private propertiesFilter: FilterType = TreeUtils.makeNodeFilter(""); + private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter(''); + private propertiesFilter: FilterType = TreeUtils.makeNodeFilter(''); private highlightedItems: Array = []; private displayIds: Array = []; private pinnedItems: Array = []; @@ -228,37 +233,45 @@ export class Presenter { private selectedHierarchyTree: HierarchyTreeNode | null = null; private previousEntry: TraceTreeNode | null = null; private entry: TraceTreeNode | null = null; - private hierarchyUserOptions: UserOptions = PersistentStoreProxy.new("WmHierarchyOptions", { - showDiff: { - name: "Show diff", - enabled: false + private hierarchyUserOptions: UserOptions = PersistentStoreProxy.new( + 'WmHierarchyOptions', + { + showDiff: { + name: 'Show diff', + enabled: false, + }, + simplifyNames: { + name: 'Simplify names', + enabled: true, + }, + onlyVisible: { + name: 'Only visible', + enabled: false, + }, + flat: { + name: 'Flat', + enabled: false, + }, }, - simplifyNames: { - name: "Simplify names", - enabled: true - }, - onlyVisible: { - name: "Only visible", - enabled: false - }, - flat: { - name: "Flat", - enabled: false - } - }, this.storage); - private propertiesUserOptions: UserOptions = PersistentStoreProxy.new("WmPropertyOptions", { - showDiff: { - name: "Show diff", - enabled: false - }, - showDefaults: { - name: "Show defaults", - enabled: false, - tooltip: ` + this.storage + ); + private propertiesUserOptions: UserOptions = PersistentStoreProxy.new( + 'WmPropertyOptions', + { + showDiff: { + name: 'Show diff', + enabled: false, + }, + showDefaults: { + name: 'Show defaults', + enabled: false, + tooltip: ` If checked, shows the value of all properties. Otherwise, hides all properties whose value is the default for its data type. - ` + `, + }, }, - }, this.storage); + this.storage + ); } diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts index 9bf29c504..bc471a4b6 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils"; -import { UserOptions } from "viewers/common/user_options"; -import { TraceType } from "common/trace/trace_type"; -import { Rectangle } from "viewers/common/rectangle"; +import {TraceType} from 'common/trace/trace_type'; +import {Rectangle} from 'viewers/common/rectangle'; +import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils'; +import {UserOptions} from 'viewers/common/user_options'; export class UiData { dependencies: Array; diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.spec.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.spec.ts index 00ef00232..59f6f8e09 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.spec.ts @@ -13,37 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {ViewerWindowManagerComponent} from "./viewer_window_manager.component"; -import { HierarchyComponent } from "viewers/components/hierarchy.component"; -import { PropertiesComponent } from "viewers/components/properties.component"; -import { RectsComponent } from "viewers/components/rects/rects.component"; -import { MatIconModule } from "@angular/material/icon"; -import { MatDividerModule } from "@angular/material/divider"; -import { ComponentFixtureAutoDetect } from "@angular/core/testing"; -import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core"; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core'; +import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing'; +import {MatDividerModule} from '@angular/material/divider'; +import {MatIconModule} from '@angular/material/icon'; +import {HierarchyComponent} from 'viewers/components/hierarchy.component'; +import {PropertiesComponent} from 'viewers/components/properties.component'; +import {RectsComponent} from 'viewers/components/rects/rects.component'; +import {ViewerWindowManagerComponent} from './viewer_window_manager.component'; -describe("ViewerWindowManagerComponent", () => { +describe('ViewerWindowManagerComponent', () => { let fixture: ComponentFixture; let component: ViewerWindowManagerComponent; let htmlElement: HTMLElement; beforeAll(async () => { await TestBed.configureTestingModule({ - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true } - ], - imports: [ - MatIconModule, - MatDividerModule - ], + providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], + imports: [MatIconModule, MatDividerModule], declarations: [ ViewerWindowManagerComponent, HierarchyComponent, PropertiesComponent, - RectsComponent + RectsComponent, ], - schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], }).compileComponents(); }); @@ -53,22 +47,22 @@ describe("ViewerWindowManagerComponent", () => { htmlElement = fixture.nativeElement; }); - it("can be created", () => { + it('can be created', () => { expect(component).toBeTruthy(); }); - it("creates rects view", () => { - const rectsView = htmlElement.querySelector(".rects-view"); + it('creates rects view', () => { + const rectsView = htmlElement.querySelector('.rects-view'); expect(rectsView).toBeTruthy(); }); - it("creates hierarchy view", () => { - const hierarchyView = htmlElement.querySelector(".hierarchy-view"); + it('creates hierarchy view', () => { + const hierarchyView = htmlElement.querySelector('.hierarchy-view'); expect(hierarchyView).toBeTruthy(); }); - it("creates properties view", () => { - const propertiesView = htmlElement.querySelector(".properties-view"); + it('creates properties view', () => { + const propertiesView = htmlElement.querySelector('.properties-view'); expect(propertiesView).toBeTruthy(); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts index 1869e3760..de694b21a 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts @@ -13,48 +13,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - Component, - Input, -} from "@angular/core"; -import {UiData} from "./ui_data"; -import { TRACE_INFO } from "app/trace_info"; -import { TraceType } from "common/trace/trace_type"; -import { PersistentStore } from "common/utils/persistent_store"; +import {Component, Input} from '@angular/core'; +import {TRACE_INFO} from 'app/trace_info'; +import {TraceType} from 'common/trace/trace_type'; +import {PersistentStore} from 'common/utils/persistent_store'; +import {UiData} from './ui_data'; @Component({ - selector: "viewer-window-manager", + selector: 'viewer-window-manager', template: ` -
- - - - - -
+
+ + + + + +
`, styles: [ ` - .rects-view, .hierarchy-view, .properties-view { + .rects-view, + .hierarchy-view, + .properties-view { flex: 1; padding: 16px; display: flex; @@ -62,7 +58,7 @@ import { PersistentStore } from "common/utils/persistent_store"; overflow: auto; } `, - ] + ], }) export class ViewerWindowManagerComponent { @Input() inputData?: UiData; diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.ts index ef8ca51c3..f8e9a799f 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {TraceType} from "common/trace/trace_type"; -import {Viewer, View, ViewType} from "viewers/viewer"; -import {Presenter} from "./presenter"; -import {UiData} from "./ui_data"; -import { ViewerEvents } from "viewers/common/viewer_events"; -import { MockStorage } from "test/unit/mock_storage"; +import {TraceType} from 'common/trace/trace_type'; +import {MockStorage} from 'test/unit/mock_storage'; +import {ViewerEvents} from 'viewers/common/viewer_events'; +import {View, Viewer, ViewType} from 'viewers/viewer'; +import {Presenter} from './presenter'; +import {UiData} from './ui_data'; class ViewerWindowManager implements Viewer { constructor() { - this.htmlElement = document.createElement("viewer-window-manager"); + this.htmlElement = document.createElement('viewer-window-manager'); this.presenter = new Presenter((uiData: UiData) => { // Angular does not deep watch @Input properties. Clearing inputData to null before repopulating // automatically ensures that the UI will change via the Angular change detection cycle. Without @@ -30,13 +30,27 @@ class ViewerWindowManager implements Viewer { (this.htmlElement as any).inputData = null; (this.htmlElement as any).inputData = uiData; }, new MockStorage()); - this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => this.presenter.updatePinnedItems(((event as CustomEvent).detail.pinnedItem))); - this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`)); - this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions)); - this.htmlElement.addEventListener(ViewerEvents.HierarchyFilterChange, (event) => this.presenter.filterHierarchyTree((event as CustomEvent).detail.filterString)); - this.htmlElement.addEventListener(ViewerEvents.PropertiesUserOptionsChange, (event) => this.presenter.updatePropertiesTree((event as CustomEvent).detail.userOptions)); - this.htmlElement.addEventListener(ViewerEvents.PropertiesFilterChange, (event) => this.presenter.filterPropertiesTree((event as CustomEvent).detail.filterString)); - this.htmlElement.addEventListener(ViewerEvents.SelectedTreeChange, (event) => this.presenter.newPropertiesTree((event as CustomEvent).detail.selectedItem)); + this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => + this.presenter.updatePinnedItems((event as CustomEvent).detail.pinnedItem) + ); + this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => + this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`) + ); + this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => + this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions) + ); + this.htmlElement.addEventListener(ViewerEvents.HierarchyFilterChange, (event) => + this.presenter.filterHierarchyTree((event as CustomEvent).detail.filterString) + ); + this.htmlElement.addEventListener(ViewerEvents.PropertiesUserOptionsChange, (event) => + this.presenter.updatePropertiesTree((event as CustomEvent).detail.userOptions) + ); + this.htmlElement.addEventListener(ViewerEvents.PropertiesFilterChange, (event) => + this.presenter.filterPropertiesTree((event as CustomEvent).detail.filterString) + ); + this.htmlElement.addEventListener(ViewerEvents.SelectedTreeChange, (event) => + this.presenter.newPropertiesTree((event as CustomEvent).detail.selectedItem) + ); } public notifyCurrentTraceEntries(entries: Map): void { @@ -44,7 +58,7 @@ class ViewerWindowManager implements Viewer { } public getViews(): View[] { - return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, "Window Manager")]; + return [new View(ViewType.TAB, this.getDependencies(), this.htmlElement, 'Window Manager')]; } public getDependencies(): TraceType[] { diff --git a/tools/winscope-ng/webpack.config.common.js b/tools/winscope-ng/webpack.config.common.js index 1bfeca7f0..8a3a00c8e 100644 --- a/tools/winscope-ng/webpack.config.common.js +++ b/tools/winscope-ng/webpack.config.common.js @@ -13,53 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const path = require("path"); -const TerserPlugin = require("terser-webpack-plugin"); +const path = require('path'); +const TerserPlugin = require('terser-webpack-plugin'); module.exports = { resolve: { - extensions: [".ts", ".js", ".css"], - modules: [ - "node_modules", - "src", - "kotlin_build", - path.resolve(__dirname, "../../.."), - ] + extensions: ['.ts', '.js', '.css'], + modules: ['node_modules', 'src', 'kotlin_build', path.resolve(__dirname, '../../..')], }, resolveLoader: { - modules: ["node_modules", path.resolve(__dirname, "loaders")], + modules: ['node_modules', path.resolve(__dirname, 'loaders')], }, module: { - rules:[ + rules: [ { test: /\.ts$/, - use: ["ts-loader", "angular2-template-loader"] + use: ['ts-loader', 'angular2-template-loader'], }, { test: /\.html$/, - use: ["html-loader"] + use: ['html-loader'], }, { test: /\.css$/, - use: ["style-loader", "css-loader"] + use: ['style-loader', 'css-loader'], }, { test: /\.s[ac]ss$/i, - use: ["style-loader", "css-loader", "sass-loader"] + use: ['style-loader', 'css-loader', 'sass-loader'], }, { test: /\.proto$/, - loader: "proto-loader", + loader: 'proto-loader', options: { paths: [ - path.resolve(__dirname, "../../.."), - path.resolve(__dirname, "../../../external/protobuf/src"), - ] - } + path.resolve(__dirname, '../../..'), + path.resolve(__dirname, '../../../external/protobuf/src'), + ], + }, }, - ] + ], }, optimization: { diff --git a/tools/winscope-ng/webpack.config.dev.js b/tools/winscope-ng/webpack.config.dev.js index a7c004a84..4b7ab84ef 100644 --- a/tools/winscope-ng/webpack.config.dev.js +++ b/tools/winscope-ng/webpack.config.dev.js @@ -13,28 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const {merge} = require("webpack-merge"); -const configCommon = require("./webpack.config.common"); -const HtmlWebpackPlugin = require("html-webpack-plugin"); +const {merge} = require('webpack-merge'); +const configCommon = require('./webpack.config.common'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); const configDev = { - mode: "development", + mode: 'development', entry: { - polyfills: "./src/polyfills.ts", - styles: [ - "./src/material-theme.scss", - "./src/styles.css" - ], - app: "./src/main.dev.ts" + polyfills: './src/polyfills.ts', + styles: ['./src/material-theme.scss', './src/styles.css'], + app: './src/main.dev.ts', }, - devtool: "source-map", + devtool: 'source-map', plugins: [ new HtmlWebpackPlugin({ - template: "src/index.html", - inject: "body", - inlineSource: ".(css|js)$", - }) - ] + template: 'src/index.html', + inject: 'body', + inlineSource: '.(css|js)$', + }), + ], }; module.exports = merge(configCommon, configDev); diff --git a/tools/winscope-ng/webpack.config.prod.js b/tools/winscope-ng/webpack.config.prod.js index 755387934..eef9d65e4 100644 --- a/tools/winscope-ng/webpack.config.prod.js +++ b/tools/winscope-ng/webpack.config.prod.js @@ -22,12 +22,9 @@ const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin const configProd = { mode: 'production', entry: { - polyfills: "./src/polyfills.ts", - styles: [ - "./src/material-theme.scss", - "./src/styles.css" - ], - app: "./src/main.prod.ts" + polyfills: './src/polyfills.ts', + styles: ['./src/material-theme.scss', './src/styles.css'], + app: './src/main.prod.ts', }, output: { path: path.resolve(__dirname, 'dist/prod'), @@ -45,8 +42,7 @@ const configProd = { vendor: { test: /[\\/]node_modules[\\/]/, name(module) { - const packageName = module.context - .match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]; + const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]; return `npm.${packageName.replace('@', '')}`; }, }, @@ -61,12 +57,12 @@ const configProd = { }, plugins: [ new HtmlWebpackPlugin({ - template: "src/index.html", - inject: "body", - inlineSource: ".(css|js)$", + template: 'src/index.html', + inject: 'body', + inlineSource: '.(css|js)$', }), new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin), - ] + ], }; module.exports = merge(configCommon, configProd); diff --git a/tools/winscope-ng/webpack.config.unit.spec.js b/tools/winscope-ng/webpack.config.unit.spec.js index c38ef0182..6dbf27b66 100644 --- a/tools/winscope-ng/webpack.config.unit.spec.js +++ b/tools/winscope-ng/webpack.config.unit.spec.js @@ -18,27 +18,24 @@ const glob = require('glob'); const config = require('./webpack.config.common'); -config["mode"] = "development"; +config['mode'] = 'development'; -const allTestFiles = [ - ...glob.sync('./src/**/*.spec.js'), - ...glob.sync('./src/**/*.spec.ts') -] +const allTestFiles = [...glob.sync('./src/**/*.spec.js'), ...glob.sync('./src/**/*.spec.ts')]; const unitTestFiles = allTestFiles - .filter(file => !file.match(".*component\\.spec\\.(js|ts)$")) - .filter(file => !file.match(".*e2e.*")) -config["entry"] = { + .filter((file) => !file.match('.*component\\.spec\\.(js|ts)$')) + .filter((file) => !file.match('.*e2e.*')); +config['entry'] = { tests: unitTestFiles, }; -config["output"] = { +config['output'] = { path: path.resolve(__dirname, 'dist/unit.spec'), - filename: 'bundle.js', + filename: 'bundle.js', }; -config["target"] = "node"; -config["node"] = { - __dirname: false -} +config['target'] = 'node'; +config['node'] = { + __dirname: false, +}; module.exports = config;