1 /*
2  * Copyright (C) 2021 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.events.services;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 
22 import androidx.annotation.CheckResult;
23 
24 import com.android.eventlib.Event;
25 import com.android.eventlib.EventLogger;
26 import com.android.eventlib.EventLogsQuery;
27 import com.android.queryable.info.ServiceInfo;
28 import com.android.queryable.queries.IntegerQueryHelper;
29 import com.android.queryable.queries.IntentQuery;
30 import com.android.queryable.queries.IntentQueryHelper;
31 import com.android.queryable.queries.ServiceQuery;
32 import com.android.queryable.queries.ServiceQueryHelper;
33 import com.android.queryable.util.SerializableParcelWrapper;
34 
35 import com.google.errorprone.annotations.CanIgnoreReturnValue;
36 
37 /**
38  * Event logged when {@link Service#onStartCommand(Intent, int, int)}
39  */
40 public class ServiceStartedEvent extends Event {
41 
42     private static final long serialVersionUID = 1;
43 
44     /** Begins a query for {@link ServiceStartedEvent} events. */
queryPackage(String packageName)45     public static ServiceStartedEventQuery queryPackage(String packageName) {
46         return new ServiceStartedEventQuery(packageName);
47     }
48 
49     /** {@link EventLogsQuery} for {@link ServiceStartedEvent}. */
50     public static final class ServiceStartedEventQuery extends EventLogsQuery<ServiceStartedEvent,
51             ServiceStartedEventQuery> {
52 
53         private static final long serialVersionUID = 1;
54 
55         ServiceQueryHelper<ServiceStartedEventQuery> mService = new ServiceQueryHelper<>(this);
56         IntentQueryHelper<ServiceStartedEventQuery> mIntent = new IntentQueryHelper<>(this);
57         IntegerQueryHelper<ServiceStartedEventQuery> mFlags = new IntegerQueryHelper<>(this);
58         IntegerQueryHelper<ServiceStartedEventQuery> mStartId = new IntegerQueryHelper<>(this);
59 
ServiceStartedEventQuery(String packageName)60         private ServiceStartedEventQuery(String packageName) {
61             super(ServiceStartedEvent.class, packageName);
62         }
63 
64         /** Query {@link Service}. */
65         @CheckResult
whereService()66         public ServiceQuery<ServiceStartedEventQuery> whereService() {
67             return mService;
68         }
69 
70         /**
71          * Query {@link Intent} passed into {@link Service#onBind(Intent)}.
72          */
73         @CheckResult
whereIntent()74         public IntentQuery<ServiceStartedEventQuery> whereIntent() {
75             return mIntent;
76         }
77 
78         /** Query {@link Service}. */
79         @CheckResult
whereFlags()80         public IntegerQueryHelper<ServiceStartedEventQuery> whereFlags() {
81             return mFlags;
82         }
83 
84         /** Query {@link Service}. */
85         @CheckResult
whereStartId()86         public IntegerQueryHelper<ServiceStartedEventQuery> whereStartId() {
87             return mStartId;
88         }
89 
90         @Override
filter(ServiceStartedEvent event)91         protected boolean filter(ServiceStartedEvent event) {
92             if (!mFlags.matches(event.mFlags)) {
93                 return false;
94             }
95             if (!mStartId.matches(event.mStartId)) {
96                 return false;
97             }
98             if (!mIntent.matches(event.mIntent)) {
99                 return false;
100             }
101             if (!mService.matches(event.mService)) {
102                 return false;
103             }
104             return true;
105         }
106 
107         @Override
describeQuery(String fieldName)108         public String describeQuery(String fieldName) {
109             return toStringBuilder(ServiceStartedEvent.class, this)
110                     .field("flags", mFlags)
111                     .field("startId", mStartId)
112                     .field("intent", mIntent)
113                     .field("service", mService)
114                     .toString();
115         }
116     }
117 
118 
119     /** Begins logging a {@link ServiceStartedEvent}. */
logger(Service service, String serviceName, Intent intent, int flags, int startId)120     public static ServiceStartedEventLogger logger(Service service,
121             String serviceName, Intent intent, int flags, int startId) {
122         return new ServiceStartedEventLogger(service, serviceName, intent, flags, startId);
123     }
124 
125     /** {@link EventLogger} for {@link ServiceStartedEvent}. */
126     public static final class ServiceStartedEventLogger extends EventLogger<ServiceStartedEvent> {
127 
128         // TODO(b/214187100) Use ServiceInfo here instead of a String to identify the service.
ServiceStartedEventLogger(Service service, String serviceName, Intent intent, int flags, int startId)129         private ServiceStartedEventLogger(Service service,
130                 String serviceName, Intent intent, int flags, int startId) {
131             super(service, new ServiceStartedEvent());
132             mEvent.mIntent = new SerializableParcelWrapper<>(intent);
133             mEvent.mFlags = flags;
134             mEvent.mStartId = startId;
135             setService(serviceName);
136         }
137 
138         /** Sets the {@link Service} which received this event. */
139         @CanIgnoreReturnValue
setService(String serviceName)140         public ServiceStartedEventLogger setService(String serviceName) {
141             mEvent.mService = ServiceInfo.builder()
142                     .serviceClass(serviceName)
143                     .build();
144             return this;
145         }
146 
147         /** Sets the {@link Intent} supplied to {@link android.content.Context#startService}. */
148         @CanIgnoreReturnValue
setIntent(Intent intent)149         public ServiceStartedEventLogger setIntent(Intent intent) {
150             mEvent.mIntent = new SerializableParcelWrapper<>(intent);
151             return this;
152         }
153 
154         /** Sets the flags used for the start request of this service. */
155         @CanIgnoreReturnValue
setFlags(int flags)156         public ServiceStartedEventLogger setFlags(int flags) {
157             mEvent.mFlags = flags;
158             return this;
159         }
160 
161         /** Sets the startId. */
162         @CanIgnoreReturnValue
setStartId(int startId)163         public ServiceStartedEventLogger setStartId(int startId) {
164             mEvent.mStartId = startId;
165             return this;
166         }
167 
168     }
169 
170     protected ServiceInfo mService;
171     protected SerializableParcelWrapper<Intent> mIntent;
172     protected int mFlags;
173     protected int mStartId;
174 
175     /**
176      * The {@link Intent} passed into {@link Service#onStartCommand(Intent, int, int)}.
177      */
intent()178     public Intent intent() {
179         if (mIntent == null) {
180             return null;
181         }
182         return mIntent.get();
183     }
184 
185     /**
186      * The flags passed into {@link Service#onStartCommand(Intent, int, int)}.
187      */
flags()188     public int flags() {
189         return mFlags;
190     }
191 
192     /**
193      * The startId passed into {@link Service#onStartCommand(Intent, int, int)}.
194      */
startId()195     public int startId() {
196         return mStartId;
197     }
198 
199     /** Information about the {@link Service} which received the intent. */
service()200     public ServiceInfo service() {
201         return mService;
202     }
203 
204     @Override
toString()205     public String toString() {
206         return "ServiceStartedEvent{"
207                 + ", service=" + mService
208                 + ", flags=" + mFlags
209                 + ", startId=" + mStartId
210                 + ", packageName='" + mPackageName + "'"
211                 + ", timestamp=" + mTimestamp
212                 + "}";
213     }
214 }
215