Home | History | Annotate | Download | only in app
      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 
     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 
     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      */
     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      */
    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
    113     public int describeContents() {
    114         if (profileFd != null) {
    115             return profileFd.describeContents();
    116         } else {
    117             return 0;
    118         }
    119     }
    120 
    121     @Override
    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 */
    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 
    151     public static final 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 
    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
    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     }
    201 }
    202