package biz.bokhorst.xprivacy; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.support.v4.app.NotificationCompat; import android.util.Log; public class PackageChange extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { try { // Check uri Uri inputUri = intent.getData(); if (inputUri.getScheme().equals("package")) { // Get data int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); int userId = Util.getUserId(uid); boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); boolean ondemand = PrivacyManager.getSettingBool(userId, PrivacyManager.cSettingOnDemand, true); NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); Util.log(null, Log.WARN, "Package change action=" + intent.getAction() + " replacing=" + replacing + " uid=" + uid); // Check action if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) { // Check privacy service if (PrivacyService.getClient() == null) return; // Get data ApplicationInfoEx appInfo = new ApplicationInfoEx(context, uid); String packageName = inputUri.getSchemeSpecificPart(); // Default deny new user apps if (appInfo.getPackageName().size() == 1) { if (replacing) PrivacyManager.clearPermissionCache(uid); else { // Delete existing restrictions PrivacyManager.deleteRestrictions(uid, null, true); PrivacyManager.deleteSettings(uid); PrivacyManager.deleteUsage(uid); PrivacyManager.clearPermissionCache(uid); // Apply template PrivacyManager.applyTemplate(uid, Meta.cTypeTemplate, null, true, true, false); // Enable on demand if (ondemand) PrivacyManager.setSetting(uid, PrivacyManager.cSettingOnDemand, Boolean.toString(true)); } } // Mark as new/changed PrivacyManager.setSetting(uid, PrivacyManager.cSettingState, Integer.toString(ApplicationInfoEx.STATE_ATTENTION)); // New/update notification boolean notify = PrivacyManager.getSettingBool(userId, PrivacyManager.cSettingNotify, true); if (notify) notify = PrivacyManager.getSettingBool(-uid, PrivacyManager.cSettingNotify, true); if (!replacing || notify) { Intent resultIntent = new Intent(context, ActivityApp.class); resultIntent.putExtra(ActivityApp.cUid, uid); // Build pending intent PendingIntent pendingIntent = PendingIntent.getActivity(context, uid, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Build result intent settings Intent resultIntentSettings = new Intent(context, ActivityApp.class); resultIntentSettings.putExtra(ActivityApp.cUid, uid); resultIntentSettings.putExtra(ActivityApp.cAction, ActivityApp.cActionSettings); // Build pending intent settings PendingIntent pendingIntentSettings = PendingIntent.getActivity(context, uid - 10000, resultIntentSettings, PendingIntent.FLAG_UPDATE_CURRENT); // Build result intent clear Intent resultIntentClear = new Intent(context, ActivityApp.class); resultIntentClear.putExtra(ActivityApp.cUid, uid); resultIntentClear.putExtra(ActivityApp.cAction, ActivityApp.cActionClear); // Build pending intent clear PendingIntent pendingIntentClear = PendingIntent.getActivity(context, uid + 10000, resultIntentClear, PendingIntent.FLAG_UPDATE_CURRENT); // Title String title = String.format("%s %s %s", context.getString(replacing ? R.string.msg_update : R.string.msg_new), appInfo.getApplicationName(packageName), appInfo.getPackageVersionName(context, packageName)); if (!replacing) title = String.format("%s %s", title, context.getString(R.string.msg_applied)); // Build notification NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context); notificationBuilder.setSmallIcon(R.drawable.ic_launcher); notificationBuilder.setContentTitle(context.getString(R.string.app_name)); notificationBuilder.setContentText(title); notificationBuilder.setContentIntent(pendingIntent); notificationBuilder.setWhen(System.currentTimeMillis()); notificationBuilder.setAutoCancel(true); // Actions notificationBuilder.addAction(android.R.drawable.ic_menu_edit, context.getString(R.string.menu_app_settings), pendingIntentSettings); notificationBuilder.addAction(android.R.drawable.ic_menu_delete, context.getString(R.string.menu_clear), pendingIntentClear); // Notify Notification notification = notificationBuilder.build(); notificationManager.notify(appInfo.getUid(), notification); } } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { // Check privacy service if (PrivacyService.getClient() == null) return; if (!replacing) { // Package removed notificationManager.cancel(uid); // Delete restrictions ApplicationInfoEx appInfo = new ApplicationInfoEx(context, uid); if (appInfo.getPackageName().size() == 0) { PrivacyManager.deleteRestrictions(uid, null, false); PrivacyManager.deleteSettings(uid); PrivacyManager.deleteUsage(uid); PrivacyManager.clearPermissionCache(uid); } } } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) { // Notify reboot required String packageName = inputUri.getSchemeSpecificPart(); if (packageName.equals(context.getPackageName())) { // Mark self as new/changed if (PrivacyService.getClient() != null) PrivacyManager.setSetting(uid, PrivacyManager.cSettingState, Integer.toString(ApplicationInfoEx.STATE_ATTENTION)); // Start package update Intent changeIntent = new Intent(); changeIntent.setClass(context, UpdateService.class); changeIntent.putExtra(UpdateService.cAction, UpdateService.cActionUpdated); context.startService(changeIntent); // Build notification NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context); notificationBuilder.setSmallIcon(R.drawable.ic_launcher); notificationBuilder.setContentTitle(context.getString(R.string.app_name)); notificationBuilder.setContentText(context.getString(R.string.msg_reboot)); notificationBuilder.setWhen(System.currentTimeMillis()); notificationBuilder.setAutoCancel(true); Notification notification = notificationBuilder.build(); // Notify notificationManager.notify(Util.NOTIFY_RESTART, notification); } } } } catch (Throwable ex) { Util.bug(null, ex); } } }