Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 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; |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 20 | import android.os.ParcelFileDescriptor; |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 21 | import android.os.Parcelable; |
| 22 | import android.util.Slog; |
Yi Jin | 148d7f4 | 2017-11-28 14:23:56 -0800 | [diff] [blame] | 23 | import android.util.proto.ProtoOutputStream; |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 24 | |
| 25 | import java.io.IOException; |
Andrii Kulian | 6b9d3a1 | 2017-11-16 14:36:36 -0800 | [diff] [blame] | 26 | import java.util.Objects; |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 27 | |
| 28 | /** |
| 29 | * System private API for passing profiler settings. |
| 30 | * |
| 31 | * {@hide} |
| 32 | */ |
| 33 | public class ProfilerInfo implements Parcelable { |
| 34 | |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 35 | private static final String TAG = "ProfilerInfo"; |
| 36 | |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 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 | |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 49 | /* |
| 50 | * Indicates whether to stream the profiling info to the out file continuously. |
| 51 | */ |
Shukang Zhou | 6ffd4f9 | 2017-01-25 16:07:57 -0800 | [diff] [blame] | 52 | public final boolean streamingOutput; |
| 53 | |
Andreas Gampe | 83085bb | 2017-06-26 17:54:11 -0700 | [diff] [blame] | 54 | /** |
| 55 | * Denotes an agent (and its parameters) to attach for profiling. |
| 56 | */ |
| 57 | public final String agent; |
| 58 | |
Andreas Gampe | ab8a63b | 2018-01-05 13:55:15 -0800 | [diff] [blame] | 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 | |
Shukang Zhou | 6ffd4f9 | 2017-01-25 16:07:57 -0800 | [diff] [blame] | 68 | public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop, |
Andreas Gampe | ab8a63b | 2018-01-05 13:55:15 -0800 | [diff] [blame] | 69 | boolean streaming, String agent, boolean attachAgentDuringBind) { |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 70 | profileFile = filename; |
| 71 | profileFd = fd; |
| 72 | samplingInterval = interval; |
| 73 | autoStopProfiler = autoStop; |
Shukang Zhou | 6ffd4f9 | 2017-01-25 16:07:57 -0800 | [diff] [blame] | 74 | streamingOutput = streaming; |
Andreas Gampe | 83085bb | 2017-06-26 17:54:11 -0700 | [diff] [blame] | 75 | this.agent = agent; |
Andreas Gampe | ab8a63b | 2018-01-05 13:55:15 -0800 | [diff] [blame] | 76 | this.attachAgentDuringBind = attachAgentDuringBind; |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 77 | } |
| 78 | |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 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; |
Andreas Gampe | 83085bb | 2017-06-26 17:54:11 -0700 | [diff] [blame] | 85 | agent = in.agent; |
Andreas Gampe | ab8a63b | 2018-01-05 13:55:15 -0800 | [diff] [blame] | 86 | attachAgentDuringBind = in.attachAgentDuringBind; |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | /** |
Andreas Gampe | 5b495d5 | 2018-01-22 15:15:54 -0800 | [diff] [blame] | 90 | * Return a new ProfilerInfo instance, with fields populated from this object, |
| 91 | * and {@link agent} and {@link attachAgentDuringBind} as given. |
| 92 | */ |
| 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 | /** |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 99 | * Close profileFd, if it is open. The field will be null after a call to this function. |
| 100 | */ |
| 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 |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 113 | public int describeContents() { |
| 114 | if (profileFd != null) { |
| 115 | return profileFd.describeContents(); |
| 116 | } else { |
| 117 | return 0; |
| 118 | } |
| 119 | } |
| 120 | |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 121 | @Override |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 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); |
Shukang Zhou | 6ffd4f9 | 2017-01-25 16:07:57 -0800 | [diff] [blame] | 132 | out.writeInt(streamingOutput ? 1 : 0); |
Andreas Gampe | 83085bb | 2017-06-26 17:54:11 -0700 | [diff] [blame] | 133 | out.writeString(agent); |
Andreas Gampe | ab8a63b | 2018-01-05 13:55:15 -0800 | [diff] [blame] | 134 | out.writeBoolean(attachAgentDuringBind); |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 135 | } |
| 136 | |
Yi Jin | 148d7f4 | 2017-11-28 14:23:56 -0800 | [diff] [blame] | 137 | /** @hide */ |
| 138 | public void writeToProto(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 | |
Jeff Sharkey | 9e8f83d | 2019-02-28 12:06:45 -0700 | [diff] [blame] | 151 | public static final @android.annotation.NonNull Parcelable.Creator<ProfilerInfo> CREATOR = |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 152 | new Parcelable.Creator<ProfilerInfo>() { |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 153 | @Override |
| 154 | public ProfilerInfo createFromParcel(Parcel in) { |
| 155 | return new ProfilerInfo(in); |
| 156 | } |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 157 | |
Andreas Gampe | 2b073a0 | 2017-06-22 17:28:57 -0700 | [diff] [blame] | 158 | @Override |
| 159 | public ProfilerInfo[] newArray(int size) { |
| 160 | return new ProfilerInfo[size]; |
| 161 | } |
| 162 | }; |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 163 | |
| 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; |
Shukang Zhou | 6ffd4f9 | 2017-01-25 16:07:57 -0800 | [diff] [blame] | 169 | streamingOutput = in.readInt() != 0; |
Andreas Gampe | 83085bb | 2017-06-26 17:54:11 -0700 | [diff] [blame] | 170 | agent = in.readString(); |
Andreas Gampe | ab8a63b | 2018-01-05 13:55:15 -0800 | [diff] [blame] | 171 | attachAgentDuringBind = in.readBoolean(); |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 172 | } |
Andrii Kulian | 6b9d3a1 | 2017-11-16 14:36:36 -0800 | [diff] [blame] | 173 | |
| 174 | @Override |
| 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 |
| 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 | } |
Jeff Hao | 1b012d3 | 2014-08-20 10:35:34 -0700 | [diff] [blame] | 201 | } |