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 |