1717
1818package net .kollnig .missioncontrol .analysis ;
1919
20+ import static net .kollnig .missioncontrol .DetailsActivity .INTENT_EXTRA_APP_NAME ;
21+ import static net .kollnig .missioncontrol .DetailsActivity .INTENT_EXTRA_APP_PACKAGENAME ;
22+ import static net .kollnig .missioncontrol .DetailsActivity .INTENT_EXTRA_APP_UID ;
23+
24+ import android .app .Notification ;
25+ import android .app .PendingIntent ;
2026import android .content .Context ;
27+ import android .content .Intent ;
2128import android .content .pm .PackageInfo ;
2229import android .content .pm .PackageManager ;
30+ import android .net .Uri ;
31+ import android .os .Build ;
32+ import android .provider .Settings ;
33+ import android .util .Log ;
2334
2435import androidx .annotation .NonNull ;
36+ import androidx .core .app .NotificationCompat ;
37+ import androidx .core .app .NotificationManagerCompat ;
2538import androidx .work .Data ;
2639import androidx .work .Worker ;
2740import androidx .work .WorkerParameters ;
2841
42+ import eu .faircode .netguard .PendingIntentCompat ;
43+ import eu .faircode .netguard .Util ;
44+ import net .kollnig .missioncontrol .DetailsActivity ;
45+ import net .kollnig .missioncontrol .R ;
46+
2947import java .util .concurrent .atomic .AtomicInteger ;
48+ import java .util .concurrent .Semaphore ;
3049
3150public class TrackerAnalysisWorker extends Worker {
51+ private static final String TAG = TrackerAnalysisWorker .class .getSimpleName ();
52+ private static final Semaphore ANALYSIS_SEMAPHORE = new Semaphore (1 );
53+
3254 public static final String KEY_PACKAGE_NAME = "package_name" ;
55+ public static final String KEY_NOTIFICATION_UID = "notification_uid" ;
56+ public static final String KEY_APP_NAME = "app_name" ;
3357 public static final String KEY_RESULT = "result" ;
3458 public static final String KEY_ERROR = "error" ;
3559 public static final String KEY_PROGRESS = "progress" ;
@@ -48,17 +72,23 @@ public Result doWork() {
4872 .build ());
4973 }
5074
75+ boolean acquired = false ;
5176 try {
5277 Context context = getApplicationContext ();
5378 PackageInfo pkg = context .getPackageManager ().getPackageInfo (packageName , 0 );
5479
80+ ANALYSIS_SEMAPHORE .acquire ();
81+ acquired = true ;
82+
5583 // Perform analysis with progress reporting
5684 String result = doAnalysis (context , packageName );
5785
5886 // Cache the result
5987 TrackerAnalysisManager .getInstance (context )
6088 .cacheResult (packageName , result , pkg .versionCode );
6189
90+ updateInstallNotification (context , packageName , result );
91+
6292 return Result .success (new Data .Builder ()
6393 .putString (KEY_RESULT , result )
6494 .build ());
@@ -75,6 +105,9 @@ public Result doWork() {
75105 return Result .failure (new Data .Builder ()
76106 .putString (KEY_ERROR , e .getMessage () != null ? e .getMessage () : "Unknown error" )
77107 .build ());
108+ } finally {
109+ if (acquired )
110+ ANALYSIS_SEMAPHORE .release ();
78111 }
79112 }
80113
@@ -91,4 +124,54 @@ private String doAnalysis(Context context, String packageName) throws AnalysisEx
91124 });
92125 return analyser .analyseApp (packageName );
93126 }
127+
128+ private void updateInstallNotification (Context context , String packageName , String result ) {
129+ int uid = getInputData ().getInt (KEY_NOTIFICATION_UID , -1 );
130+ if (uid < 0 || !Util .canNotify (context ))
131+ return ;
132+
133+ String appName = getInputData ().getString (KEY_APP_NAME );
134+ if (appName == null )
135+ appName = packageName ;
136+
137+ try {
138+ NotificationManagerCompat .from (context ).notify (uid ,
139+ buildInstallNotification (context , packageName , uid , appName , result ));
140+ } catch (SecurityException ex ) {
141+ Log .w (TAG , "SecurityException updating install notification for uid " + uid + ": " + ex .getMessage ());
142+ }
143+ }
144+
145+ static Notification buildInstallNotification (Context context , String packageName , int uid , String appName ,
146+ String result ) {
147+ int trackerCount = TrackerAnalysisManager .countTrackers (result );
148+
149+ Intent main = new Intent (context , DetailsActivity .class );
150+ main .putExtra (INTENT_EXTRA_APP_NAME , appName );
151+ main .putExtra (INTENT_EXTRA_APP_PACKAGENAME , packageName );
152+ main .putExtra (INTENT_EXTRA_APP_UID , uid );
153+ PendingIntent pi = PendingIntentCompat .getActivity (context , uid , main ,
154+ PendingIntent .FLAG_UPDATE_CURRENT );
155+
156+ NotificationCompat .Builder builder = new NotificationCompat .Builder (context , "notify" );
157+ builder .setSmallIcon (R .drawable .ic_rocket_white )
158+ .setContentIntent (pi )
159+ .addAction (0 , context .getString (R .string .title_activity_detail ), pi )
160+ .setColor (context .getResources ().getColor (R .color .colorTrackerControl ))
161+ .setAutoCancel (true );
162+ builder .setContentTitle (context .getString (R .string .msg_installed , appName ))
163+ .setContentText (context .getString (R .string .msg_installed_tracker_libraries_found , trackerCount ));
164+
165+ Intent intent = new Intent (Settings .ACTION_APPLICATION_DETAILS_SETTINGS );
166+ intent .setData (Uri .parse ("package:" + packageName ));
167+ PendingIntent piUninstall = PendingIntentCompat .getActivity (context , uid + 10000 , intent ,
168+ PendingIntent .FLAG_UPDATE_CURRENT );
169+ builder .addAction (0 , context .getString (R .string .uninstall ), piUninstall );
170+
171+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP )
172+ builder .setCategory (NotificationCompat .CATEGORY_STATUS )
173+ .setVisibility (NotificationCompat .VISIBILITY_SECRET );
174+
175+ return builder .build ();
176+ }
94177}
0 commit comments