summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhishek Aggarwal <warabhishek@e.email>2022-04-13 14:26:50 +0000
committerAbhishek Aggarwal <warabhishek@e.email>2022-04-13 14:26:50 +0000
commit5658347ab0099c4f512e19a3807d38758396114a (patch)
treed3843d84ed1da95f9f43a34bd1fc82c480b789cf
parent714db561375e369a9bc080447de6a7b5e619870b (diff)
parent14815678aaa5020e81f0cca9274f289e6ac7e2d5 (diff)
Merge branch '5249_alpha_issues' into 'main'
Fix 5249 5255 5248 alpha issues See merge request e/privacy-central/privacycentralapp!41
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/common/BootCompletedReceiver.kt146
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt3
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt21
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt51
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt6
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt7
-rw-r--r--app/src/main/res/layout/apptrackers_fragment.xml27
-rw-r--r--app/src/main/res/layout/fragment_dashboard.xml12
-rw-r--r--app/src/main/res/layout/fragment_trackers.xml8
-rw-r--r--app/src/main/res/values/strings.xml4
11 files changed, 174 insertions, 113 deletions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/BootCompletedReceiver.kt b/app/src/main/java/foundation/e/privacycentralapp/common/BootCompletedReceiver.kt
index a26c06a..f43c2cc 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/common/BootCompletedReceiver.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/common/BootCompletedReceiver.kt
@@ -1,73 +1,73 @@
-/*
- * Copyright (C) 2022 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.privacycentralapp.common
-
-import android.app.NotificationChannel
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import androidx.core.app.NotificationCompat
-import foundation.e.privacycentralapp.R
-import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
-
-class BootCompletedReceiver : BroadcastReceiver() {
- companion object {
- const val FIRST_BOOT_NOTIFICATION_ID = 10
- }
-
- override fun onReceive(context: Context, intent: Intent?) {
- if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
- val localStateRepository = LocalStateRepository(context)
- if (localStateRepository.firstBoot) {
- showNotification(context)
- localStateRepository.firstBoot = false
- }
- }
- }
-
- private fun showNotification(context: Context) {
- val channelId = "first_boot_notification"
- val pendingIntent =
- PendingIntent.getActivity(
- context,
- 0,
- context.packageManager.getLaunchIntentForPackage(context.packageName),
- PendingIntent.FLAG_IMMUTABLE
- )
- val notificationBuilder: NotificationCompat.Builder =
- NotificationCompat.Builder(context, channelId)
- .setSmallIcon(R.drawable.ic_notification_logo)
- .setContentTitle(context.getString(R.string.first_notification_title))
- .setAutoCancel(true)
- .setContentIntent(pendingIntent)
- .setStyle(
- NotificationCompat.BigTextStyle()
- .bigText(context.getString(R.string.first_notification_summary))
- )
- val notificationManager =
- context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
-
- val name: CharSequence = "First Boot"
- val importance = NotificationManager.IMPORTANCE_HIGH
- val mChannel = NotificationChannel(channelId, name, importance)
- notificationManager.createNotificationChannel(mChannel)
- notificationManager.notify(FIRST_BOOT_NOTIFICATION_ID, notificationBuilder.build())
- }
-}
+/*
+ * Copyright (C) 2022 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.privacycentralapp.common
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import androidx.core.app.NotificationCompat
+import foundation.e.privacycentralapp.R
+import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
+
+class BootCompletedReceiver : BroadcastReceiver() {
+ companion object {
+ const val FIRST_BOOT_NOTIFICATION_ID = 10
+ }
+
+ override fun onReceive(context: Context, intent: Intent?) {
+ if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
+ val localStateRepository = LocalStateRepository(context)
+ if (localStateRepository.firstBoot) {
+ showNotification(context)
+ localStateRepository.firstBoot = false
+ }
+ }
+ }
+
+ private fun showNotification(context: Context) {
+ val channelId = "first_boot_notification"
+ val pendingIntent =
+ PendingIntent.getActivity(
+ context,
+ 0,
+ context.packageManager.getLaunchIntentForPackage(context.packageName),
+ PendingIntent.FLAG_IMMUTABLE
+ )
+ val notificationBuilder: NotificationCompat.Builder =
+ NotificationCompat.Builder(context, channelId)
+ .setSmallIcon(R.drawable.ic_notification_logo)
+ .setContentTitle(context.getString(R.string.first_notification_title))
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+ .setStyle(
+ NotificationCompat.BigTextStyle()
+ .bigText(context.getString(R.string.first_notification_summary))
+ )
+ val notificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ val name: CharSequence = "First Boot"
+ val importance = NotificationManager.IMPORTANCE_HIGH
+ val mChannel = NotificationChannel(channelId, name, importance)
+ notificationManager.createNotificationChannel(mChannel)
+ notificationManager.notify(FIRST_BOOT_NOTIFICATION_ID, notificationBuilder.build())
+ }
+}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
index 9242765..4b19083 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
@@ -59,6 +59,9 @@ class AppListsRepository(
return appDescriptions.value.second
}
+ fun getVisibleAndHiddenApps(): Flow<List<ApplicationDescription>> = getVisibleApps()
+ .map { it + getHiddenSystemApps() }
+
fun getApplicationDescription(packageName: String): ApplicationDescription? {
return appDescriptions.value.first.find { it.packageName == packageName }
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt
index 4262055..6b4e098 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt
@@ -28,6 +28,7 @@ import foundation.e.privacymodules.trackers.Tracker
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
@@ -142,7 +143,8 @@ class TrackersStatisticsUseCase(
apps.map { app ->
AppWithCounts(
app,
- blockTrackersPrivacyModule.isWhitelisted(app.uid),
+ !blockTrackersPrivacyModule.isBlockingEnabled() ||
+ blockTrackersPrivacyModule.isWhitelisted(app.uid),
appListsRepository.foldForHiddenSystemApp(app.uid) {
trackersCounts.getOrDefault(it, 0)
},
@@ -153,4 +155,21 @@ class TrackersStatisticsUseCase(
}
}
}
+
+ fun getNonBlockedTrackersCount(): Flow<Int> {
+ return if (blockTrackersPrivacyModule.isBlockingEnabled())
+ appListsRepository.getVisibleAndHiddenApps().map { apps ->
+ val whiteListedTrackers = mutableSetOf<Tracker>()
+ val whiteListedAppUids = blockTrackersPrivacyModule.getWhiteListedApp()
+ apps.forEach { app ->
+ if (app.uid in whiteListedAppUids) {
+ whiteListedTrackers.addAll(getTrackers(app.uid))
+ } else {
+ whiteListedTrackers.addAll(blockTrackersPrivacyModule.getWhiteList(app.uid))
+ }
+ }
+ whiteListedTrackers.size
+ }
+ else flowOf(trackTrackersPrivacyModule.getTrackersCount())
+ }
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt
index 8a4ee54..ca45393 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt
@@ -53,8 +53,7 @@ class DashboardFeature(
val isAllTrackersBlocked: Boolean = false,
val locationMode: LocationMode = LocationMode.REAL_LOCATION,
val internetPrivacyMode: InternetPrivacyMode = InternetPrivacyMode.REAL_IP,
- val totalGraph: Int? = null,
- // val graphData
+ val leakedTrackersCount: Int? = null,
val trackersCount: Int? = null,
val activeTrackersCount: Int? = null,
val dayStatistics: List<Pair<Int, Int>>? = null,
@@ -87,7 +86,8 @@ class DashboardFeature(
val dayStatistics: List<Pair<Int, Int>>,
val dayLabels: List<String>,
val dayTrackersCount: Int,
- val trackersCount: Int
+ val trackersCount: Int,
+ val activeTrackersCount: Int
) : Effect()
data class TrackersBlockedUpdatedEffect(val areAllTrackersBlocked: Boolean) : Effect()
data class UpdateLocationModeEffect(val mode: LocationMode) : Effect()
@@ -117,8 +117,9 @@ class DashboardFeature(
is Effect.TrackersStatisticsUpdatedEffect -> state.copy(
dayStatistics = effect.dayStatistics,
dayLabels = effect.dayLabels,
- activeTrackersCount = effect.dayTrackersCount,
- trackersCount = effect.trackersCount
+ leakedTrackersCount = effect.dayTrackersCount,
+ trackersCount = effect.trackersCount,
+ activeTrackersCount = effect.activeTrackersCount
)
is Effect.TrackersBlockedUpdatedEffect -> state.copy(
@@ -133,7 +134,7 @@ class DashboardFeature(
when (action) {
Action.TogglePrivacyAction -> {
getPrivacyStateUseCase.toggle()
- flowOf(Effect.NoEffect)
+ flowOf(Effect.NewStatisticsAvailablesEffect)
}
Action.InitAction -> merge(
@@ -146,18 +147,6 @@ class DashboardFeature(
trackersStatisticsUseCase.listenUpdates().map {
Effect.NewStatisticsAvailablesEffect
},
- flowOf<Effect>(
- // trackersStatisticsUseCase.listenDayStatistics().map {
- trackersStatisticsUseCase.getDayStatistics().let {
- (dayStatistics, trackersCount) ->
- Effect.TrackersStatisticsUpdatedEffect(
- dayStatistics = dayStatistics.callsBlockedNLeaked,
- dayLabels = dayStatistics.periods,
- dayTrackersCount = dayStatistics.trackersCount,
- trackersCount = trackersCount
- )
- }
- ),
trackersStateUseCase.areAllTrackersBlocked.map {
Effect.TrackersBlockedUpdatedEffect(it)
},
@@ -171,18 +160,20 @@ class DashboardFeature(
Effect.OpenInternetActivityPrivacyEffect
)
Action.ShowTrackers -> flowOf(Effect.OpenTrackersEffect)
- Action.FetchStatistics -> flowOf<Effect>(
- // trackersStatisticsUseCase.listenDayStatistics().map {
- trackersStatisticsUseCase.getDayStatistics().let {
- (dayStatistics, trackersCount) ->
- Effect.TrackersStatisticsUpdatedEffect(
- dayStatistics = dayStatistics.callsBlockedNLeaked,
- dayLabels = dayStatistics.periods,
- dayTrackersCount = dayStatistics.trackersCount,
- trackersCount = trackersCount
- )
- }
- )
+ Action.FetchStatistics ->
+ trackersStatisticsUseCase.getNonBlockedTrackersCount()
+ .map { nonBlockedTrackersCount ->
+ trackersStatisticsUseCase.getDayStatistics()
+ .let { (dayStatistics, trackersCount) ->
+ Effect.TrackersStatisticsUpdatedEffect(
+ dayStatistics = dayStatistics.callsBlockedNLeaked,
+ dayLabels = dayStatistics.periods,
+ dayTrackersCount = dayStatistics.trackersCount,
+ trackersCount = trackersCount,
+ activeTrackersCount = nonBlockedTrackersCount
+ )
+ }
+ }
}
},
singleEventProducer = { _, _, effect ->
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt
index 51dee3d..96ace56 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt
@@ -231,7 +231,7 @@ class DashboardFragment :
binding.graphLegend.text = Html.fromHtml(
getString(
R.string.dashboard_graph_trackers_legend,
- state.activeTrackersCount?.toString() ?: "No"
+ state.leakedTrackersCount?.toString() ?: "No"
),
FROM_HTML_MODE_LEGACY
)
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt
index 270dfcb..c1eef47 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt
@@ -66,7 +66,7 @@ class AppTrackersFeature(
}
fun getTrackersCount() = trackers?.size ?: 0
- fun getBlockedTrackersCount(): Int = if (isBlockingActivated)
+ fun getBlockedTrackersCount(): Int = if (isQuickPrivacyEnabled && isBlockingActivated)
getTrackersCount() - (whitelist?.size ?: 0)
else 0
}
@@ -160,7 +160,9 @@ class AppTrackersFeature(
} ?: flowOf(Effect.ErrorEffect(R.string.apptrackers_error_no_app))
is Action.BlockAllToggleAction ->
- state.appDesc?.uid?.let { appUid ->
+ if (!state.isQuickPrivacyEnabled) {
+ flowOf(Effect.QuickPrivacyDisabledWarningEffect)
+ } else state.appDesc?.uid?.let { appUid ->
flow {
trackersStateUseCase.toggleAppWhitelist(appUid, !action.isBlocked)
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt
index 8e2dc3b..d6edee6 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt
@@ -109,6 +109,10 @@ class AppTrackersFragment :
viewModel.submitAction(Action.BlockAllToggleAction(binding.blockAllToggle.isChecked))
}
+ binding.blockAllToggleClicker.setOnClickListener {
+ viewModel.submitAction(Action.BlockAllToggleAction(false))
+ }
+
binding.trackers.apply {
layoutManager = LinearLayoutManager(requireContext())
setHasFixedSize(true)
@@ -128,7 +132,6 @@ class AppTrackersFragment :
}
override fun render(state: State) {
-
binding.trackersCountSummary.text = if (state.getTrackersCount() == 0) ""
else getString(
R.string.apptrackers_trackers_count_summary,
@@ -137,6 +140,8 @@ class AppTrackersFragment :
)
binding.blockAllToggle.isChecked = state.isBlockingActivated
+ binding.blockAllToggle.isEnabled = state.isQuickPrivacyEnabled
+ binding.blockAllToggleClicker.isVisible = !state.isQuickPrivacyEnabled
binding.trackersListTitle.isVisible = state.isBlockingActivated
diff --git a/app/src/main/res/layout/apptrackers_fragment.xml b/app/src/main/res/layout/apptrackers_fragment.xml
index b0b9e71..3eb9168 100644
--- a/app/src/main/res/layout/apptrackers_fragment.xml
+++ b/app/src/main/res/layout/apptrackers_fragment.xml
@@ -60,10 +60,31 @@
android:layout_weight="1"
android:text="@string/apptrackers_block_all_toggle"
/>
- <Switch
- android:id="@+id/block_all_toggle"
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content">
+
+ <Switch
+ android:id="@+id/block_all_toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ android:checked="true"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ />
+ <View
+ android:id="@+id/block_all_toggle_clicker"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:clickable="true"
+ />
+ </androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml
index ff64733..d2cb53c 100644
--- a/app/src/main/res/layout/fragment_dashboard.xml
+++ b/app/src/main/res/layout/fragment_dashboard.xml
@@ -168,6 +168,18 @@ android:text="@string/dashboard_state_ipaddress_off"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
+ <TextView
+ android:id="@+id/graph_subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/graph_subtitle"
+ android:layout_marginLeft="16dp"
+ android:paddingTop="4dp"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/graph_title"
+ android:textColor="@color/secondary_text"
+ android:textSize="14sp"
+ />
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/graph"
diff --git a/app/src/main/res/layout/fragment_trackers.xml b/app/src/main/res/layout/fragment_trackers.xml
index 2122816..7ee4d29 100644
--- a/app/src/main/res/layout/fragment_trackers.xml
+++ b/app/src/main/res/layout/fragment_trackers.xml
@@ -35,10 +35,16 @@
android:lineSpacingExtra="5sp"
android:text="@string/trackers_info"
/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/graph_subtitle"
+ android:paddingTop="24dp"
+ />
<include layout="@layout/trackers_item_graph"
android:id="@+id/graph_day"
- android:layout_marginTop="32dp"
+ android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:period="@{@string/trackers_period_day}"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 199472d..cf293e1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -6,6 +6,8 @@
<string name="graph_empty_message">Congratulations! No trackers are profiling you.</string>
<string name="graph_legend_blocked">Blocked leaks</string>
<string name="graph_legend_allowed">Allowed leaks</string>
+ <string name="graph_subtitle">Tap on the bars for more information.</string>
+
<!-- Dashboard -->
<string name="dashboard_title">@string/app_name</string>
@@ -20,7 +22,7 @@
<string name="dashboard_state_ipaddress_label">Real IP address:</string>
<string name="dashboard_state_ipaddress_off">Exposed</string>
<string name="dashboard_state_ipaddress_on">Hidden</string>
- <string name="dashboard_graph_label">Personal data leakage</string>
+ <string name="dashboard_graph_label">Personal data leakage:</string>
<string name="dashboard_graph_period">Today</string>
<string name="dashboard_graph_trackers_legend">%s trackers have profiled you in the last 24 hours</string>