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 android.service.tracing;
18 
19 import static android.annotation.SystemApi.Client.PRIVILEGED_APPS;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.app.Service;
25 import android.content.Intent;
26 import android.os.Handler;
27 import android.os.IBinder;
28 import android.os.Looper;
29 import android.os.Message;
30 import android.os.Messenger;
31 import android.os.ParcelFileDescriptor;
32 import android.os.Process;
33 import android.tracing.TraceReportParams;
34 import android.util.Log;
35 
36 import java.io.IOException;
37 import java.util.UUID;
38 
39 /**
40  * Service to be sub-classed and exposed by (privileged) apps which want to report
41  * system traces.
42  * <p>
43  * Subclasses should implement the onReportTrace method to handle traces reported
44  * to them.
45  * </p>
46  * <pre>
47  *    public class SampleReportService extends TraceReportService {
48  *        public void onReportTrace(TraceParams args) {
49  *            // --- Implementation goes here ---
50  *        }
51  *    }
52  * </pre>
53  * <p>
54  * The service declaration in the application manifest must specify
55  * BIND_TRACE_REPORT_SERVICE in the permission attribute.
56  * </p>
57  * <pre>
58  *   &lt;application>
59  *        &lt;service android:name=".SampleReportService"
60  *               android:permission="android.permission.BIND_TRACE_REPORT_SERVICE">
61  *       &lt;/service>
62  *   &lt;/application>
63  * </pre>
64  *
65  * Moreover, the package containing this service must hold the DUMP and PACKAGE_USAGE_STATS
66  * permissions.
67  *
68  * @hide
69  */
70 @SystemApi(client = PRIVILEGED_APPS)
71 public class TraceReportService extends Service {
72     private static final String TAG = "TraceReportService";
73     private Messenger mMessenger = null;
74 
75     /**
76      * Public to allow this to be used by TracingServiceProxy in system_server.
77      *
78      * @hide
79      */
80     public static final int MSG_REPORT_TRACE = 1;
81 
82     /**
83      * Contains information about the trace which is being reported.
84      *
85      * @hide
86      */
87     @SystemApi(client = PRIVILEGED_APPS)
88     public static final class TraceParams {
89         private final ParcelFileDescriptor mFd;
90         private final UUID mUuid;
91 
TraceParams(TraceReportParams params)92         private TraceParams(TraceReportParams params) {
93             mFd = params.fd;
94             mUuid = new UUID(params.uuidMsb, params.uuidLsb);
95         }
96 
97         /**
98          * Returns the ParcelFileDescriptor for the collected trace.
99          */
100         @NonNull
getFd()101         public ParcelFileDescriptor getFd() {
102             return mFd;
103         }
104 
105         /**
106          * Returns the UUID of the trace; this is exactly the UUID created by the tracing system
107          * (i.e. Perfetto) and is also present inside the trace file.
108          */
109         @NonNull
getUuid()110         public UUID getUuid() {
111             return mUuid;
112         }
113     }
114 
115     /**
116      * Called when a trace is reported and sent to this class.
117      *
118      * Note: the trace file descriptor should not be persisted beyond the lifetime of this
119      * function as it is owned by the framework and will be closed immediately after this function
120      * returns: if future use of the fd is needed, it should be duped.
121      */
onReportTrace(@onNull TraceParams args)122     public void onReportTrace(@NonNull TraceParams args) {
123     }
124 
125     /**
126      * Handles binder calls from system_server.
127      */
onMessage(@onNull Message msg)128     private boolean onMessage(@NonNull Message msg) {
129         if (msg.what == MSG_REPORT_TRACE) {
130             if (!(msg.obj instanceof TraceReportParams)) {
131                 Log.e(TAG, "Received invalid type for report trace message.");
132                 return false;
133             }
134             TraceParams params = new TraceParams((TraceReportParams) msg.obj);
135             try {
136                 onReportTrace(params);
137             } finally {
138                 try {
139                     params.getFd().close();
140                 } catch (IOException ignored) {
141                 }
142             }
143             return true;
144         }
145         return false;
146     }
147 
148     /**
149      * Returns an IBinder for handling binder calls from system_server.
150      *
151      * @hide
152      */
153     @Nullable
154     @Override
onBind(@onNull Intent intent)155     public final IBinder onBind(@NonNull Intent intent) {
156         if (mMessenger == null) {
157             mMessenger = new Messenger(new Handler(Looper.getMainLooper(), this::onMessage));
158         }
159         return mMessenger.getBinder();
160     }
161 }