1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.eventlib; 18 19 import android.os.UserHandle; 20 21 import com.android.bedstead.nene.users.UserReference; 22 import com.android.queryable.Queryable; 23 import com.android.queryable.queries.Query; 24 25 import java.util.ArrayList; 26 import java.util.HashSet; 27 import java.util.List; 28 import java.util.Set; 29 import java.util.function.Function; 30 31 /** 32 * Interface to provide additional restrictions on an {@link Event} query. 33 */ 34 public abstract class EventLogsQuery<E extends Event, F extends EventLogsQuery> 35 extends EventLogs<E> implements Queryable { 36 private final Class<E> mEventClass; 37 private final String mPackageName; 38 private final transient Set<Function<E, Boolean>> mFilters = new HashSet<>(); 39 private transient UserHandle mUserHandle = null; // null is default, meaning current user 40 EventLogsQuery(Class<E> eventClass, String packageName)41 protected EventLogsQuery(Class<E> eventClass, String packageName) { 42 if (eventClass == null || packageName == null) { 43 throw new NullPointerException(); 44 } 45 mQuerier = new RemoteEventQuerier<>(packageName, this); 46 mEventClass = eventClass; 47 mPackageName = packageName; 48 } 49 50 /** Get the package name being filtered for. */ getPackageName()51 protected String getPackageName() { 52 return mPackageName; 53 } 54 eventClass()55 protected Class<E> eventClass() { 56 return mEventClass; 57 } 58 59 private final transient EventQuerier<E> mQuerier; 60 61 @Override getQuerier()62 protected EventQuerier<E> getQuerier() { 63 return mQuerier; 64 } 65 66 /** Apply a lambda filter to the results. */ filter(Function<E, Boolean> filter)67 public F filter(Function<E, Boolean> filter) { 68 mFilters.add(filter); 69 return (F) this; 70 } 71 72 /** 73 * Returns true if {@code E} matches custom and default filters for this {@link Event} subclass. 74 */ filterAll(E event)75 protected final boolean filterAll(E event) { 76 if (mFilters != null) { 77 // Filters will be null when called remotely 78 for (Function<E, Boolean> filter : mFilters) { 79 if (!filter.apply(event)) { 80 return false; 81 } 82 } 83 } 84 return filter(event); 85 } 86 87 /** Returns true if {@code E} matches the custom filters for this {@link Event} subclass. */ filter(E event)88 protected abstract boolean filter(E event); 89 90 /** Query a package running on another user. */ onUser(UserHandle userHandle)91 public F onUser(UserHandle userHandle) { 92 if (userHandle == null) { 93 throw new NullPointerException(); 94 } 95 mUserHandle = userHandle; 96 return (F) this; 97 } 98 99 /** Query a package running on another user. */ onUser(UserReference userReference)100 public F onUser(UserReference userReference) { 101 return onUser(userReference.userHandle()); 102 } 103 getUserHandle()104 UserHandle getUserHandle() { 105 return mUserHandle; 106 } 107 108 109 public static class ToStringBuilder { 110 111 private final List<String> mFields = new ArrayList<>(); 112 private final int mNumberOfCustomFilters; 113 ToStringBuilder(String eventType, EventLogsQuery<?, ?> query)114 private ToStringBuilder(String eventType, EventLogsQuery<?, ?> query) { 115 mFields.add("type=" + eventType); 116 mFields.add("packageName=" + query.mPackageName); 117 if (query.mUserHandle != null) { 118 mFields.add("user=" + query.mUserHandle); 119 } 120 mNumberOfCustomFilters = query.mFilters.size(); 121 } 122 field(String fieldName, Query<?> query)123 public ToStringBuilder field(String fieldName, Query<?> query) { 124 mFields.add(query.describeQuery(fieldName)); 125 return this; 126 } 127 128 @Override toString()129 public String toString() { 130 if (mNumberOfCustomFilters > 0) { 131 mFields.add(mNumberOfCustomFilters + " custom filters"); 132 } 133 return "{" + Queryable.joinQueryStrings(mFields) + "}"; 134 } 135 } 136 toStringBuilder( Class<N> eventClass, EventLogsQuery<N, ?> query)137 public <N extends Event> ToStringBuilder toStringBuilder( 138 Class<N> eventClass, EventLogsQuery<N, ?> query) { 139 return new ToStringBuilder(eventClass.getSimpleName(), query); 140 } 141 142 @Override toString()143 public String toString() { 144 return describeQuery("Query"); 145 } 146 } 147