1// Copyright (C) 2019 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {searchSegment} from '../base/binary_search'; 16import {assertUnreachable} from '../base/logging'; 17import {Actions} from '../common/actions'; 18import {globals} from './globals'; 19import {verticalScrollToTrack} from './scroll_helper'; 20 21function setToPrevious(current: number) { 22 let index = current - 1; 23 if (index < 0) { 24 index = globals.currentSearchResults.totalResults - 1; 25 } 26 globals.dispatch(Actions.setSearchIndex({index})); 27} 28 29function setToNext(current: number) { 30 const index = (current + 1) % globals.currentSearchResults.totalResults; 31 globals.dispatch(Actions.setSearchIndex({index})); 32} 33 34export function executeSearch(reverse = false) { 35 const index = globals.state.searchIndex; 36 const vizWindow = globals.stateVisibleTime(); 37 const startNs = vizWindow.start; 38 const endNs = vizWindow.end; 39 const currentTs = globals.currentSearchResults.tses[index]; 40 41 // If the value of |globals.currentSearchResults.totalResults| is 0, 42 // it means that the query is in progress or no results are found. 43 if (globals.currentSearchResults.totalResults === 0) { 44 return; 45 } 46 47 // If this is a new search or the currentTs is not in the viewport, 48 // select the first/last item in the viewport. 49 if ( 50 index === -1 || 51 (currentTs !== -1n && (currentTs < startNs || currentTs > endNs)) 52 ) { 53 if (reverse) { 54 const [smaller] = searchSegment(globals.currentSearchResults.tses, endNs); 55 // If there is no item in the viewport just go to the previous. 56 if (smaller === -1) { 57 setToPrevious(index); 58 } else { 59 globals.dispatch(Actions.setSearchIndex({index: smaller})); 60 } 61 } else { 62 const [, larger] = searchSegment( 63 globals.currentSearchResults.tses, 64 startNs, 65 ); 66 // If there is no item in the viewport just go to the next. 67 if (larger === -1) { 68 setToNext(index); 69 } else { 70 globals.dispatch(Actions.setSearchIndex({index: larger})); 71 } 72 } 73 } else { 74 // If the currentTs is in the viewport, increment the index. 75 if (reverse) { 76 setToPrevious(index); 77 } else { 78 setToNext(index); 79 } 80 } 81 selectCurrentSearchResult(); 82} 83 84function selectCurrentSearchResult() { 85 const searchIndex = globals.state.searchIndex; 86 const source = globals.currentSearchResults.sources[searchIndex]; 87 const currentId = globals.currentSearchResults.eventIds[searchIndex]; 88 const trackKey = globals.currentSearchResults.trackKeys[searchIndex]; 89 90 if (currentId === undefined) return; 91 92 switch (source) { 93 case 'track': 94 verticalScrollToTrack(trackKey, true); 95 break; 96 case 'cpu': 97 globals.setLegacySelection( 98 { 99 kind: 'SCHED_SLICE', 100 id: currentId, 101 trackKey, 102 }, 103 { 104 clearSearch: false, 105 pendingScrollId: currentId, 106 switchToCurrentSelectionTab: true, 107 }, 108 ); 109 break; 110 case 'log': 111 globals.setLegacySelection( 112 { 113 kind: 'LOG', 114 id: currentId, 115 trackKey, 116 }, 117 { 118 clearSearch: false, 119 pendingScrollId: currentId, 120 switchToCurrentSelectionTab: true, 121 }, 122 ); 123 break; 124 case 'slice': 125 // Search results only include slices from the slice table for now. 126 // When we include annotations we need to pass the correct table. 127 globals.setLegacySelection( 128 { 129 kind: 'SLICE', 130 id: currentId, 131 trackKey, 132 table: 'slice', 133 }, 134 { 135 clearSearch: false, 136 pendingScrollId: currentId, 137 switchToCurrentSelectionTab: true, 138 }, 139 ); 140 break; 141 default: 142 assertUnreachable(source); 143 } 144} 145