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 AbstractLogdSizePreferenceController(Context context)60 public AbstractLogdSizePreferenceController(Context context) { 61 super(context); 62 } 63 64 @Override getPreferenceKey()65 public String getPreferenceKey() { 66 return SELECT_LOGD_SIZE_KEY; 67 } 68 69 @Override displayPreference(PreferenceScreen screen)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 onPreferenceChange(Preference preference, Object newValue)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 enablePreference(boolean enabled)87 public void enablePreference(boolean enabled) { 88 if (isAvailable()) { 89 mLogdSize.setEnabled(enabled); 90 } 91 } 92 defaultLogdSizeValue()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 updateLogdSizeValues()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 writeLogdSizeOption(Object newValue)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