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 * <application> 59 * <service android:name=".SampleReportService" 60 * android:permission="android.permission.BIND_TRACE_REPORT_SERVICE"> 61 * </service> 62 * </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 }