• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 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.settings.development.linuxterminal;
18 
19 import static android.system.virtualmachine.VirtualMachineManager.CAPABILITY_NON_PROTECTED_VM;
20 
21 import android.content.Context;
22 import android.content.pm.PackageManager;
23 import android.os.Process;
24 import android.os.storage.StorageManager;
25 import android.system.virtualmachine.VirtualMachineManager;
26 import android.text.TextUtils;
27 import android.util.DataUnit;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 import androidx.annotation.VisibleForTesting;
32 
33 import com.android.settings.R;
34 import com.android.settings.core.PreferenceControllerMixin;
35 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
36 
37 /** Preference controller for Linux terminal option in developers option */
38 public class LinuxTerminalPreferenceController extends DeveloperOptionsPreferenceController
39         implements PreferenceControllerMixin {
40     @VisibleForTesting
41     static final int TERMINAL_PACKAGE_NAME_RESID = R.string.config_linux_terminal_app_package_name;
42 
43     @VisibleForTesting
44     static final long MEMORY_MIN_BYTES = DataUnit.GIGABYTES.toBytes(4); // 4_000_000_000
45 
46     @VisibleForTesting
47     static final long STORAGE_MIN_BYTES = DataUnit.GIGABYTES.toBytes(16); // 16_000_000_000
48 
49     private static final String LINUX_TERMINAL_KEY = "linux_terminal";
50 
51     @Nullable private final String mTerminalPackageName;
52     private final boolean mIsDeviceCapable;
53 
LinuxTerminalPreferenceController(@onNull Context context)54     public LinuxTerminalPreferenceController(@NonNull Context context) {
55         super(context);
56         String packageName = context.getString(TERMINAL_PACKAGE_NAME_RESID);
57         mTerminalPackageName =
58                 isPackageInstalled(context.getPackageManager(), packageName) ? packageName : null;
59 
60         StorageManager storageManager = context.getSystemService(StorageManager.class);
61         VirtualMachineManager virtualMachineManager =
62                 context.getSystemService(VirtualMachineManager.class);
63 
64         mIsDeviceCapable =
65                 getTotalMemory() >= MEMORY_MIN_BYTES
66                         && storageManager != null
67                         && storageManager.getPrimaryStorageSize() >= STORAGE_MIN_BYTES
68                         && virtualMachineManager != null
69                         && ((virtualMachineManager.getCapabilities() & CAPABILITY_NON_PROTECTED_VM)
70                                 != 0);
71     }
72 
73     // Avoid lazy initialization because this may be called before displayPreference().
74     @Override
isAvailable()75     public boolean isAvailable() {
76         // Check build flag RELEASE_AVF_SUPPORT_CUSTOM_VM_WITH_PARAVIRTUALIZED_DEVICES indirectly
77         // by checking whether the terminal app is installed.
78         // TODO(b/343795511): Add explicitly check for the flag when it's accessible from Java code.
79         return mTerminalPackageName != null && mIsDeviceCapable;
80     }
81 
82     @Override
83     @NonNull
getPreferenceKey()84     public String getPreferenceKey() {
85         return LINUX_TERMINAL_KEY;
86     }
87 
isPackageInstalled(PackageManager manager, String packageName)88     private static boolean isPackageInstalled(PackageManager manager, String packageName) {
89         if (TextUtils.isEmpty(packageName)) {
90             return false;
91         }
92         try {
93             return manager.getPackageInfo(
94                             packageName,
95                             PackageManager.MATCH_ALL | PackageManager.MATCH_DISABLED_COMPONENTS)
96                     != null;
97         } catch (PackageManager.NameNotFoundException e) {
98             return false;
99         }
100     }
101 
102     // Can be overridden for test
103     @VisibleForTesting
getTotalMemory()104     long getTotalMemory() {
105         return Process.getTotalMemory();
106     }
107 }
108