Fix nullability issues that AOSP is complaining about now

This commit is contained in:
Torsten Grote 2024-03-06 11:54:57 -03:00 committed by Chirayu Desai
parent c33486ee00
commit 0c8fe3ef20
22 changed files with 114 additions and 100 deletions

View file

@ -24,14 +24,14 @@ internal class RestoreFilesFragment : SnapshotFragment() {
): View {
val v = super.onCreateView(inflater, container, savedInstanceState)
val topStub: ViewStub = v.findViewById(R.id.topStub)
val topStub: ViewStub = v.requireViewById(R.id.topStub)
topStub.layoutResource = R.layout.header_snapshots
topStub.inflate()
val bottomStub: ViewStub = v.findViewById(R.id.bottomStub)
val bottomStub: ViewStub = v.requireViewById(R.id.bottomStub)
bottomStub.layoutResource = R.layout.footer_snapshots
val footer = bottomStub.inflate()
val skipView: TextView = footer.findViewById(R.id.skipView)
val skipView: TextView = footer.requireViewById(R.id.skipView)
skipView.setOnClickListener {
requireActivity().apply {
setResult(RESULT_OK)
@ -54,7 +54,7 @@ internal class RestoreFilesStartedFragment : Fragment() {
): View {
val v: View = inflater.inflate(R.layout.fragment_restore_files_started, container, false)
val button: Button = v.findViewById(R.id.button)
val button: Button = v.requireViewById(R.id.button)
button.setOnClickListener {
requireActivity().apply {
setResult(RESULT_OK)

View file

@ -37,11 +37,11 @@ class RestoreProgressFragment : Fragment() {
): View {
val v: View = inflater.inflate(R.layout.fragment_restore_progress, container, false)
progressBar = v.findViewById(R.id.progressBar)
titleView = v.findViewById(R.id.titleView)
backupNameView = v.findViewById(R.id.backupNameView)
appList = v.findViewById(R.id.appList)
button = v.findViewById(R.id.button)
progressBar = v.requireViewById(R.id.progressBar)
titleView = v.requireViewById(R.id.titleView)
backupNameView = v.requireViewById(R.id.backupNameView)
appList = v.requireViewById(R.id.appList)
button = v.requireViewById(R.id.button)
return v
}

View file

@ -31,8 +31,8 @@ internal class RestoreSetAdapter(
inner class RestoreSetViewHolder(private val v: View) : ViewHolder(v) {
private val titleView = v.findViewById<TextView>(R.id.titleView)
private val subtitleView = v.findViewById<TextView>(R.id.subtitleView)
private val titleView = v.requireViewById<TextView>(R.id.titleView)
private val subtitleView = v.requireViewById<TextView>(R.id.subtitleView)
internal fun bind(item: RestorableBackup) {
v.setOnClickListener { listener.onRestorableBackupClicked(item) }

View file

@ -30,10 +30,10 @@ class RestoreSetFragment : Fragment() {
): View {
val v: View = inflater.inflate(R.layout.fragment_restore_set, container, false)
listView = v.findViewById(R.id.listView)
progressBar = v.findViewById(R.id.progressBar)
errorView = v.findViewById(R.id.errorView)
skipView = v.findViewById(R.id.skipView)
listView = v.requireViewById(R.id.listView)
progressBar = v.requireViewById(R.id.progressBar)
errorView = v.requireViewById(R.id.errorView)
skipView = v.requireViewById(R.id.skipView)
return v
}

View file

@ -129,13 +129,13 @@ internal class ApkRestore(
}
// get app icon and label (name)
val appInfo = packageInfo.applicationInfo.apply {
val appInfo = packageInfo.applicationInfo?.apply {
// set APK paths before, so package manager can find it for icon extraction
sourceDir = cachedApk.absolutePath
publicSourceDir = cachedApk.absolutePath
}
val icon = appInfo.loadIcon(pm)
val name = pm.getApplicationLabel(appInfo)
val icon = appInfo?.loadIcon(pm)
val name = appInfo?.let { pm.getApplicationLabel(it) }
installResult.update(packageName) { result ->
result.copy(state = IN_PROGRESS, name = name, icon = icon)

View file

@ -41,11 +41,11 @@ class InstallProgressFragment : Fragment(), InstallItemListener {
): View {
val v: View = inflater.inflate(R.layout.fragment_restore_progress, container, false)
progressBar = v.findViewById(R.id.progressBar)
titleView = v.findViewById(R.id.titleView)
backupNameView = v.findViewById(R.id.backupNameView)
appList = v.findViewById(R.id.appList)
button = v.findViewById(R.id.button)
progressBar = v.requireViewById(R.id.progressBar)
titleView = v.requireViewById(R.id.titleView)
backupNameView = v.requireViewById(R.id.backupNameView)
appList = v.requireViewById(R.id.appList)
button = v.requireViewById(R.id.button)
return v
}

View file

@ -27,12 +27,12 @@ class AboutDialogFragment : Fragment() {
val v: View = inflater.inflate(R.layout.fragment_about, container, false)
val versionName = packageService.getVersionName(requireContext().packageName) ?: "???"
val versionView: TextView = v.findViewById(R.id.versionView)
val versionView: TextView = v.requireViewById(R.id.versionView)
versionView.text = getString(R.string.about_version, versionName)
val linkMovementMethod = LinkMovementMethod.getInstance()
val contributorsView = v.findViewById<TextView>(R.id.contributorView)
val orgsView = v.findViewById<TextView>(R.id.about_contributing_organizations_content)
val contributorsView = v.requireViewById<TextView>(R.id.contributorView)
val orgsView = v.requireViewById<TextView>(R.id.about_contributing_organizations_content)
contributorsView.movementMethod = linkMovementMethod
orgsView.movementMethod = linkMovementMethod

View file

@ -39,8 +39,8 @@ class AppStatusFragment : Fragment(), AppStatusToggleListener {
setHasOptionsMenu(true)
val v: View = inflater.inflate(R.layout.fragment_app_status, container, false)
progressBar = v.findViewById(R.id.progressBar)
list = v.findViewById(R.id.list)
progressBar = v.requireViewById(R.id.progressBar)
list = v.requireViewById(R.id.list)
return v
}

View file

@ -61,7 +61,7 @@ class SettingsActivity : RequireProvisioningActivity(), OnPreferenceStartFragmen
pref: Preference,
): Boolean {
val fragment =
supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment)
supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment!!)
if (pref.key == PREF_BACKUP_RECOVERY_CODE) fragment.arguments = Bundle().apply {
putBoolean(ARG_FOR_NEW_CODE, false)
}

View file

@ -259,10 +259,14 @@ class SettingsFragment : PreferenceFragmentCompat() {
// warn if battery optimization is active
// we don't bother with yet another dialog, because the ROM should handle it
val context = requireContext()
val powerManager = context.getSystemService(PowerManager::class.java)
if (!powerManager.isIgnoringBatteryOptimizations(context.packageName)) {
Toast.makeText(context, R.string.settings_backup_storage_battery_optimization,
LENGTH_LONG).show()
val powerManager: PowerManager? = context.getSystemService(PowerManager::class.java)
if (powerManager != null &&
!powerManager.isIgnoringBatteryOptimizations(context.packageName)
) {
Toast.makeText(
context, R.string.settings_backup_storage_battery_optimization,
LENGTH_LONG
).show()
}
viewModel.enableStorageBackup()
backupStorage.isChecked = true

View file

@ -191,7 +191,7 @@ data class Storage(
}
private fun hasUnmeteredInternet(context: Context): Boolean {
val cm = context.getSystemService(ConnectivityManager::class.java)
val cm = context.getSystemService(ConnectivityManager::class.java) ?: return false
val isMetered = cm.isActiveNetworkMetered
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && !isMetered

View file

@ -60,7 +60,8 @@ internal class SettingsViewModel(
) : RequireProvisioningViewModel(app, settingsManager, keyManager) {
private val contentResolver = app.contentResolver
private val connectivityManager = app.getSystemService(ConnectivityManager::class.java)
private val connectivityManager: ConnectivityManager? =
app.getSystemService(ConnectivityManager::class.java)
override val isRestoreOperation = false
@ -129,13 +130,13 @@ internal class SettingsViewModel(
// register network observer if needed
if (networkCallback.registered && !storage.requiresNetwork) {
connectivityManager.unregisterNetworkCallback(networkCallback)
connectivityManager?.unregisterNetworkCallback(networkCallback)
networkCallback.registered = false
} else if (!networkCallback.registered && storage.requiresNetwork) {
val request = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
connectivityManager.registerNetworkCallback(request, networkCallback)
connectivityManager?.registerNetworkCallback(request, networkCallback)
networkCallback.registered = true
}
@ -156,7 +157,7 @@ internal class SettingsViewModel(
override fun onCleared() {
contentResolver.unregisterContentObserver(storageObserver)
if (networkCallback.registered) {
connectivityManager.unregisterNetworkCallback(networkCallback)
connectivityManager?.unregisterNetworkCallback(networkCallback)
networkCallback.registered = false
}
}

View file

@ -74,13 +74,14 @@ internal class ApkBackup(
}
// TODO remove when adding support for packages with multiple signers
if (packageInfo.signingInfo.hasMultipleSigners()) {
val signingInfo = packageInfo.signingInfo ?: return null
if (signingInfo.hasMultipleSigners()) {
Log.e(TAG, "Package $packageName has multiple signers. Not backing it up.")
return null
}
// get signatures
val signatures = packageInfo.signingInfo.getSignatures()
val signatures = signingInfo.getSignatures()
if (signatures.isEmpty()) {
Log.e(TAG, "Package $packageName has no signatures. Not backing it up.")
return null
@ -107,7 +108,8 @@ internal class ApkBackup(
}
// get an InputStream for the APK
val inputStream = getApkInputStream(packageInfo.applicationInfo.sourceDir)
val sourceDir = packageInfo.applicationInfo?.sourceDir ?: return null
val inputStream = getApkInputStream(sourceDir)
// copy the APK to the storage's output and calculate SHA-256 hash while at it
val name = crypto.getNameForApk(metadataManager.salt, packageName)
val sha256 = copyStreamsAndGetHash(inputStream, streamGetter(name))
@ -158,7 +160,7 @@ internal class ApkBackup(
): List<ApkSplit> {
check(packageInfo.splitNames != null)
// attention: though not documented, splitSourceDirs can be null
val splitSourceDirs = packageInfo.applicationInfo.splitSourceDirs ?: emptyArray()
val splitSourceDirs = packageInfo.applicationInfo?.splitSourceDirs ?: emptyArray()
check(packageInfo.splitNames.size == splitSourceDirs.size) {
"Size Mismatch! ${packageInfo.splitNames.size} != ${splitSourceDirs.size} " +
"splitNames is ${packageInfo.splitNames.toList()}, " +
@ -238,8 +240,10 @@ fun copyStreamsAndGetHash(inputStream: InputStream, outputStream: OutputStream):
/**
* Returns a list of Base64 encoded SHA-256 signature hashes.
*/
fun SigningInfo.getSignatures(): List<String> {
return if (hasMultipleSigners()) {
fun SigningInfo?.getSignatures(): List<String> {
return if (this == null) {
emptyList()
} else if (hasMultipleSigners()) {
apkContentsSigners.map { signature ->
hashSignature(signature).encodeBase64()
}

View file

@ -174,7 +174,8 @@ internal class PackageService(
}
private fun PackageInfo.allowsBackup(): Boolean {
if (packageName == MAGIC_PACKAGE_MANAGER || applicationInfo == null) return false
val appInfo = applicationInfo
if (packageName == MAGIC_PACKAGE_MANAGER || appInfo == null) return false
return if (settingsManager.d2dBackupsEnabled()) {
/**
@ -191,7 +192,7 @@ internal class PackageService(
*/
true
} else {
applicationInfo.flags and FLAG_ALLOW_BACKUP != 0
appInfo.flags and FLAG_ALLOW_BACKUP != 0
}
}
@ -226,8 +227,9 @@ internal fun PackageInfo.isUserVisible(context: Context): Boolean {
}
internal fun PackageInfo.isSystemApp(): Boolean {
if (packageName == MAGIC_PACKAGE_MANAGER || applicationInfo == null) return true
return applicationInfo.flags and FLAG_SYSTEM != 0
val appInfo = applicationInfo
if (packageName == MAGIC_PACKAGE_MANAGER || appInfo == null) return true
return appInfo.flags and FLAG_SYSTEM != 0
}
/**
@ -235,18 +237,21 @@ internal fun PackageInfo.isSystemApp(): Boolean {
* We don't back up those APKs.
*/
internal fun PackageInfo.isNotUpdatedSystemApp(): Boolean {
if (packageName == MAGIC_PACKAGE_MANAGER || applicationInfo == null) return true
val isSystemApp = applicationInfo.flags and FLAG_SYSTEM != 0
val isUpdatedSystemApp = applicationInfo.flags and FLAG_UPDATED_SYSTEM_APP != 0
val appInfo = applicationInfo
if (packageName == MAGIC_PACKAGE_MANAGER || appInfo == null) return true
val isSystemApp = appInfo.flags and FLAG_SYSTEM != 0
val isUpdatedSystemApp = appInfo.flags and FLAG_UPDATED_SYSTEM_APP != 0
return isSystemApp && !isUpdatedSystemApp
}
internal fun PackageInfo.isStopped(): Boolean {
if (packageName == MAGIC_PACKAGE_MANAGER || applicationInfo == null) return false
return applicationInfo.flags and FLAG_STOPPED != 0
val appInfo = applicationInfo
if (packageName == MAGIC_PACKAGE_MANAGER || appInfo == null) return false
return appInfo.flags and FLAG_STOPPED != 0
}
internal fun PackageInfo.isTestOnly(): Boolean {
if (packageName == MAGIC_PACKAGE_MANAGER || applicationInfo == null) return false
return applicationInfo.flags and FLAG_TEST_ONLY != 0
val appInfo = applicationInfo
if (packageName == MAGIC_PACKAGE_MANAGER || appInfo == null) return false
return appInfo.flags and FLAG_TEST_ONLY != 0
}

View file

@ -8,9 +8,9 @@ import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.Switch
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.switchmaterial.SwitchMaterial
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.ui.AppBackupState.FAILED
import com.stevesoltys.seedvault.ui.AppBackupState.IN_PROGRESS
@ -22,12 +22,12 @@ internal abstract class AppViewHolder(protected val v: View) : RecyclerView.View
protected val pm: PackageManager = context.packageManager
protected val clickableBackground = v.background!!
protected val appIcon: ImageView = v.findViewById(R.id.appIcon)
protected val appName: TextView = v.findViewById(R.id.appName)
protected val appInfo: TextView = v.findViewById(R.id.appInfo)
protected val appStatus: ImageView = v.findViewById(R.id.appStatus)
protected val progressBar: ProgressBar = v.findViewById(R.id.progressBar)
protected val switchView: Switch = v.findViewById(R.id.switchView)
protected val appIcon: ImageView = v.requireViewById(R.id.appIcon)
protected val appName: TextView = v.requireViewById(R.id.appName)
protected val appInfo: TextView = v.requireViewById(R.id.appInfo)
protected val appStatus: ImageView = v.requireViewById(R.id.appStatus)
protected val progressBar: ProgressBar = v.requireViewById(R.id.progressBar)
protected val switchView: SwitchMaterial = v.requireViewById(R.id.switchView)
init {
// don't use clickable background by default

View file

@ -27,8 +27,8 @@ class RecoveryCodeAdapter(private val items: List<CharArray>) :
class RecoveryCodeViewHolder(v: View) : RecyclerView.ViewHolder(v) {
private val num = v.findViewById<TextView>(R.id.num)
private val word = v.findViewById<TextView>(R.id.word)
private val num = v.requireViewById<TextView>(R.id.num)
private val word = v.requireViewById<TextView>(R.id.word)
internal fun bind(number: Int, item: CharArray) {
num.text = number.toString()

View file

@ -71,24 +71,24 @@ class RecoveryCodeInputFragment : Fragment() {
): View {
val v: View = inflater.inflate(R.layout.fragment_recovery_code_input, container, false)
if (!isDebugBuild()) getActivity()?.window?.addFlags(FLAG_SECURE)
if (!isDebugBuild()) activity?.window?.addFlags(FLAG_SECURE)
introText = v.findViewById(R.id.introText)
doneButton = v.findViewById(R.id.doneButton)
newCodeButton = v.findViewById(R.id.newCodeButton)
wordLayout1 = v.findViewById(R.id.wordLayout1)
wordLayout2 = v.findViewById(R.id.wordLayout2)
wordLayout3 = v.findViewById(R.id.wordLayout3)
wordLayout4 = v.findViewById(R.id.wordLayout4)
wordLayout5 = v.findViewById(R.id.wordLayout5)
wordLayout6 = v.findViewById(R.id.wordLayout6)
wordLayout7 = v.findViewById(R.id.wordLayout7)
wordLayout8 = v.findViewById(R.id.wordLayout8)
wordLayout9 = v.findViewById(R.id.wordLayout9)
wordLayout10 = v.findViewById(R.id.wordLayout10)
wordLayout11 = v.findViewById(R.id.wordLayout11)
wordLayout12 = v.findViewById(R.id.wordLayout12)
wordList = v.findViewById(R.id.wordList)
introText = v.requireViewById(R.id.introText)
doneButton = v.requireViewById(R.id.doneButton)
newCodeButton = v.requireViewById(R.id.newCodeButton)
wordLayout1 = v.requireViewById(R.id.wordLayout1)
wordLayout2 = v.requireViewById(R.id.wordLayout2)
wordLayout3 = v.requireViewById(R.id.wordLayout3)
wordLayout4 = v.requireViewById(R.id.wordLayout4)
wordLayout5 = v.requireViewById(R.id.wordLayout5)
wordLayout6 = v.requireViewById(R.id.wordLayout6)
wordLayout7 = v.requireViewById(R.id.wordLayout7)
wordLayout8 = v.requireViewById(R.id.wordLayout8)
wordLayout9 = v.requireViewById(R.id.wordLayout9)
wordLayout10 = v.requireViewById(R.id.wordLayout10)
wordLayout11 = v.requireViewById(R.id.wordLayout11)
wordLayout12 = v.requireViewById(R.id.wordLayout12)
wordList = v.requireViewById(R.id.wordList)
arguments?.getBoolean(ARG_FOR_NEW_CODE, true)?.let {
forStoringNewCode = it
@ -148,7 +148,7 @@ class RecoveryCodeInputFragment : Fragment() {
}
if (forStoringNewCode) {
val keyguardManager = requireContext().getSystemService(KeyguardManager::class.java)
if (keyguardManager.isDeviceSecure) {
if (keyguardManager?.isDeviceSecure == true) {
// if we have a lock-screen secret, we can ask for it before storing the code
storeNewCodeAfterAuth(input)
} else {

View file

@ -28,10 +28,10 @@ class RecoveryCodeOutputFragment : Fragment() {
): View {
val v: View = inflater.inflate(R.layout.fragment_recovery_code_output, container, false)
if (!isDebugBuild()) getActivity()?.window?.addFlags(FLAG_SECURE)
if (!isDebugBuild()) activity?.window?.addFlags(FLAG_SECURE)
wordList = v.findViewById(R.id.wordList)
confirmCodeButton = v.findViewById(R.id.confirmCodeButton)
wordList = v.requireViewById(R.id.wordList)
confirmCodeButton = v.requireViewById(R.id.confirmCodeButton)
return v
}

View file

@ -41,10 +41,10 @@ class StorageCheckFragment : Fragment() {
): View {
val v: View = inflater.inflate(R.layout.fragment_storage_check, container, false)
titleView = v.findViewById(R.id.titleView)
progressBar = v.findViewById(R.id.progressBar)
errorView = v.findViewById(R.id.errorView)
backButton = v.findViewById(R.id.backButton)
titleView = v.requireViewById(R.id.titleView)
progressBar = v.requireViewById(R.id.progressBar)
errorView = v.requireViewById(R.id.errorView)
backButton = v.requireViewById(R.id.backButton)
return v
}
@ -56,7 +56,7 @@ class StorageCheckFragment : Fragment() {
val errorMsg = requireArguments().getString(ERROR_MSG)
if (errorMsg != null) {
view.findViewById<View>(R.id.patienceView).visibility = GONE
view.requireViewById<View>(R.id.patienceView).visibility = GONE
progressBar.visibility = INVISIBLE
errorView.text = errorMsg
errorView.visibility = VISIBLE

View file

@ -45,9 +45,9 @@ internal class StorageOptionAdapter(
internal inner class StorageOptionViewHolder(private val v: View) : ViewHolder(v) {
private val iconView = v.findViewById<ImageView>(R.id.iconView)
private val titleView = v.findViewById<TextView>(R.id.titleView)
private val summaryView = v.findViewById<TextView>(R.id.summaryView)
private val iconView = v.requireViewById<ImageView>(R.id.iconView)
private val titleView = v.requireViewById<TextView>(R.id.titleView)
private val summaryView = v.requireViewById<TextView>(R.id.summaryView)
internal fun bind(item: StorageOption) {
if (item.enabled) {

View file

@ -57,12 +57,12 @@ internal class StorageOptionsFragment : Fragment(), StorageOptionClickedListener
): View {
val v: View = inflater.inflate(R.layout.fragment_storage_root, container, false)
titleView = v.findViewById(R.id.titleView)
warningIcon = v.findViewById(R.id.warningIcon)
warningText = v.findViewById(R.id.warningText)
listView = v.findViewById(R.id.listView)
progressBar = v.findViewById(R.id.progressBar)
skipView = v.findViewById(R.id.skipView)
titleView = v.requireViewById(R.id.titleView)
warningIcon = v.requireViewById(R.id.warningIcon)
warningText = v.requireViewById(R.id.warningText)
listView = v.requireViewById(R.id.listView)
progressBar = v.requireViewById(R.id.progressBar)
skipView = v.requireViewById(R.id.skipView)
return v
}

View file

@ -68,7 +68,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"