diff options
| -rw-r--r-- | core/java/com/android/internal/util/MessageUtils.java | 127 | ||||
| -rw-r--r-- | services/net/java/android/net/dhcp/DhcpClient.java | 35 | ||||
| -rw-r--r-- | services/net/java/android/net/ip/IpManager.java | 29 |
3 files changed, 144 insertions, 47 deletions
diff --git a/core/java/com/android/internal/util/MessageUtils.java b/core/java/com/android/internal/util/MessageUtils.java new file mode 100644 index 000000000000..1014bfd6955d --- /dev/null +++ b/core/java/com/android/internal/util/MessageUtils.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import android.os.Message; +import android.util.Log; +import android.util.SparseArray; + +import java.lang.reflect.Field; + +/** + * Static utility class for dealing with {@link Message} objects. + */ +public class MessageUtils { + + private static final String TAG = MessageUtils.class.getSimpleName(); + private static final boolean DBG = false; + + /** Thrown when two different constants have the same value. */ + public static class DuplicateConstantError extends Error { + private DuplicateConstantError() {} + public DuplicateConstantError(String name1, String name2, int value) { + super(String.format("Duplicate constant value: both %s and %s = %d", + name1, name2, value)); + } + } + + /** + * Finds the names of integer constants. Searches the specified {@code classes}, looking for + * accessible static integer fields whose names begin with one of the specified {@prefixes}. + * + * @param classes the classes to examine. + * @prefixes only consider fields names starting with one of these prefixes. + * @return a {@link SparseArray} mapping integer constants to their names. + */ + public static SparseArray<String> findMessageNames(Class[] classes, String[] prefixes) { + SparseArray<String> messageNames = new SparseArray<>(); + for (Class c : classes) { + String className = c.getName(); + if (DBG) Log.d(TAG, "Examining class " + className); + + Field[] fields; + try { + fields = c.getDeclaredFields(); + } catch (SecurityException e) { + Log.e(TAG, "Can't list fields of class " + className); + continue; + } + + for (Field field : fields) { + String name = field.getName(); + + for (String prefix : prefixes) { + // Does this look like a constant? + if (!name.startsWith(prefix)) { + continue; + } + + try { + // TODO: can we have the caller try to access the field instead, so we don't + // expose constants it does not have access to? + field.setAccessible(true); + + // Fetch the constant's value. + int value; + try { + value = field.getInt(null); + } catch (IllegalArgumentException | ExceptionInInitializerError e) { + // The field is not an integer (or short or byte), or c's static + // initializer failed and we have no idea what its value is. + // Either way, give up on this field. + break; + } + + // Check for duplicate values. + String previousName = messageNames.get(value); + if (previousName != null && !previousName.equals(name)) { + throw new DuplicateConstantError(name, previousName, value); + } + + messageNames.put(value, name); + if (DBG) { + Log.d(TAG, String.format("Found constant: %s.%s = %d", + className, name, value)); + } + } catch (SecurityException | IllegalAccessException e) { + // Not allowed to make the field accessible, or no access. Ignore. + continue; + } + } + } + } + return messageNames; + } + + /** + * Default prefixes for constants. + */ + public static final String[] DEFAULT_PREFIXES = {"CMD_", "EVENT_"}; + + /** + * Finds the names of integer constants. Searches the specified {@code classes}, looking for + * accessible static integer values whose names begin with {@link #DEFAULT_PREFIXES}. + * + * @param classNames the classes to examine. + * @prefixes only consider fields names starting with one of these prefixes. + * @return a {@link SparseArray} mapping integer constants to their names. + */ + public static SparseArray<String> findMessageNames(Class[] classNames) { + return findMessageNames(classNames, DEFAULT_PREFIXES); + } +} + diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index 5229b40528c5..4f99bffe245b 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -19,6 +19,7 @@ package android.net.dhcp; import com.android.internal.util.HexDump; import com.android.internal.util.Protocol; import com.android.internal.util.State; +import com.android.internal.util.MessageUtils; import com.android.internal.util.StateMachine; import com.android.internal.util.WakeupMessage; @@ -32,7 +33,6 @@ import android.net.NetworkUtils; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Message; -import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -40,16 +40,15 @@ import android.system.ErrnoException; import android.system.Os; import android.system.PacketSocketAddress; import android.util.Log; +import android.util.SparseArray; import android.util.TimeUtils; import java.io.FileDescriptor; import java.io.IOException; import java.lang.Thread; import java.net.Inet4Address; -import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketException; -import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Random; @@ -131,6 +130,11 @@ public class DhcpClient extends StateMachine { private static final int CMD_TIMEOUT = PRIVATE_BASE + 3; private static final int CMD_ONESHOT_TIMEOUT = PRIVATE_BASE + 4; + // For message logging. + private static final Class[] sMessageClasses = { DhcpClient.class }; + private static final SparseArray<String> sMessageNames = + MessageUtils.findMessageNames(sMessageClasses); + // DHCP parameters that we request. private static final byte[] REQUESTED_PARAMS = new byte[] { DHCP_SUBNET_MASK, @@ -460,30 +464,7 @@ public class DhcpClient extends StateMachine { } private String messageName(int what) { - switch (what) { - case CMD_START_DHCP: - return "CMD_START_DHCP"; - case CMD_STOP_DHCP: - return "CMD_STOP_DHCP"; - case CMD_RENEW_DHCP: - return "CMD_RENEW_DHCP"; - case CMD_PRE_DHCP_ACTION: - return "CMD_PRE_DHCP_ACTION"; - case CMD_PRE_DHCP_ACTION_COMPLETE: - return "CMD_PRE_DHCP_ACTION_COMPLETE"; - case CMD_POST_DHCP_ACTION: - return "CMD_POST_DHCP_ACTION"; - case CMD_KICK: - return "CMD_KICK"; - case CMD_RECEIVED_PACKET: - return "CMD_RECEIVED_PACKET"; - case CMD_TIMEOUT: - return "CMD_TIMEOUT"; - case CMD_ONESHOT_TIMEOUT: - return "CMD_ONESHOT_TIMEOUT"; - default: - return Integer.toString(what); - } + return sMessageNames.get(what, Integer.toString(what)); } private String messageToString(Message message) { diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java index d0d87b19ba98..61f2c8afcf58 100644 --- a/services/net/java/android/net/ip/IpManager.java +++ b/services/net/java/android/net/ip/IpManager.java @@ -16,6 +16,8 @@ package android.net.ip; +import com.android.internal.util.MessageUtils; + import android.content.Context; import android.net.DhcpResults; import android.net.InterfaceConfiguration; @@ -30,6 +32,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -61,6 +64,11 @@ public class IpManager extends StateMachine { private static final boolean DBG = true; private static final boolean VDBG = false; + // For message logging. + private static final Class[] sMessageClasses = { IpManager.class, DhcpClient.class }; + private static final SparseArray<String> sWhatToString = + MessageUtils.findMessageNames(sMessageClasses); + /** * Callbacks for handling IpManager events. */ @@ -306,26 +314,7 @@ public class IpManager extends StateMachine { @Override protected String getWhatToString(int what) { - // TODO: Investigate switching to reflection. - switch (what) { - case CMD_STOP: - return "CMD_STOP"; - case CMD_START: - return "CMD_START"; - case CMD_CONFIRM: - return "CMD_CONFIRM"; - case EVENT_PRE_DHCP_ACTION_COMPLETE: - return "EVENT_PRE_DHCP_ACTION_COMPLETE"; - case EVENT_NETLINK_LINKPROPERTIES_CHANGED: - return "EVENT_NETLINK_LINKPROPERTIES_CHANGED"; - case DhcpClient.CMD_PRE_DHCP_ACTION: - return "DhcpClient.CMD_PRE_DHCP_ACTION"; - case DhcpClient.CMD_POST_DHCP_ACTION: - return "DhcpClient.CMD_POST_DHCP_ACTION"; - case DhcpClient.CMD_ON_QUIT: - return "DhcpClient.CMD_ON_QUIT"; - } - return "UNKNOWN:" + Integer.toString(what); + return sWhatToString.get(what, "UNKNOWN: " + Integer.toString(what)); } @Override |