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

Unverified Commit 84259b23 authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Location: Add UI, various fixes

parent c730ca6d
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -145,6 +145,22 @@ object SettingsContract {
        )
    }

    object Location {
        private const val id = "location"
        fun getContentUri(context: Context) = Uri.withAppendedPath(getAuthorityUri(context), id)
        fun getContentType(context: Context) = "vnd.android.cursor.item/vnd.${getAuthority(context)}.$id"

        const val WIFI_MLS = "location_wifi_mls"
        const val WIFI_MOVING = "location_wifi_moving"
        const val CELL_MLS = "location_cell_mls"

        val PROJECTION = arrayOf(
            WIFI_MLS,
            WIFI_MOVING,
            CELL_MLS
        )
    }

    private fun <T> withoutCallingIdentity(f: () -> T): T {
        val identity = Binder.clearCallingIdentity()
        try {
+26 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import org.microg.gms.settings.SettingsContract.CheckIn
import org.microg.gms.settings.SettingsContract.DroidGuard
import org.microg.gms.settings.SettingsContract.Exposure
import org.microg.gms.settings.SettingsContract.Gcm
import org.microg.gms.settings.SettingsContract.Location
import org.microg.gms.settings.SettingsContract.Profile
import org.microg.gms.settings.SettingsContract.SafetyNet
import org.microg.gms.settings.SettingsContract.getAuthority
@@ -67,6 +68,7 @@ class SettingsProvider : ContentProvider() {
        SafetyNet.getContentUri(context!!) -> querySafetyNet(projection ?: SafetyNet.PROJECTION)
        DroidGuard.getContentUri(context!!) -> queryDroidGuard(projection ?: DroidGuard.PROJECTION)
        Profile.getContentUri(context!!) -> queryProfile(projection ?: Profile.PROJECTION)
        Location.getContentUri(context!!) -> queryLocation(projection ?: Location.PROJECTION)
        else -> null
    }

@@ -86,6 +88,7 @@ class SettingsProvider : ContentProvider() {
            SafetyNet.getContentUri(context!!) -> updateSafetyNet(values)
            DroidGuard.getContentUri(context!!) -> updateDroidGuard(values)
            Profile.getContentUri(context!!) -> updateProfile(values)
            Location.getContentUri(context!!) -> updateLocation(values)
            else -> return 0
        }
        return 1
@@ -288,6 +291,29 @@ class SettingsProvider : ContentProvider() {
        editor.apply()
    }

    private fun queryLocation(p: Array<out String>): Cursor = MatrixCursor(p).addRow(p) { key ->
        when (key) {
            Location.WIFI_MLS -> getSettingsBoolean(key, true)
            Location.WIFI_MOVING -> getSettingsBoolean(key, true)
            Location.CELL_MLS -> getSettingsBoolean(key, true)
            else -> throw IllegalArgumentException("Unknown key: $key")
        }
    }

    private fun updateLocation(values: ContentValues) {
        if (values.size() == 0) return
        val editor = preferences.edit()
        values.valueSet().forEach { (key, value) ->
            when (key) {
                Location.WIFI_MLS -> editor.putBoolean(key, value as Boolean)
                Location.WIFI_MOVING -> editor.putBoolean(key, value as Boolean)
                Location.CELL_MLS -> editor.putBoolean(key, value as Boolean)
                else -> throw IllegalArgumentException("Unknown key: $key")
            }
        }
        editor.apply()
    }

    private fun MatrixCursor.addRow(
        p: Array<out String>,
        valueGetter: (String) -> Any?
+150 −0
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2023 microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package org.microg.gms.utils

import android.app.AlarmManager
import android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_NO_CREATE
import android.app.PendingIntent.FLAG_MUTABLE
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION.SDK_INT
import android.os.Parcelable
import android.os.SystemClock
import android.util.Log
import androidx.core.content.getSystemService
import java.util.UUID

class IntentCacheManager<S : Service, T : Parcelable>(private val context: Context, private val clazz: Class<S>, private val type: Int) {
    private val lock = Any()
    private lateinit var content: ArrayList<T>
    private lateinit var id: String
    private var isReady: Boolean = false
    private val pendingActions: MutableList<() -> Unit> = arrayListOf()

    init {
        val pendingIntent = PendingIntent.getService(context, type, getIntent(), if (SDK_INT >= 31) FLAG_MUTABLE else 0)
        val alarmManager = context.getSystemService<AlarmManager>()
        if (SDK_INT >= 19) {
            alarmManager?.setWindow(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TEN_YEARS, -1, pendingIntent)
        } else {
            alarmManager?.set(ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TEN_YEARS, pendingIntent)
        }
        pendingIntent.send()
    }

    private fun getIntent() = Intent(context, clazz).apply {
        action = ACTION
        putExtra(EXTRA_IS_CACHE, true)
        putExtra(EXTRA_CACHE_TYPE, this@IntentCacheManager.type)
    }

    fun add(entry: T, check: (T) -> Boolean = { false }) = runIfReady {
        val iterator = content.iterator()
        while (iterator.hasNext()) {
            if (check(iterator.next())) {
                iterator.remove()
            }
        }
        content.add(entry)
        updateIntent()
    }

    fun remove(entry: T) = runIfReady {
        if (content.remove(entry)) updateIntent()
    }

    fun removeIf(check: (T) -> Boolean) = runIfReady {
        var removed = false
        val iterator = content.iterator()
        while (iterator.hasNext()) {
            if (check(iterator.next())) {
                iterator.remove()
                removed = true
            }
        }
        if (removed) updateIntent()
    }

    fun clear() = runIfReady {
        content.clear()
        updateIntent()
    }

    fun getId(): String? = if (this::id.isInitialized) id else null

    fun getEntries(): List<T> = if (this::content.isInitialized) content else emptyList()

    fun processIntent(intent: Intent) {
        if (isCache(intent) && getType(intent) == type) {
            synchronized(lock) {
                content = intent.getParcelableArrayListExtra(EXTRA_DATA) ?: arrayListOf()
                id = intent.getStringExtra(EXTRA_ID) ?: UUID.randomUUID().toString()
                if (!intent.hasExtra(EXTRA_ID)) {
                    Log.d(TAG, "Created new intent cache with id $id")
                } else if (intent.hasExtra(EXTRA_DATA)) {
                    Log.d(TAG, "Recovered data from intent cache with id $id")
                }
                pendingActions.forEach { it() }
                pendingActions.clear()
                isReady = true
                updateIntent()
            }
        }
    }

    private fun runIfReady(action: () -> Unit) {
        synchronized(lock) {
            if (isReady) {
                action()
            } else {
                pendingActions.add(action)
            }
        }
    }

    private fun updateIntent() {
        synchronized(lock) {
            if (isReady) {
                val intent = getIntent().apply {
                    putExtra(EXTRA_ID, id)
                    putParcelableArrayListExtra(EXTRA_DATA, content)
                }
                val pendingIntent = PendingIntent.getService(context, type, intent, FLAG_NO_CREATE or FLAG_UPDATE_CURRENT or if (SDK_INT >= 31) FLAG_MUTABLE else 0)
                if (pendingIntent == null) {
                    Log.w(TAG, "Failed to update existing pending intent, will likely have a loss of information")
                }
            }
        }
    }

    companion object {
        private const val TAG = "IntentCacheManager"
        private const val TEN_YEARS = 315360000000L
        private const val ACTION = "org.microg.gms.ACTION_INTENT_CACHE_MANAGER"
        private const val EXTRA_IS_CACHE = "org.microg.gms.IntentCacheManager.is_cache"
        private const val EXTRA_CACHE_TYPE = "org.microg.gms.IntentCacheManager.cache_type"
        private const val EXTRA_ID = "org.microg.gms.IntentCacheManager.id"
        private const val EXTRA_DATA = "org.microg.gms.IntentCacheManager.data"

        inline fun<reified S: Service, T: Parcelable> create(context: Context, type: Int) = IntentCacheManager<S, T>(context, S::class.java, type)

        fun isCache(intent: Intent): Boolean = try {
            intent.getBooleanExtra(EXTRA_IS_CACHE, false)
        } catch (e: Exception) {
            false
        }

        fun getType(intent: Intent): Int {
            val ret = intent.getIntExtra(EXTRA_CACHE_TYPE, -1)
            if (ret == -1) throw IllegalArgumentException()
            return ret
        }
    }
}
 No newline at end of file
+8 −3
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2020, microG Project Team
 * SPDX-FileCopyrightText: 2023 microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

@@ -11,15 +11,20 @@ dependencies {
    compileOnly project(':play-services-location-system-api')
    implementation project(':play-services-base-core')

    implementation "androidx.lifecycle:lifecycle-service:$lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"
    implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
    implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
    implementation "androidx.preference:preference-ktx:$preferenceVersion"

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion"
    implementation "androidx.lifecycle:lifecycle-service:$lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"

    implementation "com.android.volley:volley:$volleyVersion"

    implementation 'org.microg:address-formatter:0.3.1'
    compileOnly project(':play-services-maps')
}

android {
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.BODY_SENSORS"/>
Loading