Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit baf12eeb authored by Rambo Wang's avatar Rambo Wang Committed by Android (Google) Code Review
Browse files

Merge "Add Developer option to enable vendor logging in Settings app"

parents 6980bebe 9b7acf72
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ android_library {
        "settings-logtags",
        "statslog-settings",
        "zxing-core-1.7",
        "android.hardware.dumpstate-V1.0-java",
        "android.hardware.dumpstate-V1.1-java",
    ],

    libs: [
+6 −0
Original line number Diff line number Diff line
@@ -151,6 +151,12 @@
            android:title="@string/bugreport_in_power"
            android:summary="@string/bugreport_in_power_summary" />

        <SwitchPreference
            android:key="enable_verbose_vendor_logging"
            android:title="@string/enable_verbose_vendor_logging"
            android:summary="@string/enable_verbose_vendor_logging_summary"
            />

        <SwitchPreference
            android:key="automatic_system_server_heap_dumps"
            android:title="@string/automatic_system_heap_dump_title"
+1 −0
Original line number Diff line number Diff line
@@ -451,6 +451,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
        controllers.add(new SelectDebugAppPreferenceController(context, fragment));
        controllers.add(new WaitForDebuggerPreferenceController(context));
        controllers.add(new EnableGpuDebugLayersPreferenceController(context));
        controllers.add(new EnableVerboseVendorLoggingPreferenceController(context));
        controllers.add(new VerifyAppsOverUsbPreferenceController(context));
        controllers.add(new ArtVerifierPreferenceController(context));
        controllers.add(new LogdSizePreferenceController(context));
+159 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.settings.development;

import android.annotation.Nullable;
import android.content.Context;
import android.hardware.dumpstate.V1_0.IDumpstateDevice;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;

import java.util.NoSuchElementException;

public class EnableVerboseVendorLoggingPreferenceController
        extends DeveloperOptionsPreferenceController
        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {

    private static final String TAG = "EnableVerboseVendorLoggingPreferenceController";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);

    private static final String ENABLE_VERBOSE_VENDOR_LOGGING_KEY = "enable_verbose_vendor_logging";
    private static final int DUMPSTATE_HAL_VERSION_UNKNOWN = -1;
    private static final int DUMPSTATE_HAL_VERSION_1_0 = 0;
    private static final int DUMPSTATE_HAL_VERSION_1_1 = 1;

    private int mDumpstateHalVersion;

    public EnableVerboseVendorLoggingPreferenceController(Context context) {
        super(context);
        mDumpstateHalVersion = DUMPSTATE_HAL_VERSION_UNKNOWN;
    }

    @Override
    public String getPreferenceKey() {
        return ENABLE_VERBOSE_VENDOR_LOGGING_KEY;
    }

    @Override
    public boolean isAvailable() {
        // Only show preference when IDumpstateDevice v1.1 is avalaible
        // This is temperary strategy that may change later.
        return isIDumpstateDeviceV1_1ServiceAvailable();
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        final boolean isEnabled = (Boolean) newValue;
        setVerboseLoggingEnabled(isEnabled);
        return true;
    }

    @Override
    public void updateState(Preference preference) {
        final boolean enabled = getVerboseLoggingEnabled();
        ((SwitchPreference) mPreference).setChecked(enabled);
    }

    @Override
    protected void onDeveloperOptionsSwitchDisabled() {
        super.onDeveloperOptionsSwitchDisabled();
        setVerboseLoggingEnabled(false);
        ((SwitchPreference) mPreference).setChecked(false);
    }

    @VisibleForTesting
    boolean isIDumpstateDeviceV1_1ServiceAvailable() {
        IDumpstateDevice service = getDumpstateDeviceService();
        if (service == null) {
            if (DBG) Log.d(TAG, "IDumpstateDevice service is not available.");
        }
        return service != null && mDumpstateHalVersion >= DUMPSTATE_HAL_VERSION_1_1;
    }

    @VisibleForTesting
    void setVerboseLoggingEnabled(boolean enable) {
        IDumpstateDevice service = getDumpstateDeviceService();

        if (service == null || mDumpstateHalVersion < DUMPSTATE_HAL_VERSION_1_1) {
            if (DBG) Log.d(TAG, "setVerboseLoggingEnabled not supported.");
            return;
        }

        try {
            android.hardware.dumpstate.V1_1.IDumpstateDevice service11 =
                    (android.hardware.dumpstate.V1_1.IDumpstateDevice) service;
            if (service11 != null) {
                service11.setVerboseLoggingEnabled(enable);
            }
        } catch (RemoteException | RuntimeException e) {
            if (DBG) Log.e(TAG, "setVerboseLoggingEnabled fail: " + e);
        }
    }

    @VisibleForTesting
    boolean getVerboseLoggingEnabled() {
        IDumpstateDevice service = getDumpstateDeviceService();

        if (service == null || mDumpstateHalVersion < DUMPSTATE_HAL_VERSION_1_1) {
            if (DBG) Log.d(TAG, "getVerboseLoggingEnabled not supported.");
            return false;
        }

        try {
            android.hardware.dumpstate.V1_1.IDumpstateDevice service11 =
                    (android.hardware.dumpstate.V1_1.IDumpstateDevice) service;
            if (service11 != null) {
                return service11.getVerboseLoggingEnabled();
            }
        } catch (RemoteException | RuntimeException e) {
            if (DBG) Log.e(TAG, "getVerboseLoggingEnabled fail: " + e);
        }
        return false;
    }

    /** Return a {@IDumpstateDevice} instance or null if service is not available. */
    private @Nullable IDumpstateDevice getDumpstateDeviceService() {
        IDumpstateDevice service = null;
        try {
            service = android.hardware.dumpstate.V1_1.IDumpstateDevice
                    .getService(true /* retry */);
            mDumpstateHalVersion = DUMPSTATE_HAL_VERSION_1_1;
        } catch (NoSuchElementException | RemoteException e) {
        }

        if (service == null) {
            try {
                service = android.hardware.dumpstate.V1_0.IDumpstateDevice
                        .getService(true /* retry */);
                mDumpstateHalVersion = DUMPSTATE_HAL_VERSION_1_0;
            } catch (NoSuchElementException | RemoteException e) {
            }
        }

        if (service == null) {
            mDumpstateHalVersion = DUMPSTATE_HAL_VERSION_UNKNOWN;
        }
        return service;
    }
}
+102 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.settings.development;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;

import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@RunWith(RobolectricTestRunner.class)
public final class EnableVerboseVendorLoggingPreferenceControllerTest {
    @Mock
    private SwitchPreference mPreference;
    @Mock
    private PreferenceScreen mPreferenceScreen;

    private Context mContext;
    private EnableVerboseVendorLoggingPreferenceController mController;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;
        mController = new EnableVerboseVendorLoggingPreferenceController(mContext);

        // bypass if IDumpstateDevice service not avalaible at all
        org.junit.Assume.assumeTrue(mController.isIDumpstateDeviceV1_1ServiceAvailable());

        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
                .thenReturn(mPreference);
        mController.displayPreference(mPreferenceScreen);
    }

    @Test
    public void onPreferenceChange_settingEnable_enableVendorLoggingShouldBeOn() {
        mController.onPreferenceChange(mPreference, true /* new value */);

        final boolean enabled = mController.getVerboseLoggingEnabled();
        assertTrue(enabled);
    }

    @Test
    public void onPreferenceChange_settingDisable_enableVendorLoggingShouldBeOff() {
        mController.onPreferenceChange(mPreference,  false /* new value */);

        final boolean enabled = mController.getVerboseLoggingEnabled();
        assertFalse(enabled);
    }

    @Test
    public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
        mController.setVerboseLoggingEnabled(false);
        mController.updateState(mPreference);

        verify(mPreference).setChecked(false);
    }

    @Test
    public void updateState_settingEnabled_preferenceShouldBeChecked() {
        mController.setVerboseLoggingEnabled(true);
        mController.updateState(mPreference);

        verify(mPreference).setChecked(true);
    }

    @Test
    public void onDeveloperOptionDisabled_shouldDisablePreference() {
        mController.onDeveloperOptionsSwitchDisabled();

        final boolean enabled = mController.getVerboseLoggingEnabled();
        assertFalse(enabled);
        verify(mPreference).setChecked(false);
        verify(mPreference).setEnabled(false);
    }
}