1 /* 2 * Copyright (C) 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; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.SystemProperties; 22 import android.os.UserHandle; 23 import android.os.UserManager; 24 import android.service.oemlock.OemLockManager; 25 import android.system.Os; 26 import android.system.OsConstants; 27 import android.util.Log; 28 29 import androidx.annotation.NonNull; 30 import androidx.annotation.VisibleForTesting; 31 32 import java.io.BufferedReader; 33 import java.io.FileReader; 34 import java.io.IOException; 35 36 public class Enable16kUtils { 37 private static final long PAGE_SIZE = Os.sysconf(OsConstants._SC_PAGESIZE); 38 private static final int PAGE_SIZE_16KB = 16 * 1024; 39 40 @VisibleForTesting 41 static final String DEV_OPTION_PROPERTY = "ro.product.build.16k_page.enabled"; 42 43 private static final String TAG = "Enable16kUtils"; 44 45 /** 46 * @param context uses context to retrieve OEM unlock info 47 * @return true if device is OEM unlocked and factory reset is allowed for user. 48 */ isDeviceOEMUnlocked(@onNull Context context)49 public static boolean isDeviceOEMUnlocked(@NonNull Context context) { 50 // OEM unlock is checked for bootloader, carrier and user. Check all three to ensure 51 // that device is unlocked and it is also allowed by user as well as carrier 52 final OemLockManager oemLockManager = context.getSystemService(OemLockManager.class); 53 final UserManager userManager = context.getSystemService(UserManager.class); 54 if (oemLockManager == null || userManager == null) { 55 Log.e(TAG, "Required services not found on device to check for OEM unlock state."); 56 return false; 57 } 58 59 // If either of device or carrier is not allowed to unlock, return false 60 if (!oemLockManager.isDeviceOemUnlocked()) { 61 Log.e(TAG, "Device is not OEM unlocked"); 62 return false; 63 } 64 65 final UserHandle userHandle = UserHandle.of(UserHandle.myUserId()); 66 if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, userHandle)) { 67 Log.e(TAG, "Factory reset is not allowed for user."); 68 return false; 69 } 70 71 return true; 72 } 73 74 /** 75 * @return true if /data partition is ext4 76 */ isDataExt4()77 public static boolean isDataExt4() { 78 try (BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { 79 String line; 80 while ((line = br.readLine()) != null) { 81 Log.i(TAG, line); 82 final String[] fields = line.split(" "); 83 final String partition = fields[1]; 84 final String fsType = fields[2]; 85 if (partition.equals("/data") && fsType.equals("ext4")) { 86 return true; 87 } 88 } 89 } catch (IOException e) { 90 Log.e(TAG, "Failed to read /proc/mounts"); 91 } 92 93 return false; 94 } 95 96 /** 97 * @return returns true if 16KB developer option is available for the device. 98 */ is16KbToggleAvailable()99 public static boolean is16KbToggleAvailable() { 100 return SystemProperties.getBoolean(DEV_OPTION_PROPERTY, false); 101 } 102 103 /** 104 * 16kB page-agnostic mode requires /data to be ext4, ro.product.build.16k_page.enabled for 105 * device and Device OEM unlocked. 106 * 107 * @param context is needed to query OEM unlock state 108 * @return true if device is in page-agnostic mode. 109 */ isPageAgnosticModeOn(@onNull Context context)110 public static boolean isPageAgnosticModeOn(@NonNull Context context) { 111 return is16KbToggleAvailable() && isDeviceOEMUnlocked(context) && isDataExt4(); 112 } 113 114 /** 115 * @return returns true if current page size is 16KB 116 */ isUsing16kbPages()117 public static boolean isUsing16kbPages() { 118 return PAGE_SIZE == PAGE_SIZE_16KB; 119 } 120 121 /** 122 * show page-agnostic mode warning dialog to user 123 * @param context to start activity 124 */ showPageAgnosticWarning(@onNull Context context)125 public static void showPageAgnosticWarning(@NonNull Context context) { 126 Intent intent = new Intent(context, PageAgnosticWarningActivity.class); 127 context.startActivityAsUser(intent, UserHandle.SYSTEM); 128 } 129 } 130