Home | History | Annotate | Download | only in development
      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 com.android.settingslib.development;
     18 
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.os.SystemProperties;
     22 import android.support.annotation.VisibleForTesting;
     23 import android.support.v4.content.LocalBroadcastManager;
     24 import android.support.v7.preference.ListPreference;
     25 import android.support.v7.preference.Preference;
     26 import android.support.v7.preference.PreferenceScreen;
     27 
     28 import com.android.settingslib.R;
     29 
     30 public abstract class AbstractLogdSizePreferenceController extends
     31         DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
     32     public static final String ACTION_LOGD_SIZE_UPDATED = "com.android.settingslib.development."
     33             + "AbstractLogdSizePreferenceController.LOGD_SIZE_UPDATED";
     34     public static final String EXTRA_CURRENT_LOGD_VALUE = "CURRENT_LOGD_VALUE";
     35 
     36     @VisibleForTesting
     37     static final String LOW_RAM_CONFIG_PROPERTY_KEY = "ro.config.low_ram";
     38     private static final String SELECT_LOGD_SIZE_KEY = "select_logd_size";
     39     @VisibleForTesting
     40     static final String SELECT_LOGD_SIZE_PROPERTY = "persist.logd.size";
     41     static final String SELECT_LOGD_TAG_PROPERTY = "persist.log.tag";
     42     // Tricky, isLoggable only checks for first character, assumes silence
     43     static final String SELECT_LOGD_TAG_SILENCE = "Settings";
     44     @VisibleForTesting
     45     static final String SELECT_LOGD_SNET_TAG_PROPERTY = "persist.log.tag.snet_event_log";
     46     private static final String SELECT_LOGD_RUNTIME_SNET_TAG_PROPERTY = "log.tag.snet_event_log";
     47     private static final String SELECT_LOGD_DEFAULT_SIZE_PROPERTY = "ro.logd.size";
     48     @VisibleForTesting
     49     static final String SELECT_LOGD_DEFAULT_SIZE_VALUE = "262144";
     50     private static final String SELECT_LOGD_SVELTE_DEFAULT_SIZE_VALUE = "65536";
     51     // 32768 is merely a menu marker, 64K is our lowest log buffer size we replace it with.
     52     @VisibleForTesting
     53     static final String SELECT_LOGD_MINIMUM_SIZE_VALUE = "65536";
     54     static final String SELECT_LOGD_OFF_SIZE_MARKER_VALUE = "32768";
     55     @VisibleForTesting
     56     static final String DEFAULT_SNET_TAG = "I";
     57 
     58     private ListPreference mLogdSize;
     59 
     60     public AbstractLogdSizePreferenceController(Context context) {
     61         super(context);
     62     }
     63 
     64     @Override
     65     public String getPreferenceKey() {
     66         return SELECT_LOGD_SIZE_KEY;
     67     }
     68 
     69     @Override
     70     public void displayPreference(PreferenceScreen screen) {
     71         super.displayPreference(screen);
     72         if (isAvailable()) {
     73             mLogdSize = (ListPreference) screen.findPreference(SELECT_LOGD_SIZE_KEY);
     74         }
     75     }
     76 
     77     @Override
     78     public boolean onPreferenceChange(Preference preference, Object newValue) {
     79         if (preference == mLogdSize) {
     80             writeLogdSizeOption(newValue);
     81             return true;
     82         } else {
     83             return false;
     84         }
     85     }
     86 
     87     public void enablePreference(boolean enabled) {
     88         if (isAvailable()) {
     89             mLogdSize.setEnabled(enabled);
     90         }
     91     }
     92 
     93     private String defaultLogdSizeValue() {
     94         String defaultValue = SystemProperties.get(SELECT_LOGD_DEFAULT_SIZE_PROPERTY);
     95         if ((defaultValue == null) || (defaultValue.length() == 0)) {
     96             if (SystemProperties.get("ro.config.low_ram").equals("true")) {
     97                 defaultValue = SELECT_LOGD_SVELTE_DEFAULT_SIZE_VALUE;
     98             } else {
     99                 defaultValue = SELECT_LOGD_DEFAULT_SIZE_VALUE;
    100             }
    101         }
    102         return defaultValue;
    103     }
    104 
    105     public void updateLogdSizeValues() {
    106         if (mLogdSize != null) {
    107             String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);
    108             String currentValue = SystemProperties.get(SELECT_LOGD_SIZE_PROPERTY);
    109             if ((currentTag != null) && currentTag.startsWith(SELECT_LOGD_TAG_SILENCE)) {
    110                 currentValue = SELECT_LOGD_OFF_SIZE_MARKER_VALUE;
    111             }
    112             LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(
    113                     new Intent(ACTION_LOGD_SIZE_UPDATED)
    114                             .putExtra(EXTRA_CURRENT_LOGD_VALUE, currentValue));
    115             if ((currentValue == null) || (currentValue.length() == 0)) {
    116                 currentValue = defaultLogdSizeValue();
    117             }
    118             String[] values = mContext.getResources()
    119                     .getStringArray(R.array.select_logd_size_values);
    120             String[] titles = mContext.getResources()
    121                     .getStringArray(R.array.select_logd_size_titles);
    122             int index = 2; // punt to second entry if not found
    123             if (SystemProperties.get("ro.config.low_ram").equals("true")) {
    124                 mLogdSize.setEntries(R.array.select_logd_size_lowram_titles);
    125                 titles = mContext.getResources()
    126                         .getStringArray(R.array.select_logd_size_lowram_titles);
    127                 index = 1;
    128             }
    129             String[] summaries = mContext.getResources()
    130                     .getStringArray(R.array.select_logd_size_summaries);
    131             for (int i = 0; i < titles.length; i++) {
    132                 if (currentValue.equals(values[i])
    133                         || currentValue.equals(titles[i])) {
    134                     index = i;
    135                     break;
    136                 }
    137             }
    138             mLogdSize.setValue(values[index]);
    139             mLogdSize.setSummary(summaries[index]);
    140         }
    141     }
    142 
    143     public void writeLogdSizeOption(Object newValue) {
    144         boolean disable = (newValue != null) &&
    145                 (newValue.toString().equals(SELECT_LOGD_OFF_SIZE_MARKER_VALUE));
    146         String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);
    147         if (currentTag == null) {
    148             currentTag = "";
    149         }
    150         // filter clean and unstack all references to our setting
    151         String newTag = currentTag.replaceAll(
    152                 ",+" + SELECT_LOGD_TAG_SILENCE, "").replaceFirst(
    153                 "^" + SELECT_LOGD_TAG_SILENCE + ",*", "").replaceAll(
    154                 ",+", ",").replaceFirst(
    155                 ",+$", "");
    156         if (disable) {
    157             newValue = SELECT_LOGD_MINIMUM_SIZE_VALUE;
    158             // Make sure snet_event_log get through first, but do not override
    159             String snetValue = SystemProperties.get(SELECT_LOGD_SNET_TAG_PROPERTY);
    160             if ((snetValue == null) || (snetValue.length() == 0)) {
    161                 snetValue = SystemProperties.get(SELECT_LOGD_RUNTIME_SNET_TAG_PROPERTY);
    162                 if ((snetValue == null) || (snetValue.length() == 0)) {
    163                     SystemProperties.set(SELECT_LOGD_SNET_TAG_PROPERTY, DEFAULT_SNET_TAG);
    164                 }
    165             }
    166             // Silence all log sources, security logs notwithstanding
    167             if (newTag.length() != 0) {
    168                 newTag = "," + newTag;
    169             }
    170             // Stack settings, stack to help preserve original value
    171             newTag = SELECT_LOGD_TAG_SILENCE + newTag;
    172         }
    173         if (!newTag.equals(currentTag)) {
    174             SystemProperties.set(SELECT_LOGD_TAG_PROPERTY, newTag);
    175         }
    176         String defaultValue = defaultLogdSizeValue();
    177         final String size = ((newValue != null) && (newValue.toString().length() != 0)) ?
    178                 newValue.toString() : defaultValue;
    179         SystemProperties.set(SELECT_LOGD_SIZE_PROPERTY, defaultValue.equals(size) ? "" : size);
    180         SystemProperties.set("ctl.start", "logd-reinit");
    181         SystemPropPoker.getInstance().poke();
    182         updateLogdSizeValues();
    183     }
    184 }
    185