diff --git a/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchPermission.kt b/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchPermission.kt new file mode 100644 index 0000000000..bf648a451c --- /dev/null +++ b/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchPermission.kt @@ -0,0 +1,7 @@ +package app.lawnchair.search.algorithms.engine + +import android.content.Context + +interface SearchPermission { + fun checkPermission(context: Context): Boolean +} diff --git a/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/ContactsSearchProvider.kt b/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/ContactsSearchProvider.kt index acd7acbcbd..cf953262db 100644 --- a/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/ContactsSearchProvider.kt +++ b/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/ContactsSearchProvider.kt @@ -1,11 +1,14 @@ package app.lawnchair.search.algorithms.engine.provider +import android.Manifest import android.content.Context +import android.content.pm.PackageManager import android.provider.ContactsContract import android.util.Log import app.lawnchair.preferences.PreferenceManager import app.lawnchair.preferences2.PreferenceManager2 import app.lawnchair.search.algorithms.data.ContactInfo +import app.lawnchair.search.algorithms.engine.SearchPermission import app.lawnchair.search.algorithms.engine.SearchProvider import app.lawnchair.search.algorithms.engine.SearchResult import com.patrykmichalik.opto.core.firstBlocking @@ -18,7 +21,7 @@ import kotlinx.serialization.json.buildJsonArray import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.put -object ContactsSearchProvider : SearchProvider { +object ContactsSearchProvider : SearchProvider, SearchPermission { override val id: String = "contacts" override fun search( @@ -28,7 +31,7 @@ object ContactsSearchProvider : SearchProvider { val prefs = PreferenceManager.getInstance(context) val prefs2 = PreferenceManager2.getInstance(context) - val permissionsGranted = true // TODO: replace with real permission check + val permissionsGranted = checkPermission(context) if (query.isBlank() || !prefs.searchResultPeople.get() || !permissionsGranted) { emit(emptyList()) return@flow @@ -45,6 +48,10 @@ object ContactsSearchProvider : SearchProvider { emit(searchResults) } + override fun checkPermission(context: Context): Boolean { + return context.checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED + } + private suspend fun findContactsByName(context: Context, query: String, max: Int): List { try { if (query.isEmpty() || query.isBlank() || max <= 0) return emptyList() diff --git a/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/FileSearchProvider.kt b/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/FileSearchProvider.kt index 2a35a9437a..1dae25858e 100644 --- a/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/FileSearchProvider.kt +++ b/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/FileSearchProvider.kt @@ -1,14 +1,19 @@ package app.lawnchair.search.algorithms.engine.provider +import android.Manifest import android.content.Context +import android.content.pm.PackageManager import android.database.Cursor import android.net.Uri +import android.os.Build +import android.os.Environment import android.provider.MediaStore import app.lawnchair.preferences.PreferenceManager import app.lawnchair.preferences2.PreferenceManager2 import app.lawnchair.search.algorithms.data.FileInfo import app.lawnchair.search.algorithms.data.FolderInfo import app.lawnchair.search.algorithms.data.IFileInfo +import app.lawnchair.search.algorithms.engine.SearchPermission import app.lawnchair.search.algorithms.engine.SearchProvider import app.lawnchair.search.algorithms.engine.SearchResult import app.lawnchair.util.exists @@ -23,7 +28,7 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.withContext import okio.Path.Companion.toPath -object FileSearchProvider : SearchProvider { +object FileSearchProvider : SearchProvider, SearchPermission { override val id = "Files" override fun search( @@ -33,7 +38,7 @@ object FileSearchProvider : SearchProvider { val prefs = PreferenceManager.getInstance(context) val prefs2 = PreferenceManager2.getInstance(context) - val permissionsGranted = true // TODO: Replace with real permission check, to be added later + val permissionsGranted = checkPermission(context) if (query.isBlank() || !prefs.searchResultFiles.get() || !permissionsGranted) { emit(emptyList()) return@flow @@ -54,6 +59,16 @@ object FileSearchProvider : SearchProvider { emit(searchResults) } + override fun checkPermission(context: Context): Boolean { + // TODO: improve granularity of permissions + return when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> + Environment.isExternalStorageManager() || context.checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED + Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> Environment.isExternalStorageManager() + else -> context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED + } + } + private suspend fun queryFilesInMediaStore( context: Context, uri: Uri = MediaStore.Files.getContentUri("external"), diff --git a/lawnchair/src/app/lawnchair/util/PackagePermissionManager.kt b/lawnchair/src/app/lawnchair/util/PackagePermissionManager.kt index 88b94d3530..26b8debddf 100644 --- a/lawnchair/src/app/lawnchair/util/PackagePermissionManager.kt +++ b/lawnchair/src/app/lawnchair/util/PackagePermissionManager.kt @@ -9,39 +9,11 @@ import android.net.Uri import android.os.Build import android.os.Environment import android.provider.Settings -import android.util.Log import androidx.annotation.RequiresApi import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import app.lawnchair.preferences.PreferenceManager -private const val TAG: String = "PackagePermissionManager" - -fun requestContactPermissionGranted(context: Context, prefs: PreferenceManager): Boolean { - val isGranted = contactPermissionGranted(context) - if (!isGranted) { - val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - val uri: Uri = Uri.fromParts("package", context.packageName, null) - intent.data = uri - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY) - intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) - - if (intent.resolveActivity(context.packageManager) != null) { - context.startActivity(intent) - } else { - Log.e(TAG, "No activity found to handle application details settings intent") - } - prefs.searchResultPeople.set(false) - } - return isGranted -} - -fun contactPermissionGranted(context: Context): Boolean { - return context.checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED -} - fun checkAndRequestFilesPermission(context: Context, prefs: PreferenceManager): Boolean { when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {