1 /* 2 * Copyright (C) 2014 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.app; 18 19 import android.os.Parcel; 20 import android.os.ParcelFileDescriptor; 21 import android.os.Parcelable; 22 import android.util.Slog; 23 import android.util.proto.ProtoOutputStream; 24 25 import java.io.IOException; 26 import java.util.Objects; 27 28 /** 29 * System private API for passing profiler settings. 30 * 31 * {@hide} 32 */ 33 public class ProfilerInfo implements Parcelable { 34 35 private static final String TAG = "ProfilerInfo"; 36 37 /* Name of profile output file. */ 38 public final String profileFile; 39 40 /* File descriptor for profile output file, can be null. */ 41 public ParcelFileDescriptor profileFd; 42 43 /* Indicates sample profiling when nonzero, interval in microseconds. */ 44 public final int samplingInterval; 45 46 /* Automatically stop the profiler when the app goes idle. */ 47 public final boolean autoStopProfiler; 48 49 /* 50 * Indicates whether to stream the profiling info to the out file continuously. 51 */ 52 public final boolean streamingOutput; 53 54 /** 55 * Denotes an agent (and its parameters) to attach for profiling. 56 */ 57 public final String agent; 58 59 /** 60 * Whether the {@link agent} should be attached early (before bind-application) or during 61 * bind-application. Agents attached prior to binding cannot be loaded from the app's APK 62 * directly and must be given as an absolute path (or available in the default LD_LIBRARY_PATH). 63 * Agents attached during bind-application will miss early setup (e.g., resource initialization 64 * and classloader generation), but are searched in the app's library search path. 65 */ 66 public final boolean attachAgentDuringBind; 67 ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop, boolean streaming, String agent, boolean attachAgentDuringBind)68 public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop, 69 boolean streaming, String agent, boolean attachAgentDuringBind) { 70 profileFile = filename; 71 profileFd = fd; 72 samplingInterval = interval; 73 autoStopProfiler = autoStop; 74 streamingOutput = streaming; 75 this.agent = agent; 76 this.attachAgentDuringBind = attachAgentDuringBind; 77 } 78 ProfilerInfo(ProfilerInfo in)79 public ProfilerInfo(ProfilerInfo in) { 80 profileFile = in.profileFile; 81 profileFd = in.profileFd; 82 samplingInterval = in.samplingInterval; 83 autoStopProfiler = in.autoStopProfiler; 84 streamingOutput = in.streamingOutput; 85 agent = in.agent; 86 attachAgentDuringBind = in.attachAgentDuringBind; 87 } 88 89 /** 90 * Return a new ProfilerInfo instance, with fields populated from this object, 91 * and {@link agent} and {@link attachAgentDuringBind} as given. 92 */ setAgent(String agent, boolean attachAgentDuringBind)93 public ProfilerInfo setAgent(String agent, boolean attachAgentDuringBind) { 94 return new ProfilerInfo(this.profileFile, this.profileFd, this.samplingInterval, 95 this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind); 96 } 97 98 /** 99 * Close profileFd, if it is open. The field will be null after a call to this function. 100 */ closeFd()101 public void closeFd() { 102 if (profileFd != null) { 103 try { 104 profileFd.close(); 105 } catch (IOException e) { 106 Slog.w(TAG, "Failure closing profile fd", e); 107 } 108 profileFd = null; 109 } 110 } 111 112 @Override describeContents()113 public int describeContents() { 114 if (profileFd != null) { 115 return profileFd.describeContents(); 116 } else { 117 return 0; 118 } 119 } 120 121 @Override writeToParcel(Parcel out, int flags)122 public void writeToParcel(Parcel out, int flags) { 123 out.writeString(profileFile); 124 if (profileFd != null) { 125 out.writeInt(1); 126 profileFd.writeToParcel(out, flags); 127 } else { 128 out.writeInt(0); 129 } 130 out.writeInt(samplingInterval); 131 out.writeInt(autoStopProfiler ? 1 : 0); 132 out.writeInt(streamingOutput ? 1 : 0); 133 out.writeString(agent); 134 out.writeBoolean(attachAgentDuringBind); 135 } 136 137 /** @hide */ dumpDebug(ProtoOutputStream proto, long fieldId)138 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 139 final long token = proto.start(fieldId); 140 proto.write(ProfilerInfoProto.PROFILE_FILE, profileFile); 141 if (profileFd != null) { 142 proto.write(ProfilerInfoProto.PROFILE_FD, profileFd.getFd()); 143 } 144 proto.write(ProfilerInfoProto.SAMPLING_INTERVAL, samplingInterval); 145 proto.write(ProfilerInfoProto.AUTO_STOP_PROFILER, autoStopProfiler); 146 proto.write(ProfilerInfoProto.STREAMING_OUTPUT, streamingOutput); 147 proto.write(ProfilerInfoProto.AGENT, agent); 148 proto.end(token); 149 } 150 151 public static final @android.annotation.NonNull Parcelable.Creator<ProfilerInfo> CREATOR = 152 new Parcelable.Creator<ProfilerInfo>() { 153 @Override 154 public ProfilerInfo createFromParcel(Parcel in) { 155 return new ProfilerInfo(in); 156 } 157 158 @Override 159 public ProfilerInfo[] newArray(int size) { 160 return new ProfilerInfo[size]; 161 } 162 }; 163 ProfilerInfo(Parcel in)164 private ProfilerInfo(Parcel in) { 165 profileFile = in.readString(); 166 profileFd = in.readInt() != 0 ? ParcelFileDescriptor.CREATOR.createFromParcel(in) : null; 167 samplingInterval = in.readInt(); 168 autoStopProfiler = in.readInt() != 0; 169 streamingOutput = in.readInt() != 0; 170 agent = in.readString(); 171 attachAgentDuringBind = in.readBoolean(); 172 } 173 174 @Override equals(Object o)175 public boolean equals(Object o) { 176 if (this == o) { 177 return true; 178 } 179 if (o == null || getClass() != o.getClass()) { 180 return false; 181 } 182 final ProfilerInfo other = (ProfilerInfo) o; 183 // TODO: Also check #profileFd for equality. 184 return Objects.equals(profileFile, other.profileFile) 185 && autoStopProfiler == other.autoStopProfiler 186 && samplingInterval == other.samplingInterval 187 && streamingOutput == other.streamingOutput 188 && Objects.equals(agent, other.agent); 189 } 190 191 @Override hashCode()192 public int hashCode() { 193 int result = 17; 194 result = 31 * result + Objects.hashCode(profileFile); 195 result = 31 * result + samplingInterval; 196 result = 31 * result + (autoStopProfiler ? 1 : 0); 197 result = 31 * result + (streamingOutput ? 1 : 0); 198 result = 31 * result + Objects.hashCode(agent); 199 return result; 200 } 201 } 202