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