| /* |
| * Copyright (C) 2017 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.settingslib.development; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.os.Bundle; |
| import android.os.SystemProperties; |
| import android.support.annotation.VisibleForTesting; |
| import android.support.v4.content.LocalBroadcastManager; |
| import android.support.v7.preference.ListPreference; |
| import android.support.v7.preference.Preference; |
| import android.support.v7.preference.PreferenceScreen; |
| import android.text.TextUtils; |
| |
| import com.android.settingslib.R; |
| import com.android.settingslib.core.AbstractPreferenceController; |
| import com.android.settingslib.core.ConfirmationDialogController; |
| import com.android.settingslib.core.lifecycle.Lifecycle; |
| import com.android.settingslib.core.lifecycle.LifecycleObserver; |
| import com.android.settingslib.core.lifecycle.events.OnCreate; |
| import com.android.settingslib.core.lifecycle.events.OnDestroy; |
| |
| public abstract class AbstractLogpersistPreferenceController extends AbstractPreferenceController |
| implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnCreate, OnDestroy, |
| ConfirmationDialogController { |
| |
| private static final String SELECT_LOGPERSIST_KEY = "select_logpersist"; |
| private static final String SELECT_LOGPERSIST_PROPERTY = "persist.logd.logpersistd"; |
| @VisibleForTesting |
| static final String ACTUAL_LOGPERSIST_PROPERTY = "logd.logpersistd"; |
| @VisibleForTesting |
| static final String SELECT_LOGPERSIST_PROPERTY_SERVICE = "logcatd"; |
| private static final String SELECT_LOGPERSIST_PROPERTY_CLEAR = "clear"; |
| private static final String SELECT_LOGPERSIST_PROPERTY_STOP = "stop"; |
| private static final String SELECT_LOGPERSIST_PROPERTY_BUFFER = |
| "persist.logd.logpersistd.buffer"; |
| @VisibleForTesting |
| static final String ACTUAL_LOGPERSIST_PROPERTY_BUFFER = "logd.logpersistd.buffer"; |
| private static final String ACTUAL_LOGPERSIST_PROPERTY_ENABLE = "logd.logpersistd.enable"; |
| |
| private ListPreference mLogpersist; |
| private boolean mLogpersistCleared; |
| |
| private final BroadcastReceiver mReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| final String currentValue = intent.getStringExtra( |
| AbstractLogdSizePreferenceController.EXTRA_CURRENT_LOGD_VALUE); |
| onLogdSizeSettingUpdate(currentValue); |
| } |
| }; |
| |
| public AbstractLogpersistPreferenceController(Context context, Lifecycle lifecycle) { |
| super(context); |
| if (isAvailable()) { |
| lifecycle.addObserver(this); |
| } |
| } |
| |
| @Override |
| public boolean isAvailable() { |
| return TextUtils.equals(SystemProperties.get("ro.debuggable", "0"), "1"); |
| } |
| |
| @Override |
| public String getPreferenceKey() { |
| return SELECT_LOGPERSIST_KEY; |
| } |
| |
| @Override |
| public void displayPreference(PreferenceScreen screen) { |
| super.displayPreference(screen); |
| if (isAvailable()) { |
| mLogpersist = (ListPreference) screen.findPreference(SELECT_LOGPERSIST_KEY); |
| } |
| } |
| |
| @Override |
| public boolean onPreferenceChange(Preference preference, Object newValue) { |
| if (preference == mLogpersist) { |
| writeLogpersistOption(newValue, false); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| LocalBroadcastManager.getInstance(mContext).registerReceiver(mReceiver, |
| new IntentFilter(AbstractLogdSizePreferenceController.ACTION_LOGD_SIZE_UPDATED)); |
| } |
| |
| @Override |
| public void onDestroy() { |
| LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mReceiver); |
| } |
| |
| public void enablePreference(boolean enabled) { |
| if (isAvailable()) { |
| mLogpersist.setEnabled(enabled); |
| } |
| } |
| |
| private void onLogdSizeSettingUpdate(String currentValue) { |
| if (mLogpersist != null) { |
| String currentLogpersistEnable |
| = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_ENABLE); |
| if ((currentLogpersistEnable == null) |
| || !currentLogpersistEnable.equals("true") |
| || currentValue.equals( |
| AbstractLogdSizePreferenceController.SELECT_LOGD_OFF_SIZE_MARKER_VALUE)) { |
| writeLogpersistOption(null, true); |
| mLogpersist.setEnabled(false); |
| } else if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)) { |
| mLogpersist.setEnabled(true); |
| } |
| } |
| } |
| |
| public void updateLogpersistValues() { |
| if (mLogpersist == null) { |
| return; |
| } |
| String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY); |
| if (currentValue == null) { |
| currentValue = ""; |
| } |
| String currentBuffers = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_BUFFER); |
| if ((currentBuffers == null) || (currentBuffers.length() == 0)) { |
| currentBuffers = "all"; |
| } |
| int index = 0; |
| if (currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) { |
| index = 1; |
| if (currentBuffers.equals("kernel")) { |
| index = 3; |
| } else if (!currentBuffers.equals("all") && |
| !currentBuffers.contains("radio") && |
| currentBuffers.contains("security") && |
| currentBuffers.contains("kernel")) { |
| index = 2; |
| if (!currentBuffers.contains("default")) { |
| String[] contains = {"main", "events", "system", "crash"}; |
| for (String type : contains) { |
| if (!currentBuffers.contains(type)) { |
| index = 1; |
| break; |
| } |
| } |
| } |
| } |
| } |
| mLogpersist.setValue( |
| mContext.getResources().getStringArray(R.array.select_logpersist_values)[index]); |
| mLogpersist.setSummary( |
| mContext.getResources().getStringArray(R.array.select_logpersist_summaries)[index]); |
| if (index != 0) { |
| mLogpersistCleared = false; |
| } else if (!mLogpersistCleared) { |
| // would File.delete() directly but need to switch uid/gid to access |
| SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_CLEAR); |
| SystemPropPoker.getInstance().poke(); |
| mLogpersistCleared = true; |
| } |
| } |
| |
| protected void setLogpersistOff(boolean update) { |
| SystemProperties.set(SELECT_LOGPERSIST_PROPERTY_BUFFER, ""); |
| // deal with trampoline of empty properties |
| SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY_BUFFER, ""); |
| SystemProperties.set(SELECT_LOGPERSIST_PROPERTY, ""); |
| SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY, |
| update ? "" : SELECT_LOGPERSIST_PROPERTY_STOP); |
| SystemPropPoker.getInstance().poke(); |
| if (update) { |
| updateLogpersistValues(); |
| } else { |
| for (int i = 0; i < 3; i++) { |
| String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY); |
| if ((currentValue == null) || currentValue.equals("")) { |
| break; |
| } |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| // Ignore |
| } |
| } |
| } |
| } |
| |
| public void writeLogpersistOption(Object newValue, boolean skipWarning) { |
| if (mLogpersist == null) { |
| return; |
| } |
| String currentTag = SystemProperties.get( |
| AbstractLogdSizePreferenceController.SELECT_LOGD_TAG_PROPERTY); |
| if ((currentTag != null) && currentTag.startsWith( |
| AbstractLogdSizePreferenceController.SELECT_LOGD_TAG_SILENCE)) { |
| newValue = null; |
| skipWarning = true; |
| } |
| |
| if ((newValue == null) || newValue.toString().equals("")) { |
| if (skipWarning) { |
| mLogpersistCleared = false; |
| } else if (!mLogpersistCleared) { |
| // if transitioning from on to off, pop up an are you sure? |
| String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY); |
| if ((currentValue != null) && |
| currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) { |
| showConfirmationDialog(mLogpersist); |
| return; |
| } |
| } |
| setLogpersistOff(true); |
| return; |
| } |
| |
| String currentBuffer = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_BUFFER); |
| if ((currentBuffer != null) && !currentBuffer.equals(newValue.toString())) { |
| setLogpersistOff(false); |
| } |
| SystemProperties.set(SELECT_LOGPERSIST_PROPERTY_BUFFER, newValue.toString()); |
| SystemProperties.set(SELECT_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_SERVICE); |
| SystemPropPoker.getInstance().poke(); |
| for (int i = 0; i < 3; i++) { |
| String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY); |
| if ((currentValue != null) |
| && currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) { |
| break; |
| } |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| // Ignore |
| } |
| } |
| updateLogpersistValues(); |
| } |
| } |