Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2017 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.net.util;
     18 
     19 import android.text.TextUtils;
     20 import android.util.LocalLog;
     21 import android.util.Log;
     22 
     23 import java.io.FileDescriptor;
     24 import java.io.PrintWriter;
     25 import java.util.StringJoiner;
     26 
     27 
     28 /**
     29  * Class to centralize logging functionality for tethering.
     30  *
     31  * All access to class methods other than dump() must be on the same thread.
     32  *
     33  * @hide
     34  */
     35 public class SharedLog {
     36     private final static int DEFAULT_MAX_RECORDS = 500;
     37     private final static String COMPONENT_DELIMITER = ".";
     38 
     39     private enum Category {
     40         NONE,
     41         ERROR,
     42         MARK,
     43         WARN,
     44     };
     45 
     46     private final LocalLog mLocalLog;
     47     // The tag to use for output to the system log. This is not output to the
     48     // LocalLog because that would be redundant.
     49     private final String mTag;
     50     // The component (or subcomponent) of a system that is sharing this log.
     51     // This can grow in depth if components call forSubComponent() to obtain
     52     // their SharedLog instance. The tag is not included in the component for
     53     // brevity.
     54     private final String mComponent;
     55 
     56     public SharedLog(String tag) {
     57         this(DEFAULT_MAX_RECORDS, tag);
     58     }
     59 
     60     public SharedLog(int maxRecords, String tag) {
     61         this(new LocalLog(maxRecords), tag, tag);
     62     }
     63 
     64     private SharedLog(LocalLog localLog, String tag, String component) {
     65         mLocalLog = localLog;
     66         mTag = tag;
     67         mComponent = component;
     68     }
     69 
     70     public SharedLog forSubComponent(String component) {
     71         if (!isRootLogInstance()) {
     72             component = mComponent + COMPONENT_DELIMITER + component;
     73         }
     74         return new SharedLog(mLocalLog, mTag, component);
     75     }
     76 
     77     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
     78         mLocalLog.readOnlyLocalLog().dump(fd, writer, args);
     79     }
     80 
     81     //////
     82     // Methods that both log an entry and emit it to the system log.
     83     //////
     84 
     85     public void e(Exception e) {
     86         Log.e(mTag, record(Category.ERROR, e.toString()));
     87     }
     88 
     89     public void e(String msg) {
     90         Log.e(mTag, record(Category.ERROR, msg));
     91     }
     92 
     93     public void i(String msg) {
     94         Log.i(mTag, record(Category.NONE, msg));
     95     }
     96 
     97     public void w(String msg) {
     98         Log.w(mTag, record(Category.WARN, msg));
     99     }
    100 
    101     //////
    102     // Methods that only log an entry (and do NOT emit to the system log).
    103     //////
    104 
    105     public void log(String msg) {
    106         record(Category.NONE, msg);
    107     }
    108 
    109     public void logf(String fmt, Object... args) {
    110         log(String.format(fmt, args));
    111     }
    112 
    113     public void mark(String msg) {
    114         record(Category.MARK, msg);
    115     }
    116 
    117     private String record(Category category, String msg) {
    118         final String entry = logLine(category, msg);
    119         mLocalLog.log(entry);
    120         return entry;
    121     }
    122 
    123     private String logLine(Category category, String msg) {
    124         final StringJoiner sj = new StringJoiner(" ");
    125         if (!isRootLogInstance()) sj.add("[" + mComponent + "]");
    126         if (category != Category.NONE) sj.add(category.toString());
    127         return sj.add(msg).toString();
    128     }
    129 
    130     // Check whether this SharedLog instance is nominally the top level in
    131     // a potential hierarchy of shared logs (the root of a tree),
    132     // or is a subcomponent within the hierarchy.
    133     private boolean isRootLogInstance() {
    134         return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag);
    135     }
    136 }
    137