CrackMe.apk
Download file
package androidx.core.app;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.v4.app.INotificationSideChannel;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public final class NotificationManagerCompat {
public static final String ACTION_BIND_SIDE_CHANNEL = "android.support.BIND_NOTIFICATION_SIDE_CHANNEL";
private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
public static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel";
public static final int IMPORTANCE_DEFAULT = 3;
public static final int IMPORTANCE_HIGH = 4;
public static final int IMPORTANCE_LOW = 2;
public static final int IMPORTANCE_MAX = 5;
public static final int IMPORTANCE_MIN = 1;
public static final int IMPORTANCE_NONE = 0;
public static final int IMPORTANCE_UNSPECIFIED = -1000;
static final int MAX_SIDE_CHANNEL_SDK_VERSION = 19;
private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
private static final String SETTING_ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
private static final int SIDE_CHANNEL_RETRY_BASE_INTERVAL_MS = 1000;
private static final int SIDE_CHANNEL_RETRY_MAX_COUNT = 6;
private static final String TAG = "NotifManCompat";
private static Set<String> sEnabledNotificationListenerPackages = new HashSet();
private static String sEnabledNotificationListeners;
private static final Object sEnabledNotificationListenersLock = new Object();
private static final Object sLock = new Object();
private static SideChannelManager sSideChannelManager;
private final Context mContext;
private final NotificationManager mNotificationManager;
private interface Task {
void send(INotificationSideChannel iNotificationSideChannel) throws RemoteException;
}
public static NotificationManagerCompat from(Context context) {
return new NotificationManagerCompat(context);
}
private NotificationManagerCompat(Context context) {
this.mContext = context;
this.mNotificationManager = (NotificationManager) context.getSystemService("notification");
}
public void cancel(int i) {
cancel((String) null, i);
}
public void cancel(String str, int i) {
this.mNotificationManager.cancel(str, i);
if (Build.VERSION.SDK_INT <= 19) {
pushSideChannelQueue(new CancelTask(this.mContext.getPackageName(), i, str));
}
}
public void cancelAll() {
this.mNotificationManager.cancelAll();
if (Build.VERSION.SDK_INT <= 19) {
pushSideChannelQueue(new CancelTask(this.mContext.getPackageName()));
}
}
public void notify(int i, Notification notification) {
notify((String) null, i, notification);
}
public void notify(String str, int i, Notification notification) {
if (useSideChannelForNotification(notification)) {
pushSideChannelQueue(new NotifyTask(this.mContext.getPackageName(), i, str, notification));
this.mNotificationManager.cancel(str, i);
return;
}
this.mNotificationManager.notify(str, i, notification);
}
public boolean areNotificationsEnabled() {
if (Build.VERSION.SDK_INT >= 24) {
return this.mNotificationManager.areNotificationsEnabled();
}
if (Build.VERSION.SDK_INT < 19) {
return true;
}
AppOpsManager appOpsManager = (AppOpsManager) this.mContext.getSystemService("appops");
ApplicationInfo applicationInfo = this.mContext.getApplicationInfo();
String packageName = this.mContext.getApplicationContext().getPackageName();
int i = applicationInfo.uid;
try {
Class<?> cls = Class.forName(AppOpsManager.class.getName());
if (((Integer) cls.getMethod(CHECK_OP_NO_THROW, new Class[]{Integer.TYPE, Integer.TYPE, String.class}).invoke(appOpsManager, new Object[]{Integer.valueOf(((Integer) cls.getDeclaredField(OP_POST_NOTIFICATION).get(Integer.class)).intValue()), Integer.valueOf(i), packageName})).intValue() == 0) {
return true;
}
return false;
} catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException | NoSuchMethodException | RuntimeException | InvocationTargetException unused) {
return true;
}
}
public int getImportance() {
if (Build.VERSION.SDK_INT >= 24) {
return this.mNotificationManager.getImportance();
}
return -1000;
}
public void createNotificationChannel(NotificationChannel notificationChannel) {
if (Build.VERSION.SDK_INT >= 26) {
this.mNotificationManager.createNotificationChannel(notificationChannel);
}
}
public void createNotificationChannel(NotificationChannelCompat notificationChannelCompat) {
createNotificationChannel(notificationChannelCompat.getNotificationChannel());
}
public void createNotificationChannelGroup(NotificationChannelGroup notificationChannelGroup) {
if (Build.VERSION.SDK_INT >= 26) {
this.mNotificationManager.createNotificationChannelGroup(notificationChannelGroup);
}
}
public void createNotificationChannelGroup(NotificationChannelGroupCompat notificationChannelGroupCompat) {
createNotificationChannelGroup(notificationChannelGroupCompat.getNotificationChannelGroup());
}
public void createNotificationChannels(List<NotificationChannel> list) {
if (Build.VERSION.SDK_INT >= 26) {
this.mNotificationManager.createNotificationChannels(list);
}
}
public void createNotificationChannelsCompat(List<NotificationChannelCompat> list) {
if (Build.VERSION.SDK_INT >= 26 && !list.isEmpty()) {
ArrayList arrayList = new ArrayList(list.size());
for (NotificationChannelCompat notificationChannel : list) {
arrayList.add(notificationChannel.getNotificationChannel());
}
this.mNotificationManager.createNotificationChannels(arrayList);
}
}
public void createNotificationChannelGroups(List<NotificationChannelGroup> list) {
if (Build.VERSION.SDK_INT >= 26) {
this.mNotificationManager.createNotificationChannelGroups(list);
}
}
public void createNotificationChannelGroupsCompat(List<NotificationChannelGroupCompat> list) {
if (Build.VERSION.SDK_INT >= 26 && !list.isEmpty()) {
ArrayList arrayList = new ArrayList(list.size());
for (NotificationChannelGroupCompat notificationChannelGroup : list) {
arrayList.add(notificationChannelGroup.getNotificationChannelGroup());
}
this.mNotificationManager.createNotificationChannelGroups(arrayList);
}
}
public void deleteNotificationChannel(String str) {
if (Build.VERSION.SDK_INT >= 26) {
this.mNotificationManager.deleteNotificationChannel(str);
}
}
public void deleteNotificationChannelGroup(String str) {
if (Build.VERSION.SDK_INT >= 26) {
this.mNotificationManager.deleteNotificationChannelGroup(str);
}
}
public void deleteUnlistedNotificationChannels(Collection<String> collection) {
if (Build.VERSION.SDK_INT >= 26) {
for (NotificationChannel next : this.mNotificationManager.getNotificationChannels()) {
if (!collection.contains(next.getId()) && (Build.VERSION.SDK_INT < 30 || !collection.contains(next.getParentChannelId()))) {
this.mNotificationManager.deleteNotificationChannel(next.getId());
}
}
}
}
public NotificationChannel getNotificationChannel(String str) {
if (Build.VERSION.SDK_INT >= 26) {
return this.mNotificationManager.getNotificationChannel(str);
}
return null;
}
public NotificationChannelCompat getNotificationChannelCompat(String str) {
NotificationChannel notificationChannel;
if (Build.VERSION.SDK_INT < 26 || (notificationChannel = getNotificationChannel(str)) == null) {
return null;
}
return new NotificationChannelCompat(notificationChannel);
}
public NotificationChannel getNotificationChannel(String str, String str2) {
if (Build.VERSION.SDK_INT >= 30) {
return this.mNotificationManager.getNotificationChannel(str, str2);
}
return getNotificationChannel(str);
}
public NotificationChannelCompat getNotificationChannelCompat(String str, String str2) {
NotificationChannel notificationChannel;
if (Build.VERSION.SDK_INT < 26 || (notificationChannel = getNotificationChannel(str, str2)) == null) {
return null;
}
return new NotificationChannelCompat(notificationChannel);
}
public NotificationChannelGroup getNotificationChannelGroup(String str) {
if (Build.VERSION.SDK_INT >= 28) {
return this.mNotificationManager.getNotificationChannelGroup(str);
}
if (Build.VERSION.SDK_INT >= 26) {
for (NotificationChannelGroup next : getNotificationChannelGroups()) {
if (next.getId().equals(str)) {
return next;
}
}
}
return null;
}
public NotificationChannelGroupCompat getNotificationChannelGroupCompat(String str) {
NotificationChannelGroup notificationChannelGroup;
if (Build.VERSION.SDK_INT >= 28) {
NotificationChannelGroup notificationChannelGroup2 = getNotificationChannelGroup(str);
if (notificationChannelGroup2 != null) {
return new NotificationChannelGroupCompat(notificationChannelGroup2);
}
return null;
} else if (Build.VERSION.SDK_INT < 26 || (notificationChannelGroup = getNotificationChannelGroup(str)) == null) {
return null;
} else {
return new NotificationChannelGroupCompat(notificationChannelGroup, getNotificationChannels());
}
}
public List<NotificationChannel> getNotificationChannels() {
if (Build.VERSION.SDK_INT >= 26) {
return this.mNotificationManager.getNotificationChannels();
}
return Collections.emptyList();
}
public List<NotificationChannelCompat> getNotificationChannelsCompat() {
if (Build.VERSION.SDK_INT >= 26) {
List<NotificationChannel> notificationChannels = getNotificationChannels();
if (!notificationChannels.isEmpty()) {
ArrayList arrayList = new ArrayList(notificationChannels.size());
for (NotificationChannel notificationChannelCompat : notificationChannels) {
arrayList.add(new NotificationChannelCompat(notificationChannelCompat));
}
return arrayList;
}
}
return Collections.emptyList();
}
public List<NotificationChannelGroup> getNotificationChannelGroups() {
if (Build.VERSION.SDK_INT >= 26) {
return this.mNotificationManager.getNotificationChannelGroups();
}
return Collections.emptyList();
}
public List<NotificationChannelGroupCompat> getNotificationChannelGroupsCompat() {
List<NotificationChannel> list;
if (Build.VERSION.SDK_INT >= 26) {
List<NotificationChannelGroup> notificationChannelGroups = getNotificationChannelGroups();
if (!notificationChannelGroups.isEmpty()) {
if (Build.VERSION.SDK_INT >= 28) {
list = Collections.emptyList();
} else {
list = getNotificationChannels();
}
ArrayList arrayList = new ArrayList(notificationChannelGroups.size());
for (NotificationChannelGroup next : notificationChannelGroups) {
if (Build.VERSION.SDK_INT >= 28) {
arrayList.add(new NotificationChannelGroupCompat(next));
} else {
arrayList.add(new NotificationChannelGroupCompat(next, list));
}
}
return arrayList;
}
}
return Collections.emptyList();
}
public static Set<String> getEnabledListenerPackages(Context context) {
Set<String> set;
String string = Settings.Secure.getString(context.getContentResolver(), SETTING_ENABLED_NOTIFICATION_LISTENERS);
synchronized (sEnabledNotificationListenersLock) {
if (string != null) {
if (!string.equals(sEnabledNotificationListeners)) {
String[] split = string.split(":", -1);
HashSet hashSet = new HashSet(split.length);
for (String unflattenFromString : split) {
ComponentName unflattenFromString2 = ComponentName.unflattenFromString(unflattenFromString);
if (unflattenFromString2 != null) {
hashSet.add(unflattenFromString2.getPackageName());
}
}
sEnabledNotificationListenerPackages = hashSet;
sEnabledNotificationListeners = string;
}
}
set = sEnabledNotificationListenerPackages;
}
return set;
}
private static boolean useSideChannelForNotification(Notification notification) {
Bundle extras = NotificationCompat.getExtras(notification);
return extras != null && extras.getBoolean(EXTRA_USE_SIDE_CHANNEL);
}
private void pushSideChannelQueue(Task task) {
synchronized (sLock) {
if (sSideChannelManager == null) {
sSideChannelManager = new SideChannelManager(this.mContext.getApplicationContext());
}
sSideChannelManager.queueTask(task);
}
}
private static class SideChannelManager implements Handler.Callback, ServiceConnection {
private static final int MSG_QUEUE_TASK = 0;
private static final int MSG_RETRY_LISTENER_QUEUE = 3;
private static final int MSG_SERVICE_CONNECTED = 1;
private static final int MSG_SERVICE_DISCONNECTED = 2;
private Set<String> mCachedEnabledPackages = new HashSet();
private final Context mContext;
private final Handler mHandler;
private final HandlerThread mHandlerThread;
private final Map<ComponentName, ListenerRecord> mRecordMap = new HashMap();
SideChannelManager(Context context) {
this.mContext = context;
HandlerThread handlerThread = new HandlerThread("NotificationManagerCompat");
this.mHandlerThread = handlerThread;
handlerThread.start();
this.mHandler = new Handler(handlerThread.getLooper(), this);
}
public void queueTask(Task task) {
this.mHandler.obtainMessage(0, task).sendToTarget();
}
public boolean handleMessage(Message message) {
int i = message.what;
if (i == 0) {
handleQueueTask((Task) message.obj);
return true;
} else if (i == 1) {
ServiceConnectedEvent serviceConnectedEvent = (ServiceConnectedEvent) message.obj;
handleServiceConnected(serviceConnectedEvent.componentName, serviceConnectedEvent.iBinder);
return true;
} else if (i == 2) {
handleServiceDisconnected((ComponentName) message.obj);
return true;
} else if (i != 3) {
return false;
} else {
handleRetryListenerQueue((ComponentName) message.obj);
return true;
}
}
private void handleQueueTask(Task task) {
updateListenerMap();
for (ListenerRecord next : this.mRecordMap.values()) {
next.taskQueue.add(task);
processListenerQueue(next);
}
}
private void handleServiceConnected(ComponentName componentName, IBinder iBinder) {
ListenerRecord listenerRecord = this.mRecordMap.get(componentName);
if (listenerRecord != null) {
listenerRecord.service = INotificationSideChannel.Stub.asInterface(iBinder);
listenerRecord.retryCount = 0;
processListenerQueue(listenerRecord);
}
}
private void handleServiceDisconnected(ComponentName componentName) {
ListenerRecord listenerRecord = this.mRecordMap.get(componentName);
if (listenerRecord != null) {
ensureServiceUnbound(listenerRecord);
}
}
private void handleRetryListenerQueue(ComponentName componentName) {
ListenerRecord listenerRecord = this.mRecordMap.get(componentName);
if (listenerRecord != null) {
processListenerQueue(listenerRecord);
}
}
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Connected to service " + componentName);
}
this.mHandler.obtainMessage(1, new ServiceConnectedEvent(componentName, iBinder)).sendToTarget();
}
public void onServiceDisconnected(ComponentName componentName) {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Disconnected from service " + componentName);
}
this.mHandler.obtainMessage(2, componentName).sendToTarget();
}
private void updateListenerMap() {
Set<String> enabledListenerPackages = NotificationManagerCompat.getEnabledListenerPackages(this.mContext);
if (!enabledListenerPackages.equals(this.mCachedEnabledPackages)) {
this.mCachedEnabledPackages = enabledListenerPackages;
List<ResolveInfo> queryIntentServices = this.mContext.getPackageManager().queryIntentServices(new Intent().setAction(NotificationManagerCompat.ACTION_BIND_SIDE_CHANNEL), 0);
HashSet<ComponentName> hashSet = new HashSet<>();
for (ResolveInfo next : queryIntentServices) {
if (enabledListenerPackages.contains(next.serviceInfo.packageName)) {
ComponentName componentName = new ComponentName(next.serviceInfo.packageName, next.serviceInfo.name);
if (next.serviceInfo.permission != null) {
Log.w(NotificationManagerCompat.TAG, "Permission present on component " + componentName + ", not adding listener record.");
} else {
hashSet.add(componentName);
}
}
}
for (ComponentName componentName2 : hashSet) {
if (!this.mRecordMap.containsKey(componentName2)) {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Adding listener record for " + componentName2);
}
this.mRecordMap.put(componentName2, new ListenerRecord(componentName2));
}
}
Iterator<Map.Entry<ComponentName, ListenerRecord>> it = this.mRecordMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry next2 = it.next();
if (!hashSet.contains(next2.getKey())) {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Removing listener record for " + next2.getKey());
}
ensureServiceUnbound((ListenerRecord) next2.getValue());
it.remove();
}
}
}
}
private boolean ensureServiceBound(ListenerRecord listenerRecord) {
if (listenerRecord.bound) {
return true;
}
listenerRecord.bound = this.mContext.bindService(new Intent(NotificationManagerCompat.ACTION_BIND_SIDE_CHANNEL).setComponent(listenerRecord.componentName), this, 33);
if (listenerRecord.bound) {
listenerRecord.retryCount = 0;
} else {
Log.w(NotificationManagerCompat.TAG, "Unable to bind to listener " + listenerRecord.componentName);
this.mContext.unbindService(this);
}
return listenerRecord.bound;
}
private void ensureServiceUnbound(ListenerRecord listenerRecord) {
if (listenerRecord.bound) {
this.mContext.unbindService(this);
listenerRecord.bound = false;
}
listenerRecord.service = null;
}
private void scheduleListenerRetry(ListenerRecord listenerRecord) {
if (!this.mHandler.hasMessages(3, listenerRecord.componentName)) {
listenerRecord.retryCount++;
if (listenerRecord.retryCount > 6) {
Log.w(NotificationManagerCompat.TAG, "Giving up on delivering " + listenerRecord.taskQueue.size() + " tasks to " + listenerRecord.componentName + " after " + listenerRecord.retryCount + " retries");
listenerRecord.taskQueue.clear();
return;
}
int i = (1 << (listenerRecord.retryCount - 1)) * 1000;
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Scheduling retry for " + i + " ms");
}
this.mHandler.sendMessageDelayed(this.mHandler.obtainMessage(3, listenerRecord.componentName), (long) i);
}
}
private void processListenerQueue(ListenerRecord listenerRecord) {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Processing component " + listenerRecord.componentName + ", " + listenerRecord.taskQueue.size() + " queued tasks");
}
if (!listenerRecord.taskQueue.isEmpty()) {
if (!ensureServiceBound(listenerRecord) || listenerRecord.service == null) {
scheduleListenerRetry(listenerRecord);
return;
}
while (true) {
Task peek = listenerRecord.taskQueue.peek();
if (peek == null) {
break;
}
try {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Sending task " + peek);
}
peek.send(listenerRecord.service);
listenerRecord.taskQueue.remove();
} catch (DeadObjectException unused) {
if (Log.isLoggable(NotificationManagerCompat.TAG, 3)) {
Log.d(NotificationManagerCompat.TAG, "Remote service has died: " + listenerRecord.componentName);
}
} catch (RemoteException e) {
Log.w(NotificationManagerCompat.TAG, "RemoteException communicating with " + listenerRecord.componentName, e);
}
}
if (!listenerRecord.taskQueue.isEmpty()) {
scheduleListenerRetry(listenerRecord);
}
}
}
private static class ListenerRecord {
boolean bound = false;
final ComponentName componentName;
int retryCount = 0;
INotificationSideChannel service;
ArrayDeque<Task> taskQueue = new ArrayDeque<>();
ListenerRecord(ComponentName componentName2) {
this.componentName = componentName2;
}
}
}
private static class ServiceConnectedEvent {
final ComponentName componentName;
final IBinder iBinder;
ServiceConnectedEvent(ComponentName componentName2, IBinder iBinder2) {
this.componentName = componentName2;
this.iBinder = iBinder2;
}
}
private static class NotifyTask implements Task {
final int id;
final Notification notif;
final String packageName;
final String tag;
NotifyTask(String str, int i, String str2, Notification notification) {
this.packageName = str;
this.id = i;
this.tag = str2;
this.notif = notification;
}
public void send(INotificationSideChannel iNotificationSideChannel) throws RemoteException {
iNotificationSideChannel.notify(this.packageName, this.id, this.tag, this.notif);
}
public String toString() {
return "NotifyTask[" + "packageName:" + this.packageName + ", id:" + this.id + ", tag:" + this.tag + "]";
}
}
private static class CancelTask implements Task {
final boolean all;
final int id;
final String packageName;
final String tag;
CancelTask(String str) {
this.packageName = str;
this.id = 0;
this.tag = null;
this.all = true;
}
CancelTask(String str, int i, String str2) {
this.packageName = str;
this.id = i;
this.tag = str2;
this.all = false;
}
public void send(INotificationSideChannel iNotificationSideChannel) throws RemoteException {
if (this.all) {
iNotificationSideChannel.cancelAll(this.packageName);
} else {
iNotificationSideChannel.cancel(this.packageName, this.id, this.tag);
}
}
public String toString() {
return "CancelTask[" + "packageName:" + this.packageName + ", id:" + this.id + ", tag:" + this.tag + ", all:" + this.all + "]";
}
}
}
Download file