• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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