1 /*
2  * Copyright (C) 2016 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.admin;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 import java.net.InetAddress;
23 import java.net.UnknownHostException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.List;
27 
28 /**
29  * A class that represents a DNS lookup event initiated through the standard network stack.
30  *
31  * <p>It contains information about the originating app as well as the DNS hostname and resolved
32  * IP addresses.
33  */
34 public final class DnsEvent extends NetworkEvent implements Parcelable {
35 
36     /** The hostname that was looked up. */
37     private final String mHostname;
38 
39     /** Contains (possibly a subset of) the IP addresses returned. */
40     private final String[] mIpAddresses;
41 
42     /**
43      * The number of IP addresses returned from the DNS lookup event. May be different from the
44      * length of ipAddresses if there were too many addresses to log.
45      */
46     private final int mIpAddressesCount;
47 
48     /** @hide */
DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount, String packageName, long timestamp)49     public DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
50             String packageName, long timestamp) {
51         super(packageName, timestamp);
52         this.mHostname = hostname;
53         this.mIpAddresses = ipAddresses;
54         this.mIpAddressesCount = ipAddressesCount;
55     }
56 
DnsEvent(Parcel in)57     private DnsEvent(Parcel in) {
58         this.mHostname = in.readString();
59         this.mIpAddresses = in.createStringArray();
60         this.mIpAddressesCount = in.readInt();
61         this.mPackageName = in.readString();
62         this.mTimestamp = in.readLong();
63         this.mId = in.readLong();
64     }
65 
66     /** Returns the hostname that was looked up. */
getHostname()67     public String getHostname() {
68         return mHostname;
69     }
70 
71     /** Returns (possibly a subset of) the IP addresses returned. */
getInetAddresses()72     public List<InetAddress> getInetAddresses() {
73         if (mIpAddresses == null || mIpAddresses.length == 0) {
74             return Collections.emptyList();
75         }
76         final List<InetAddress> inetAddresses = new ArrayList<>(mIpAddresses.length);
77         for (final String ipAddress : mIpAddresses) {
78             try {
79                 // ipAddress is already an address, not a host name, no DNS resolution will happen.
80                 inetAddresses.add(InetAddress.getByName(ipAddress));
81             } catch (UnknownHostException e) {
82                 // Should never happen as we aren't passing a host name.
83             }
84         }
85         return inetAddresses;
86     }
87 
88     /**
89      * Returns the number of IP addresses returned from the DNS lookup event. May be different from
90      * the length of the list returned by {@link #getInetAddresses()} if there were too many
91      * addresses to log.
92      */
getTotalResolvedAddressCount()93     public int getTotalResolvedAddressCount() {
94         return mIpAddressesCount;
95     }
96 
97     @Override
toString()98     public String toString() {
99         return String.format("DnsEvent(%d, %s, %s, %d, %d, %s)", mId, mHostname,
100                 (mIpAddresses == null) ? "NONE" : String.join(" ", mIpAddresses),
101                 mIpAddressesCount, mTimestamp, mPackageName);
102     }
103 
104     public static final @android.annotation.NonNull Parcelable.Creator<DnsEvent> CREATOR
105             = new Parcelable.Creator<DnsEvent>() {
106         @Override
107         public DnsEvent createFromParcel(Parcel in) {
108             if (in.readInt() != PARCEL_TOKEN_DNS_EVENT) {
109                 return null;
110             }
111             return new DnsEvent(in);
112         }
113 
114         @Override
115         public DnsEvent[] newArray(int size) {
116             return new DnsEvent[size];
117         }
118     };
119 
120     @Override
describeContents()121     public int describeContents() {
122         return 0;
123     }
124 
125     @Override
writeToParcel(Parcel out, int flags)126     public void writeToParcel(Parcel out, int flags) {
127         // write parcel token first
128         out.writeInt(PARCEL_TOKEN_DNS_EVENT);
129         out.writeString(mHostname);
130         out.writeStringArray(mIpAddresses);
131         out.writeInt(mIpAddressesCount);
132         out.writeString(mPackageName);
133         out.writeLong(mTimestamp);
134         out.writeLong(mId);
135     }
136 }
137