@Nullable protected AlarmManager getAlarmManager() { if (mAlarmManager == null) { mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); } if (mAlarmManager == null) { // https://gist.github.com/vRallev/5daef6e8a3b0d4a7c366 mCat.e("AlarmManager is null"); } return mAlarmManager; } }
protected PendingIntent getPendingIntent(int jobId, boolean exact, @Nullable Bundle transientExtras, int flags) { Intent intent = PlatformAlarmReceiver.createIntent(mContext, jobId, exact, transientExtras); // repeating PendingIntent with service seams to have problems try { return PendingIntent.getBroadcast(mContext, jobId, intent, flags); } catch (Exception e) { // java.lang.SecurityException: Permission Denial: getIntentSender() from pid=31482, uid=10057, // (need uid=-1) is not allowed to send as package com.evernote mCat.e(e); return null; } }
static void releaseWakeLock(@Nullable PowerManager.WakeLock wakeLock) { try { if (wakeLock != null && wakeLock.isHeld()) { wakeLock.release(); } } catch (Exception e) { // just to make sure if the PowerManager crashes while acquiring a wake lock CAT.e(e); } }
public Common(@NonNull Context context, JobCat cat, int jobId) { mContext = context; mJobId = jobId; mCat = cat; JobManager manager; try { manager = JobManager.create(context); } catch (JobManagerCreateException e) { mCat.e(e); manager = null; } mJobManager = manager; }
private static boolean hasPermission(Context context, String permission, int repeatCount) { try { return PackageManager.PERMISSION_GRANTED == context.getPackageManager() .checkPermission(permission, context.getPackageName()); } catch (Exception e) { CAT.e(e); // crash https://gist.github.com/vRallev/6affe17c93e993681bfd // give it another chance with the application context return repeatCount < 1 && hasPermission(context.getApplicationContext(), permission, repeatCount + 1); } } }
/*package*/ static void startService(Context context) { try { enqueueWork(context, JobRescheduleService.class, JobIdsInternal.JOB_ID_JOB_RESCHEDULE_SERVICE, new Intent()); latch = new CountDownLatch(1); } catch (Exception e) { /* * Caused by: java.lang.SecurityException: Unable to start service Intent * { cmp=com.evernote/.android.job.JobRescheduleService (has extras) }: Unable to launch * app com.evernote/1210016 for service Intent { cmp=com.evernote/.android.job.JobRescheduleService }: * user 12 is stopped * * It's bad to catch all exceptions. But this service is only a safety check and * if it fails, then better try next time and don't handle the exception upstream * where it's hard to deal with this case. */ CAT.e(e); } }
static boolean acquireWakeLock(@NonNull Context context, @Nullable PowerManager.WakeLock wakeLock, long timeoutMillis) { if (wakeLock != null && !wakeLock.isHeld() && JobUtil.hasWakeLockPermission(context)) { // Even if we have the permission, some devices throw an exception in the try block nonetheless, // I'm looking at you, Samsung SM-T805 try { wakeLock.acquire(timeoutMillis); return true; } catch (Exception e) { // saw an NPE on rooted Galaxy Nexus Android 4.1.1 // android.os.IPowerManager$Stub$Proxy.acquireWakeLock(IPowerManager.java:288) CAT.e(e); } } return false; }
public void update(JobRequest request, ContentValues contentValues) { SQLiteDatabase database = null; mLock.writeLock().lock(); try { updateRequestInCache(request); database = getDatabase(); database.update(JOB_TABLE_NAME, contentValues, COLUMN_ID + "=?", new String[]{String.valueOf(request.getJobId())}); } catch (Exception e) { // catch the exception here and keep what's in the database CAT.e(e, "could not update %s", request); } finally { closeDatabase(database); mLock.writeLock().unlock(); } }
private boolean remove(@Nullable JobRequest request, int jobId) { SQLiteDatabase database = null; mLock.writeLock().lock(); try { mCacheId.remove(jobId); database = getDatabase(); database.delete(JOB_TABLE_NAME, COLUMN_ID + "=?", new String[]{String.valueOf(jobId)}); return true; } catch (Exception e) { CAT.e(e, "could not delete %d %s", jobId, request); addFailedDeleteId(jobId); return false; } finally { closeDatabase(database); mLock.writeLock().unlock(); } }
public static void cancel(@NonNull Context context, int jobId, @Nullable PendingIntent pendingIntent) { try { if (pendingIntent == null) { Intent intent = PlatformAlarmServiceExact.createIntent(context, jobId, null); pendingIntent = PendingIntent.getService(context, jobId, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent == null) { return; } } AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent); pendingIntent.cancel(); } catch (Exception e) { CAT.e(e); // we don't care if it fails, we don't want to crash the library } } }
/*package*/ void deleteDatabaseFile(String fileName) { if (fileName.equalsIgnoreCase(":memory:") || fileName.trim().length() == 0) { return; } CAT.e("deleting the database file: " + fileName); try { File databaseFile = new File(fileName); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { deleteApi16(databaseFile); } else { deleteApi14(JobManager.instance().getContext(), databaseFile); } } catch (Exception e) { /* print warning and ignore exception */ CAT.w(e, "delete failed: " + e.getMessage()); } }
@VisibleForTesting /*package*/ int getMaxJobId() { SQLiteDatabase database = null; Cursor cursor = null; int jobId = 0; try { database = getDatabase(); cursor = database.rawQuery("SELECT MAX(" + COLUMN_ID + ") FROM " + JOB_TABLE_NAME, null); if (cursor != null && cursor.moveToFirst()) { jobId = cursor.getInt(0); } } catch (Exception e) { CAT.e(e); } finally { closeCursor(cursor); closeDatabase(database); } return Math.max(JobConfig.getJobIdOffset(), Math.max(jobId, mPreferences.getInt(JOB_ID_COUNTER, 0))); }
@Override public void cancel(int jobId) { try { getJobScheduler().cancel(jobId); } catch (Exception e) { // https://gist.github.com/vRallev/5d48a4a8e8d05067834e mCat.e(e); } TransientBundleCompat.cancel(mContext, jobId, null); }
/*package*/ JobRequest reschedule(boolean failure, boolean newJob) { JobRequest newRequest = new Builder(this.mBuilder, newJob).build(); if (failure) { newRequest.mFailureCount = mFailureCount + 1; } try { newRequest.schedule(); } catch (Exception e) { CAT.e(e); // this may crash (e.g. more than 100 jobs with JobScheduler), but it's not catchable for the user, wait for reschedule } return newRequest; }
@Override public void plantPeriodicFlexSupport(JobRequest request) { PendingIntent pendingIntent = getPendingIntent(request, false); AlarmManager alarmManager = getAlarmManager(); if (alarmManager == null) { return; } try { plantOneOffFlexSupport(request, alarmManager, pendingIntent); } catch (Exception e) { // https://gist.github.com/vRallev/621b0b76a14ddde8691c mCat.e(e); } }
private Job.Result runJob() { Job.Result result; try { result = mJob.runJob(); CAT.i("Finished %s", mJob); handleResult(mJob, result); } catch (Throwable t) { CAT.e(t, "Crashed %s", mJob); result = mJob.getResult(); // probably the default value } return result; }
@Override public boolean isPlatformJobScheduled(JobRequest request) { try { return isJobInfoScheduled(getJobScheduler().getPendingJob(request.getJobId()), request); } catch (Exception e) { mCat.e(e); return false; } }
@NonNull @VisibleForTesting /*package*/ SQLiteDatabase getDatabase() { if (mInjectedDatabase != null) { return mInjectedDatabase; } else { try { return mDbHelper.getWritableDatabase(); } catch (SQLiteCantOpenDatabaseException e) { CAT.e(e); // that's bad, delete the database and try again, otherwise users may get stuck in a loop new JobStorageDatabaseErrorHandler().deleteDatabaseFile(DATABASE_NAME); return mDbHelper.getWritableDatabase(); } } }
public static boolean startWithTransientBundle(@NonNull Context context, @NonNull JobRequest request) { // transientExtras are not necessary in this case Intent intent = PlatformAlarmServiceExact.createIntent(context, request.getJobId(), null); PendingIntent pendingIntent = PendingIntent.getService(context, request.getJobId(), intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent == null) { return false; } try { CAT.i("Delegating transient job %s to API 14", request); pendingIntent.send(); } catch (PendingIntent.CanceledException e) { CAT.e(e); return false; } if (!request.isPeriodic()) { cancel(context, request.getJobId(), pendingIntent); } return true; }
@Override public void cancel(int jobId) { AlarmManager alarmManager = getAlarmManager(); if (alarmManager != null) { try { // exact parameter doesn't matter alarmManager.cancel(getPendingIntent(jobId, false, null, createPendingIntentFlags(true))); alarmManager.cancel(getPendingIntent(jobId, false, null, createPendingIntentFlags(false))); } catch (Exception e) { // java.lang.SecurityException: get application info: Neither user 1010133 nor // current process has android.permission.INTERACT_ACROSS_USERS. mCat.e(e); } } }