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

Commit 5965a10f authored by Jaewan Kim's avatar Jaewan Kim Committed by Gerrit Code Review
Browse files

Merge "Hide Linux terminal if device doesn't meet minimum requirement" into main

parents fb6902d8 a6334bc0
Loading
Loading
Loading
Loading
+27 −3
Original line number Diff line number Diff line
@@ -18,7 +18,10 @@ package com.android.settings.development.linuxterminal;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.DataUnit;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,30 +31,45 @@ import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;

import java.util.Objects;

/** Preference controller for Linux terminal option in developers option */
public class LinuxTerminalPreferenceController extends DeveloperOptionsPreferenceController
        implements PreferenceControllerMixin {
    @VisibleForTesting
    static final int TERMINAL_PACKAGE_NAME_RESID = R.string.config_linux_terminal_app_package_name;

    @VisibleForTesting
    static final long MEMORY_MIN_BYTES = DataUnit.GIGABYTES.toBytes(4); // 4_000_000_000

    @VisibleForTesting
    static final long STORAGE_MIN_BYTES = DataUnit.GIBIBYTES.toBytes(128); // 128 * 2^30

    private static final String LINUX_TERMINAL_KEY = "linux_terminal";

    @Nullable private final String mTerminalPackageName;
    private final boolean mIsDeviceCapable;

    public LinuxTerminalPreferenceController(@NonNull Context context) {
        super(context);
        String packageName = context.getString(TERMINAL_PACKAGE_NAME_RESID);
        mTerminalPackageName =
                isPackageInstalled(context.getPackageManager(), packageName) ? packageName : null;

        StorageManager storageManager =
                Objects.requireNonNull(context.getSystemService(StorageManager.class));
        mIsDeviceCapable =
                getTotalMemory() >= MEMORY_MIN_BYTES
                        && storageManager.getPrimaryStorageSize() >= STORAGE_MIN_BYTES;
    }

    // Avoid lazy initialization because this may be called before displayPreference().
    @Override
    public boolean isAvailable() {
        // Returns true only if the terminal app is installed which only happens when the build flag
        // RELEASE_AVF_SUPPORT_CUSTOM_VM_WITH_PARAVIRTUALIZED_DEVICES is true.
        // Check build flag RELEASE_AVF_SUPPORT_CUSTOM_VM_WITH_PARAVIRTUALIZED_DEVICES indirectly
        // by checking whether the terminal app is installed.
        // TODO(b/343795511): Add explicitly check for the flag when it's accessible from Java code.
        return mTerminalPackageName != null;
        return mTerminalPackageName != null && mIsDeviceCapable;
    }

    @Override
@@ -73,4 +91,10 @@ public class LinuxTerminalPreferenceController extends DeveloperOptionsPreferenc
            return false;
        }
    }

    // Can be overridden for test
    @VisibleForTesting
    long getTotalMemory() {
        return Process.getTotalMemory();
    }
}
+40 −4
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.settings.development.linuxterminal;

import static com.android.settings.development.linuxterminal.LinuxTerminalPreferenceController.MEMORY_MIN_BYTES;
import static com.android.settings.development.linuxterminal.LinuxTerminalPreferenceController.STORAGE_MIN_BYTES;
import static com.android.settings.development.linuxterminal.LinuxTerminalPreferenceController.TERMINAL_PACKAGE_NAME_RESID;

import static com.google.common.truth.Truth.assertThat;
@@ -29,6 +31,7 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.storage.StorageManager;

import org.junit.Before;
import org.junit.Test;
@@ -43,6 +46,7 @@ public class LinuxTerminalPreferenceControllerTest {

    @Mock private Context mContext;
    @Mock private PackageManager mPackageManager;
    @Mock private StorageManager mStorageManager;
    @Mock private PackageInfo mPackageInfo;

    private String mTerminalPackageName = "com.android.virtualization.terminal";
@@ -57,11 +61,30 @@ public class LinuxTerminalPreferenceControllerTest {
        doReturn(mPackageInfo)
                .when(mPackageManager)
                .getPackageInfo(eq(mTerminalPackageName), anyInt());

        doReturn(mStorageManager).when(mContext).getSystemService(StorageManager.class);
        doReturn(STORAGE_MIN_BYTES).when(mStorageManager).getPrimaryStorageSize();
    }

    @Test
    public void isAvailable_whenPackageExists_returnsTrue() throws NameNotFoundException {
        mController = new LinuxTerminalPreferenceController(mContext);
    public void isAvailable_whenMemoryInsufficient_returnFalse() {
        mController = createController(mContext, MEMORY_MIN_BYTES / 2);

        assertThat(mController.isAvailable()).isFalse();
    }

    @Test
    public void isAvailable_whenDeviceStorageInsufficient_returnFalse() {
        doReturn(STORAGE_MIN_BYTES / 2).when(mStorageManager).getPrimaryStorageSize();

        mController = createController(mContext);

        assertThat(mController.isAvailable()).isFalse();
    }

    @Test
    public void isAvailable_whenPackageExists_returnsTrue() {
        mController = createController(mContext);

        assertThat(mController.isAvailable()).isTrue();
    }
@@ -70,7 +93,7 @@ public class LinuxTerminalPreferenceControllerTest {
    public void isAvailable_whenPackageNameIsNull_returnsFalse() {
        doReturn(null).when(mContext).getString(TERMINAL_PACKAGE_NAME_RESID);

        mController = new LinuxTerminalPreferenceController(mContext);
        mController = createController(mContext);

        assertThat(mController.isAvailable()).isFalse();
    }
@@ -81,8 +104,21 @@ public class LinuxTerminalPreferenceControllerTest {
                .when(mPackageManager)
                .getPackageInfo(eq(mTerminalPackageName), anyInt());

        mController = new LinuxTerminalPreferenceController(mContext);
        mController = createController(mContext);

        assertThat(mController.isAvailable()).isFalse();
    }

    private LinuxTerminalPreferenceController createController(Context context) {
        return createController(context, MEMORY_MIN_BYTES);
    }

    private LinuxTerminalPreferenceController createController(Context context, long totalMemory) {
        return new LinuxTerminalPreferenceController(context) {
            @Override
            public long getTotalMemory() {
                return totalMemory;
            }
        };
    }
}