Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Verified Commit 484d01fb authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Bug fixes

parent 60f7532a
Loading
Loading
Loading
Loading
+21 −22
Original line number Diff line number Diff line
@@ -212,11 +212,7 @@ class UnifiedLocationClient private constructor(context: Context) {

    @Synchronized
    fun requestLocationUpdates(listener: LocationListener, interval: Long, count: Int) {
        for (request in requests) {
            if (request.listener === listener) {
                requests.remove(request)
            }
        }
        requests.removeAll(requests.filter { it.listener === listener })
        requests.add(LocationRequest(listener, interval, count))
        updateServiceInterval()
        updateBinding()
@@ -224,13 +220,7 @@ class UnifiedLocationClient private constructor(context: Context) {

    @Synchronized
    fun removeLocationUpdates(listener: LocationListener) {
        for (request in requests) {
            if (request.listener === listener) {
                requests.remove(request)
            }
        }
        updateServiceInterval()
        updateBinding()
        removeRequests(requests.filter { it.listener === listener })
    }

    private suspend fun refAndGetService(): UnifiedLocationService = suspendCoroutine { continuation -> refAndGetServiceContinued(continuation) }
@@ -293,7 +283,7 @@ class UnifiedLocationClient private constructor(context: Context) {
                service.getFromLocationWithOptions(latitude, longitude, maxResults, locale, options, AddressContinuation(continuation))
                configureContinuationTimeout(continuation, timeout)
            }
        } catch (e: RemoteException) {
        } catch (e: Exception) {
            Log.w(TAG, "Failed to request geocode", e)
            return emptyList()
        } finally {
@@ -368,7 +358,7 @@ class UnifiedLocationClient private constructor(context: Context) {

    suspend fun setGeocoderBackends(backends: Array<String>) {
        try {
            refAndGetService().locationBackends = backends
            refAndGetService().geocoderBackends = backends
        } catch (e: RemoteException) {
            Log.w(TAG, "Failed to handle request", e)
        } finally {
@@ -399,11 +389,17 @@ class UnifiedLocationClient private constructor(context: Context) {
    }

    @Synchronized
    private fun removeRequest(request: LocationRequest) {
        requests.remove(request)
    private fun removeRequestPendingRemoval() {
        removeRequests(requests.filter { it.needsRemoval })
    }

    private fun removeRequests(removalNeeded: List<LocationRequest>) {
        if (removalNeeded.isNotEmpty()) {
            requests.removeAll(removalNeeded)
            updateServiceInterval()
            updateBinding()
        }
    }

    @Synchronized
    private fun updateServiceInterval() {
@@ -459,6 +455,7 @@ class UnifiedLocationClient private constructor(context: Context) {
                    for (request in requests) {
                        request.handleLocation(location)
                    }
                    removeRequestPendingRemoval()
                }
            }, options)
            updateServiceInterval()
@@ -501,6 +498,10 @@ class UnifiedLocationClient private constructor(context: Context) {
    private inner class LocationRequest(val listener: LocationListener, var interval: Long, var pendingCount: Int) {
        private var lastUpdate: Long = 0

        private var failed: Boolean = false
        val needsRemoval: Boolean
            get() = pendingCount <= 0 || failed

        fun reset(interval: Long, count: Int) {
            this.interval = interval
            this.pendingCount = count
@@ -508,6 +509,7 @@ class UnifiedLocationClient private constructor(context: Context) {

        @Synchronized
        fun handleLocation(location: Location) {
            if (needsRemoval) return
            if (lastUpdate > System.currentTimeMillis()) {
                lastUpdate = System.currentTimeMillis()
            }
@@ -520,13 +522,10 @@ class UnifiedLocationClient private constructor(context: Context) {
                    listener.onLocation(location)
                } catch (e: Exception) {
                    Log.w(TAG, "Listener threw uncaught exception, stopping location request", e)
                    removeRequest(this)
                    failed = true
                }

            }
            if (pendingCount == 0) {
                removeRequest(this)
            }
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -152,7 +152,7 @@ class UnifiedLocationServiceRoot(private val service: UnifiedLocationServiceEntr

    override fun setGeocoderBackends(backends: Array<String>) {
        if (Binder.getCallingUid() != myUid()) throw SecurityException("Only allowed from same UID")
        Preferences(service).locationBackends = backends
        Preferences(service).geocoderBackends = backends
        reloadPreferences()
    }

+84 −28
Original line number Diff line number Diff line
@@ -12,7 +12,10 @@ import android.content.Intent.ACTION_VIEW
import android.content.pm.PackageManager.GET_META_DATA
import android.content.res.ColorStateList
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
@@ -21,9 +24,10 @@ import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.databinding.Observable
import androidx.databinding.Observable.OnPropertyChangedCallback
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.delay
import org.microg.nlp.client.UnifiedLocationClient
import org.microg.nlp.ui.BackendType.GEOCODER
import org.microg.nlp.ui.BackendType.LOCATION
@@ -73,19 +77,58 @@ class BackendDetailsFragment : Fragment(R.layout.backend_details) {
            return ColorStateList(arrayOf(emptyArray<Int>().toIntArray()), arrayOf(withAlpha).toIntArray())
        }

    private lateinit var binding: BackendDetailsBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val binding = BackendDetailsBinding.inflate(inflater, container, false)
        binding = BackendDetailsBinding.inflate(inflater, container, false)
        binding.fragment = this
        return binding.root
    }

    override fun onResume() {
        super.onResume()
        binding.switchWidget.trackTintList = switchBarTrackTintColor
        lifecycleScope.launchWhenStarted {
            val entry = createBackendInfo()
        lifecycleScope.launchWhenStarted { initContent(createBackendInfo()) }
    }

    private suspend fun initContent(entry: BackendInfo?) {
        binding.entry = entry
        binding.executePendingBindings()
            if (entry?.type == LOCATION) {
        updateContent(entry)
        entry?.addOnPropertyChangedCallback(object : OnPropertyChangedCallback() {
            override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
                if (propertyId == BR.enabled) {
                    lifecycleScope.launchWhenStarted { initContent(entry) }
                }
            }
        })
    }

    private var updateInProgress = false
    private suspend fun updateContent(entry: BackendInfo?) {
        if (entry?.type == LOCATION && entry.enabled) {
            if (updateInProgress) return
            updateInProgress = true
            val client = UnifiedLocationClient[entry.context]

                val location = client.getLastLocationForBackend(entry.serviceInfo.packageName, entry.serviceInfo.name, entry.firstSignatureDigest)
                        ?: return@launchWhenStarted
            val locationTemp = client.getLastLocationForBackend(entry.serviceInfo.packageName, entry.serviceInfo.name, entry.firstSignatureDigest)
            val location = when (locationTemp) {
                null -> {
                    delay(500L) // Wait short time to ensure backend was activated
                    Log.d(TAG, "Location was not available, requesting once")
                    client.forceNextUpdate = true
                    client.getSingleLocation()
                    val secondAttempt = client.getLastLocationForBackend(entry.serviceInfo.packageName, entry.serviceInfo.name, entry.firstSignatureDigest)
                    if (secondAttempt == null) {
                        Log.d(TAG, "Location still not available, waiting or giving up")
                        delay(WAIT_FOR_RESULT)
                        client.getLastLocationForBackend(entry.serviceInfo.packageName, entry.serviceInfo.name, entry.firstSignatureDigest)
                    } else {
                        secondAttempt
                    }
                }
                else -> locationTemp
            } ?: return
            var locationString = "${location.latitude.toStringWithDigits(6)}, ${location.longitude.toStringWithDigits(6)}"

            val address = client.getFromLocation(location.latitude, location.longitude, 1, Locale.getDefault().toString()).singleOrNull()
@@ -100,12 +143,15 @@ class BackendDetailsFragment : Fragment(R.layout.backend_details) {
                }
                locationString = addressLine.toString()
            }
            updateInProgress = false
            binding.lastLocationString = locationString
            binding.executePendingBindings()
        } else {
            Log.d(TAG, "Location is not available for this backend (type: ${entry?.type}, enabled ${entry?.enabled}")
            binding.lastLocationString = ""
            binding.executePendingBindings()
        }
    }
        return binding.root
    }

    fun onBackendEnabledChanged(entry: BackendInfo) {
        entry.enabled = !entry.enabled
@@ -130,6 +176,14 @@ class BackendDetailsFragment : Fragment(R.layout.backend_details) {
        entry.settingsActivity?.let { activityName -> startExternalActivity(entry.serviceInfo.packageName, activityName) }
    }

    fun onAppClicked(entry: BackendInfo) {
        val intent = Intent()
        intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        val uri = Uri.fromParts("package", entry.serviceInfo.packageName, null)
        intent.data = uri
        requireContext().startActivity(intent)
    }

    private suspend fun createBackendInfo(): BackendInfo? {
        val activity = activity ?: return null
        val intent = activity.intent ?: return null
@@ -147,9 +201,11 @@ class BackendDetailsFragment : Fragment(R.layout.backend_details) {
    }

    companion object {
        val ACTION = "org.microg.nlp.ui.BACKEND_DETAILS"
        val EXTRA_TYPE = "org.microg.nlp.ui.BackendDetailsFragment.type"
        val EXTRA_PACKAGE = "org.microg.nlp.ui.BackendDetailsFragment.package"
        val EXTRA_NAME = "org.microg.nlp.ui.BackendDetailsFragment.name"
        const val ACTION = "org.microg.nlp.ui.BACKEND_DETAILS"
        const val EXTRA_TYPE = "org.microg.nlp.ui.BackendDetailsFragment.type"
        const val EXTRA_PACKAGE = "org.microg.nlp.ui.BackendDetailsFragment.package"
        const val EXTRA_NAME = "org.microg.nlp.ui.BackendDetailsFragment.name"
        private const val TAG = "USettings"
        private const val WAIT_FOR_RESULT = 5000L
    }
}
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ class BackendInfo(val context: Context, val serviceInfo: ServiceInfo, val type:
    val settingsActivity: String? by lazy { serviceInfo.metaData?.getString(Constants.METADATA_BACKEND_SETTINGS_ACTIVITY) }
    val aboutActivity: String? by lazy { serviceInfo.metaData?.getString(Constants.METADATA_BACKEND_ABOUT_ACTIVITY) }

    override fun equals(other: Any?): Boolean {
        return other is BackendInfo && other.name == name && other.enabled == enabled && other.appName == appName && other.unsignedComponent == unsignedComponent && other.backendSummary == backendSummary
    }
}

enum class BackendType { LOCATION, GEOCODER }
+55 −14
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.delay
import org.microg.nlp.api.Constants.*
import org.microg.nlp.client.UnifiedLocationClient
import org.microg.nlp.ui.BackendDetailsFragment.Companion.EXTRA_NAME
@@ -32,36 +34,39 @@ class BackendListFragment : Fragment(R.layout.backend_list) {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val binding = BackendListBinding.inflate(inflater, container, false)
        binding.fragment = this
        lifecycleScope.launchWhenStarted { updateAdapters() }
        return binding.root
    }

    fun onBackendSelected(entry: BackendInfo) {
    override fun onResume() {
        super.onResume()
        lifecycleScope.launchWhenStarted { updateAdapters() }
    }

    fun onBackendSelected(entry: BackendInfo?) {
        if (entry == null) return
        val intent = Intent(BackendDetailsFragment.ACTION)
        //intent.`package` = requireContext().packageName
        intent.`package` = requireContext().packageName
        intent.putExtra(EXTRA_TYPE, entry.type.name)
        intent.putExtra(EXTRA_PACKAGE, entry.serviceInfo.packageName)
        intent.putExtra(EXTRA_NAME, entry.serviceInfo.name)
        context?.packageManager?.queryIntentActivities(intent, 0)?.forEach {
            Log.d("USettings", it.activityInfo.name)
        }
        startActivity(intent)
    }

    private suspend fun updateAdapters() {
        val context = requireContext()
        locationAdapter.entries = createBackendInfoList(context, Intent(ACTION_LOCATION_BACKEND), UnifiedLocationClient[context].getLocationBackends(), BackendType.LOCATION)
        geocoderAdapter.entries = createBackendInfoList(context, Intent(ACTION_GEOCODER_BACKEND), UnifiedLocationClient[context].getGeocoderBackends(), BackendType.GEOCODER)
        locationAdapter.setEntries(createBackendInfoList(context, Intent(ACTION_LOCATION_BACKEND), UnifiedLocationClient[context].getLocationBackends(), BackendType.LOCATION))
        geocoderAdapter.setEntries(createBackendInfoList(context, Intent(ACTION_GEOCODER_BACKEND), UnifiedLocationClient[context].getGeocoderBackends(), BackendType.GEOCODER))
    }

    private fun createBackendInfoList(context: Context, intent: Intent, enabledBackends: Array<String>, type: BackendType): Array<BackendInfo> {
    private fun createBackendInfoList(context: Context, intent: Intent, enabledBackends: Array<String>, type: BackendType): Array<BackendInfo?> {
        val backends = context.packageManager.queryIntentServices(intent, GET_META_DATA).map { BackendInfo(context, it.serviceInfo, type, lifecycleScope, enabledBackends) }
        if (backends.isEmpty()) return arrayOf(null)
        return backends.toTypedArray()
    }
}

class BackendSettingsLineViewHolder(val binding: BackendListEntryBinding) : RecyclerView.ViewHolder(binding.root) {
    fun bind(fragment: BackendListFragment, entry: BackendInfo) {
    fun bind(fragment: BackendListFragment, entry: BackendInfo?) {
        binding.fragment = fragment
        binding.entry = entry
        binding.executePendingBindings()
@@ -69,10 +74,46 @@ class BackendSettingsLineViewHolder(val binding: BackendListEntryBinding) : Recy
}

class BackendSettingsLineAdapter(val fragment: BackendListFragment) : RecyclerView.Adapter<BackendSettingsLineViewHolder>() {
    var entries: Array<BackendInfo> = emptyArray()
        set(value) {
            field = value
            notifyDataSetChanged()
    private val entries: MutableList<BackendInfo?> = arrayListOf()

    fun addOrUpdateEntry(entry: BackendInfo?) {
        if (entry == null) {
            if (entries.contains(null)) return
            entries.add(entry)
            notifyItemInserted(entries.size - 1)
        } else {
            val oldIndex = entries.indexOfFirst { it?.unsignedComponent == entry.unsignedComponent }
            if (oldIndex != -1) {
                if (entries[oldIndex] == entry) return
                entries.removeAt(oldIndex)
            }
            val targetIndex = when (val i = entries.indexOfFirst { it == null || it.name.toString() > entry.name.toString() }) {
                -1 -> entries.size
                else -> i
            }
            entries.add(targetIndex, entry)
            when (oldIndex) {
                targetIndex -> notifyItemChanged(targetIndex)
                -1 -> notifyItemInserted(targetIndex)
                else -> notifyItemMoved(oldIndex, targetIndex)
            }
        }
    }

    fun removeEntry(entry: BackendInfo?) {
        val index = entries.indexOfFirst { it == entry || it?.unsignedComponent == entry?.unsignedComponent }
        entries.removeAt(index)
        notifyItemRemoved(index)
    }

    fun setEntries(entries: Array<BackendInfo?>) {
        val oldEntries = this.entries.toTypedArray()
        for (oldEntry in oldEntries) {
            if (!entries.any { it == oldEntry || it?.unsignedComponent == oldEntry?.unsignedComponent }) {
                removeEntry(oldEntry)
            }
        }
        entries.forEach { addOrUpdateEntry(it) }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BackendSettingsLineViewHolder {
Loading