diff --git a/sdk/platform_source.prop_template b/sdk/platform_source.prop_template index fa996c7e3..34766b781 100644 --- a/sdk/platform_source.prop_template +++ b/sdk/platform_source.prop_template @@ -2,7 +2,7 @@ Pkg.Desc=Android SDK Platform ${PLATFORM_VERSION} Pkg.UserSrc=false Platform.Version=${PLATFORM_VERSION} Platform.CodeName= -Pkg.Revision=1 +Pkg.Revision=2 AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION} AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME} AndroidVersion.ExtensionLevel=${PLATFORM_SDK_EXTENSION_VERSION} diff --git a/tools/winscope/protractor.config.js b/tools/winscope/protractor.config.js index f1fdbe6d8..875c38fae 100644 --- a/tools/winscope/protractor.config.js +++ b/tools/winscope/protractor.config.js @@ -30,7 +30,7 @@ exports.config = { args: ['--headless', '--disable-gpu', '--window-size=1280x1024'], }, }, - chromeDriver: './node_modules/webdriver-manager/selenium/chromedriver_113.0.5672.63', + chromeDriver: './node_modules/webdriver-manager/selenium/chromedriver_114.0.5735.90', allScriptsTimeout: 10000, getPageTimeout: 10000, diff --git a/tools/winscope/src/app/app_module.ts b/tools/winscope/src/app/app_module.ts index ddc8c74a2..93957ad8a 100644 --- a/tools/winscope/src/app/app_module.ts +++ b/tools/winscope/src/app/app_module.ts @@ -58,6 +58,7 @@ import {ViewerScreenRecordingComponent} from 'viewers/viewer_screen_recording/vi import {ViewerSurfaceFlingerComponent} from 'viewers/viewer_surface_flinger/viewer_surface_flinger_component'; import {ViewerTransactionsComponent} from 'viewers/viewer_transactions/viewer_transactions_component'; import {ViewerTransitionsComponent} from 'viewers/viewer_transitions/viewer_transitions_component'; +import {ViewerViewCaptureComponent} from 'viewers/viewer_view_capture/viewer_view_capture_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'; @@ -88,6 +89,7 @@ import {WebAdbComponent} from './components/web_adb_component'; ViewerTransactionsComponent, ViewerScreenRecordingComponent, ViewerTransitionsComponent, + ViewerViewCaptureComponent, CollectTracesComponent, UploadTracesComponent, AdbProxyComponent, diff --git a/tools/winscope/src/app/components/app_component.ts b/tools/winscope/src/app/components/app_component.ts index f249c0c06..deb11129d 100644 --- a/tools/winscope/src/app/components/app_component.ts +++ b/tools/winscope/src/app/components/app_component.ts @@ -32,8 +32,8 @@ import {FileUtils} from 'common/file_utils'; import {PersistentStore} from 'common/persistent_store'; import {CrossToolProtocol} from 'cross_tool/cross_tool_protocol'; import {TraceDataListener} from 'interfaces/trace_data_listener'; -import {LoadedTrace} from 'trace/loaded_trace'; import {Timestamp} from 'trace/timestamp'; +import {Trace} from 'trace/trace'; import {TraceType} from 'trace/trace_type'; import {proxyClient, ProxyState} from 'trace_collection/proxy_client'; import {ViewerInputMethodComponent} from 'viewers/components/viewer_input_method_component'; @@ -43,6 +43,7 @@ import {ViewerScreenRecordingComponent} from 'viewers/viewer_screen_recording/vi import {ViewerSurfaceFlingerComponent} from 'viewers/viewer_surface_flinger/viewer_surface_flinger_component'; import {ViewerTransactionsComponent} from 'viewers/viewer_transactions/viewer_transactions_component'; import {ViewerTransitionsComponent} from 'viewers/viewer_transitions/viewer_transitions_component'; +import {ViewerViewCaptureComponent} from 'viewers/viewer_view_capture/viewer_view_capture_component'; import {ViewerWindowManagerComponent} from 'viewers/viewer_window_manager/viewer_window_manager_component'; import {CollectTracesComponent} from './collect_traces_component'; import {SnackBarOpener} from './snack_bar_opener'; @@ -61,7 +62,7 @@ import {UploadTracesComponent} from './upload_traces_component';
@@ -213,7 +214,7 @@ export class AppComponent implements TraceDataListener { isDarkModeOn!: boolean; dataLoaded = false; activeView?: View; - activeTrace?: LoadedTrace; + activeTrace?: Trace; activeTraceFileInfo = ''; collapsedTimelineHeight = 0; @ViewChild(UploadTracesComponent) uploadTracesComponent?: UploadTracesComponent; @@ -284,6 +285,12 @@ export class AppComponent implements TraceDataListener { createCustomElement(ViewerTransitionsComponent, {injector}) ); } + if (!customElements.get('viewer-view-capture')) { + customElements.define( + 'viewer-view-capture', + createCustomElement(ViewerViewCaptureComponent, {injector}) + ); + } } ngAfterViewInit() { @@ -302,7 +309,7 @@ export class AppComponent implements TraceDataListener { } getLoadedTraceTypes(): TraceType[] { - return this.tracePipeline.getLoadedTraces().map((trace) => trace.type); + return this.tracePipeline.getTraces().mapTrace((trace) => trace.type); } onTraceDataLoaded(viewers: Viewer[]) { @@ -338,11 +345,11 @@ export class AppComponent implements TraceDataListener { document.body.removeChild(a); } - onActiveViewChanged(view: View) { + async onActiveViewChanged(view: View) { this.activeView = view; this.activeTrace = this.getActiveTrace(view); this.activeTraceFileInfo = this.makeActiveTraceFileInfo(view); - this.timelineData.setActiveViewTraceTypes(view.dependencies); + await this.mediator.onWinscopeActiveViewChanged(view); } goToLink(url: string) { @@ -356,13 +363,17 @@ export class AppComponent implements TraceDataListener { return ''; } - return `${trace.descriptors.join(', ')}`; + return `${trace.getDescriptors().join(', ')}`; } - private getActiveTrace(view: View): LoadedTrace | undefined { - return this.tracePipeline - .getLoadedTraces() - .find((trace) => trace.type === view.dependencies[0]); + private getActiveTrace(view: View): Trace | undefined { + let activeTrace: Trace | undefined; + this.tracePipeline.getTraces().forEachTrace((trace) => { + if (trace.type === view.dependencies[0]) { + activeTrace = trace; + } + }); + return activeTrace; } private async makeTraceFilesForDownload(): Promise { diff --git a/tools/winscope/src/app/components/timeline/expanded_timeline_component.ts b/tools/winscope/src/app/components/timeline/expanded_timeline_component.ts index 51a1d9b59..c392d85b6 100644 --- a/tools/winscope/src/app/components/timeline/expanded_timeline_component.ts +++ b/tools/winscope/src/app/components/timeline/expanded_timeline_component.ts @@ -37,7 +37,7 @@ import {SingleTimelineComponent} from './single_timeline_component'; template: `
> { - const traces = new Array>(); - this.timelineData.getTraces().forEachTrace((trace) => { - traces.push(trace); - }); - return traces; - } - @HostListener('window:resize', ['$event']) onResize(event: Event) { this.resizeCanvases(); diff --git a/tools/winscope/src/app/components/timeline/mini_timeline_component.ts b/tools/winscope/src/app/components/timeline/mini_timeline_component.ts index 89230a3aa..2f11e1e1f 100644 --- a/tools/winscope/src/app/components/timeline/mini_timeline_component.ts +++ b/tools/winscope/src/app/components/timeline/mini_timeline_component.ts @@ -107,9 +107,11 @@ export class MiniTimelineComponent { private getTracesToShow(): Traces { const traces = new Traces(); - this.selectedTraces.forEach((type) => { - traces.setTrace(type, assertDefined(this.timelineData.getTraces().getTrace(type))); - }); + this.selectedTraces + .filter((type) => this.timelineData.getTraces().getTrace(type) !== undefined) + .forEach((type) => { + traces.setTrace(type, assertDefined(this.timelineData.getTraces().getTrace(type))); + }); return traces; } diff --git a/tools/winscope/src/app/components/timeline/timeline_component.ts b/tools/winscope/src/app/components/timeline/timeline_component.ts index 7d2f4301e..1650d7523 100644 --- a/tools/winscope/src/app/components/timeline/timeline_component.ts +++ b/tools/winscope/src/app/components/timeline/timeline_component.ts @@ -30,8 +30,14 @@ import {FormControl, FormGroup, Validators} from '@angular/forms'; import {DomSanitizer, SafeUrl} from '@angular/platform-browser'; import {TimelineData} from 'app/timeline_data'; import {TRACE_INFO} from 'app/trace_info'; +import {assertDefined} from 'common/assert_utils'; +import {FunctionUtils} from 'common/function_utils'; import {StringUtils} from 'common/string_utils'; import {TimeUtils} from 'common/time_utils'; +import { + OnTracePositionUpdate, + TracePositionUpdateEmitter, +} from 'interfaces/trace_position_update_emitter'; import {TracePositionUpdateListener} from 'interfaces/trace_position_update_listener'; import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp'; import {TracePosition} from 'trace/trace_position'; @@ -287,7 +293,7 @@ import {MiniTimelineComponent} from './mini_timeline_component'; `, ], }) -export class TimelineComponent implements TracePositionUpdateListener { +export class TimelineComponent implements TracePositionUpdateEmitter, TracePositionUpdateListener { readonly TOGGLE_BUTTON_CLASS: string = 'button-toggle-expansion'; readonly MAX_SELECTED_TRACES = 3; @@ -358,6 +364,8 @@ export class TimelineComponent implements TracePositionUpdateListener { TRACE_INFO = TRACE_INFO; + private onTracePositionUpdateCallback: OnTracePositionUpdate = FunctionUtils.DO_NOTHING_ASYNC; + constructor( @Inject(DomSanitizer) private sanitizer: DomSanitizer, @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef @@ -381,17 +389,21 @@ export class TimelineComponent implements TracePositionUpdateListener { this.collapsedTimelineSizeChanged.emit(height); } + setOnTracePositionUpdate(callback: OnTracePositionUpdate) { + this.onTracePositionUpdateCallback = callback; + } + getVideoCurrentTime() { return this.timelineData.searchCorrespondingScreenRecordingTimeSeconds( this.getCurrentTracePosition() ); } - private seekTimestamp: Timestamp | undefined; + private seekTracePosition?: TracePosition; getCurrentTracePosition(): TracePosition { - if (this.seekTimestamp !== undefined) { - return TracePosition.fromTimestamp(this.seekTimestamp); + if (this.seekTracePosition) { + return this.seekTracePosition; } const position = this.timelineData.getCurrentPosition(); @@ -411,8 +423,9 @@ export class TimelineComponent implements TracePositionUpdateListener { this.changeDetectorRef.detectChanges(); } - updatePosition(position: TracePosition) { + async updatePosition(position: TracePosition) { this.timelineData.setPosition(position); + await this.onTracePositionUpdateCallback(position); } usingRealtime(): boolean { @@ -420,7 +433,11 @@ export class TimelineComponent implements TracePositionUpdateListener { } updateSeekTimestamp(timestamp: Timestamp | undefined) { - this.seekTimestamp = timestamp; + if (timestamp) { + this.seekTracePosition = TracePosition.fromTimestamp(timestamp); + } else { + this.seekTracePosition = undefined; + } this.updateTimeInputValuesToCurrentTimestamp(); } @@ -464,11 +481,11 @@ export class TimelineComponent implements TracePositionUpdateListener { } @HostListener('document:keydown', ['$event']) - handleKeyboardEvent(event: KeyboardEvent) { + async handleKeyboardEvent(event: KeyboardEvent) { if (event.key === 'ArrowLeft') { - this.moveToPreviousEntry(); + await this.moveToPreviousEntry(); } else if (event.key === 'ArrowRight') { - this.moveToNextEntry(); + await this.moveToNextEntry(); } } @@ -476,6 +493,9 @@ export class TimelineComponent implements TracePositionUpdateListener { if (!this.internalActiveTrace) { return false; } + if (this.timelineData.getTraces().getTrace(this.internalActiveTrace) === undefined) { + return false; + } return this.timelineData.getPreviousEntryFor(this.internalActiveTrace) !== undefined; } @@ -483,45 +503,50 @@ export class TimelineComponent implements TracePositionUpdateListener { if (!this.internalActiveTrace) { return false; } + if (this.timelineData.getTraces().getTrace(this.internalActiveTrace) === undefined) { + return false; + } return this.timelineData.getNextEntryFor(this.internalActiveTrace) !== undefined; } - moveToPreviousEntry() { + async moveToPreviousEntry() { if (!this.internalActiveTrace) { return; } this.timelineData.moveToPreviousEntryFor(this.internalActiveTrace); + await this.onTracePositionUpdateCallback(assertDefined(this.timelineData.getCurrentPosition())); } - moveToNextEntry() { + async moveToNextEntry() { if (!this.internalActiveTrace) { return; } this.timelineData.moveToNextEntryFor(this.internalActiveTrace); + await this.onTracePositionUpdateCallback(assertDefined(this.timelineData.getCurrentPosition())); } - humanElapsedTimeInputChange(event: Event) { + async humanElapsedTimeInputChange(event: Event) { if (event.type !== 'change') { return; } const target = event.target as HTMLInputElement; const timestamp = TimeUtils.parseHumanElapsed(target.value); - this.timelineData.setPosition(TracePosition.fromTimestamp(timestamp)); + await this.updatePosition(TracePosition.fromTimestamp(timestamp)); this.updateTimeInputValuesToCurrentTimestamp(); } - humanRealTimeInputChanged(event: Event) { + async humanRealTimeInputChanged(event: Event) { if (event.type !== 'change') { return; } const target = event.target as HTMLInputElement; const timestamp = TimeUtils.parseHumanReal(target.value); - this.timelineData.setPosition(TracePosition.fromTimestamp(timestamp)); + await this.updatePosition(TracePosition.fromTimestamp(timestamp)); this.updateTimeInputValuesToCurrentTimestamp(); } - nanosecondsInputTimeChange(event: Event) { + async nanosecondsInputTimeChange(event: Event) { if (event.type !== 'change') { return; } @@ -531,7 +556,7 @@ export class TimelineComponent implements TracePositionUpdateListener { this.timelineData.getTimestampType()!, StringUtils.parseBigIntStrippingUnit(target.value) ); - this.timelineData.setPosition(TracePosition.fromTimestamp(timestamp)); + await this.updatePosition(TracePosition.fromTimestamp(timestamp)); this.updateTimeInputValuesToCurrentTimestamp(); } } diff --git a/tools/winscope/src/app/components/timeline/timeline_component_stub.ts b/tools/winscope/src/app/components/timeline/timeline_component_stub.ts index 595e1179e..265e8215d 100644 --- a/tools/winscope/src/app/components/timeline/timeline_component_stub.ts +++ b/tools/winscope/src/app/components/timeline/timeline_component_stub.ts @@ -14,10 +14,20 @@ * limitations under the License. */ +import { + OnTracePositionUpdate, + TracePositionUpdateEmitter, +} from 'interfaces/trace_position_update_emitter'; import {TracePositionUpdateListener} from 'interfaces/trace_position_update_listener'; import {TracePosition} from 'trace/trace_position'; -export class TimelineComponentStub implements TracePositionUpdateListener { +export class TimelineComponentStub + implements TracePositionUpdateEmitter, TracePositionUpdateListener +{ + setOnTracePositionUpdate(callback: OnTracePositionUpdate) { + // do nothing + } + onTracePositionUpdate(position: TracePosition) { // do nothing } diff --git a/tools/winscope/src/app/components/upload_traces_component.ts b/tools/winscope/src/app/components/upload_traces_component.ts index a52692e83..1652ccc9b 100644 --- a/tools/winscope/src/app/components/upload_traces_component.ts +++ b/tools/winscope/src/app/components/upload_traces_component.ts @@ -25,7 +25,7 @@ import { import {TRACE_INFO} from 'app/trace_info'; import {TracePipeline} from 'app/trace_pipeline'; import {ProgressListener} from 'interfaces/progress_listener'; -import {LoadedTrace} from 'trace/loaded_trace'; +import {Trace} from 'trace/trace'; import {LoadProgressComponent} from './load_progress_component'; @Component({ @@ -57,15 +57,15 @@ import {LoadProgressComponent} from './load_progress_component'; - + {{ TRACE_INFO[trace.type].icon }}

{{ TRACE_INFO[trace.type].name }}

-

{{ descriptor }}

+

{{ descriptor }}