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.deviceinfo.firmwareversion 18 19 import android.content.Context 20 import android.content.Intent 21 import android.content.pm.PackageManager 22 import android.text.format.DateFormat 23 import android.util.Log 24 import androidx.preference.Preference 25 import com.android.settings.R 26 import com.android.settings.flags.Flags 27 import com.android.settings.utils.getLocale 28 import com.android.settingslib.metadata.PreferenceAvailabilityProvider 29 import com.android.settingslib.metadata.PreferenceMetadata 30 import com.android.settingslib.metadata.PreferenceSummaryProvider 31 import com.android.settingslib.preference.PreferenceBinding 32 import java.text.ParseException 33 import java.text.SimpleDateFormat 34 import java.util.Date 35 import java.util.TimeZone 36 37 // LINT.IfChange 38 class MainlineModuleVersionPreference : 39 PreferenceMetadata, 40 PreferenceSummaryProvider, 41 PreferenceAvailabilityProvider, 42 PreferenceBinding { 43 44 private var moduleVersion: String? = null 45 46 override val key: String 47 get() = "module_version" 48 49 override val title: Int 50 get() = R.string.module_version 51 getSummarynull52 override fun getSummary(context: Context): CharSequence? { 53 val version = getModuleVersion(context) 54 if (version.isEmpty()) return null 55 56 val locale = context.getLocale() 57 fun parseDate(pattern: String): Date? { 58 val simpleDateFormat = SimpleDateFormat(pattern, locale) 59 simpleDateFormat.timeZone = TimeZone.getDefault() 60 return try { 61 simpleDateFormat.parse(version) 62 } catch (e: ParseException) { 63 null 64 } 65 } 66 67 val date = parseDate("yyyy-MM-dd") ?: parseDate("yyyy-MM") 68 return if (date == null) { 69 Log.w(TAG, "Cannot parse mainline versionName ($version) as date") 70 version 71 } else { 72 DateFormat.format(DateFormat.getBestDateTimePattern(locale, "dMMMMyyyy"), date) 73 } 74 } 75 intentnull76 override fun intent(context: Context): Intent? { 77 val packageManager = context.packageManager 78 val intentPackage = 79 if (Flags.mainlineModuleExplicitIntent()) { 80 context.getString(R.string.config_mainline_module_update_package) 81 } else { 82 null 83 } 84 fun String.resolveIntent() = 85 Intent(this).let { 86 if (intentPackage != null) it.setPackage(intentPackage) 87 if (packageManager.resolveActivity(it, 0) != null) it else null 88 } 89 90 return MODULE_UPDATE_ACTION_V2.resolveIntent() ?: MODULE_UPDATE_ACTION.resolveIntent() 91 } 92 isAvailablenull93 override fun isAvailable(context: Context) = getModuleVersion(context).isNotEmpty() 94 95 override fun bind(preference: Preference, metadata: PreferenceMetadata) { 96 super.bind(preference, metadata) 97 // This seems unnecessary, just follow existing behavior to pass test 98 if (preference.intent == null) preference.setSummary(R.string.summary_placeholder) 99 preference.isCopyingEnabled = true 100 } 101 getModuleVersionnull102 private fun getModuleVersion(context: Context): String = 103 moduleVersion ?: context.getVersion().also { moduleVersion = it } 104 Contextnull105 private fun Context.getVersion(): String { 106 val moduleProvider = 107 getString(com.android.internal.R.string.config_defaultModuleMetadataProvider) 108 if (moduleProvider.isEmpty()) return "" 109 return try { 110 packageManager.getPackageInfo(moduleProvider, 0)?.versionName ?: "" 111 } catch (e: PackageManager.NameNotFoundException) { 112 Log.e(TAG, "Failed to get mainline version.", e) 113 "" 114 } 115 } 116 117 companion object { 118 private const val TAG = "MainlineModulePreference" 119 const val MODULE_UPDATE_ACTION = "android.settings.MODULE_UPDATE_SETTINGS" 120 const val MODULE_UPDATE_ACTION_V2 = "android.settings.MODULE_UPDATE_VERSIONS" 121 } 122 } 123 // LINT.ThenChange(MainlineModuleVersionPreferenceController.java) 124