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