Loading services/core/java/com/android/server/job/JobSchedulerService.java +99 −23 Original line number Diff line number Diff line Loading @@ -1270,6 +1270,17 @@ public final class JobSchedulerService extends com.android.server.SystemService } } private void stopNonReadyActiveJobsLocked() { for (int i=0; i<mActiveServices.size(); i++) { JobServiceContext serviceContext = mActiveServices.get(i); final JobStatus running = serviceContext.getRunningJobLocked(); if (running != null && !running.isReady()) { serviceContext.cancelExecutingJobLocked( JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } } } /** * Run through list of jobs and execute all possible - at least one is expired so we do * as many as we can. Loading @@ -1280,6 +1291,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } noteJobsNonpending(mPendingJobs); mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mReadyQueueFunctor); mReadyQueueFunctor.postProcess(); Loading @@ -1306,9 +1318,6 @@ public final class JobSchedulerService extends com.android.server.SystemService newReadyJobs = new ArrayList<JobStatus>(); } newReadyJobs.add(job); } else if (areJobConstraintsNotSatisfiedLocked(job)) { stopJobOnServiceContextLocked(job, JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } } Loading Loading @@ -1387,9 +1396,6 @@ public final class JobSchedulerService extends com.android.server.SystemService runnableJobs = new ArrayList<>(); } runnableJobs.add(job); } else if (areJobConstraintsNotSatisfiedLocked(job)) { stopJobOnServiceContextLocked(job, JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } } Loading Loading @@ -1439,6 +1445,7 @@ public final class JobSchedulerService extends com.android.server.SystemService noteJobsNonpending(mPendingJobs); mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mMaybeQueueFunctor); mMaybeQueueFunctor.postProcess(); } Loading Loading @@ -1515,15 +1522,6 @@ public final class JobSchedulerService extends com.android.server.SystemService return componentPresent; } /** * Criteria for cancelling an active job: * - It's not ready * - It's running on a JSC. */ private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) { return !job.isReady() && isCurrentlyActiveLocked(job); } /** * Reconcile jobs in the pending queue against available execution contexts. * A controller can force a job into the pending queue even if it's already running, but Loading Loading @@ -2088,6 +2086,83 @@ public final class JobSchedulerService extends com.android.server.SystemService } } int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) { try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM); if (uid < 0) { pw.print("unknown("); pw.print(pkgName); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE; } synchronized (mLock) { final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId); if (DEBUG) Slog.d(TAG, "get-job-state " + uid + "/" + jobId + ": " + js); if (js == null) { pw.print("unknown("); UserHandle.formatUid(pw, uid); pw.print("/jid"); pw.print(jobId); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } boolean printed = false; if (mPendingJobs.contains(js)) { pw.print("pending"); printed = true; } if (isCurrentlyActiveLocked(js)) { if (printed) { pw.print(" "); } printed = true; pw.println("active"); } if (!ArrayUtils.contains(mStartedUsers, js.getUserId())) { if (printed) { pw.print(" "); } printed = true; pw.println("user-stopped"); } if (mBackingUpUids.indexOfKey(js.getSourceUid()) >= 0) { if (printed) { pw.print(" "); } printed = true; pw.println("backing-up"); } boolean componentPresent = false; try { componentPresent = (AppGlobals.getPackageManager().getServiceInfo( js.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, js.getUserId()) != null); } catch (RemoteException e) { } if (!componentPresent) { if (printed) { pw.print(" "); } printed = true; pw.println("no-component"); } if (js.isReady()) { if (printed) { pw.print(" "); } printed = true; pw.println("ready"); } if (!printed) { pw.print("waiting"); } pw.println(); } } catch (RemoteException e) { // can't happen } return 0; } private String printContextIdToJobMap(JobStatus[] map, String initial) { StringBuilder s = new StringBuilder(initial + ": "); for (int i=0; i<map.length; i++) { Loading Loading @@ -2152,7 +2227,8 @@ public final class JobSchedulerService extends com.android.server.SystemService } final int filterUidFinal = UserHandle.getAppId(filterUid); final long now = SystemClock.elapsedRealtime(); final long nowElapsed = SystemClock.elapsedRealtime(); final long nowUptime = SystemClock.uptimeMillis(); synchronized (mLock) { mConstants.dump(pw); pw.println(); Loading Loading @@ -2184,7 +2260,7 @@ public final class JobSchedulerService extends com.android.server.SystemService continue; } job.dump(pw, " ", true, now); job.dump(pw, " ", true, nowElapsed); pw.print(" Ready: "); pw.print(isReadyToBeExecutedLocked(job)); pw.print(" (job="); Loading Loading @@ -2254,14 +2330,14 @@ public final class JobSchedulerService extends com.android.server.SystemService JobStatus job = mPendingJobs.get(i); pw.print(" Pending #"); pw.print(i); pw.print(": "); pw.println(job.toShortString()); job.dump(pw, " ", false, now); job.dump(pw, " ", false, nowElapsed); int priority = evaluateJobPriorityLocked(job); if (priority != JobInfo.PRIORITY_DEFAULT) { pw.print(" Evaluated priority: "); pw.println(priority); } pw.print(" Tag: "); pw.println(job.getTag()); pw.print(" Enq: "); TimeUtils.formatDuration(job.madePending - now, pw); TimeUtils.formatDuration(job.madePending - nowUptime, pw); pw.println(); } pw.println(); Loading @@ -2276,17 +2352,17 @@ public final class JobSchedulerService extends com.android.server.SystemService } else { pw.println(job.toShortString()); pw.print(" Running for: "); TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw); TimeUtils.formatDuration(nowElapsed - jsc.getExecutionStartTimeElapsed(), pw); pw.print(", timeout at: "); TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw); TimeUtils.formatDuration(jsc.getTimeoutElapsed() - nowElapsed, pw); pw.println(); job.dump(pw, " ", false, now); job.dump(pw, " ", false, nowElapsed); int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked()); if (priority != JobInfo.PRIORITY_DEFAULT) { pw.print(" Evaluated priority: "); pw.println(priority); } pw.print(" Active at "); TimeUtils.formatDuration(job.madeActive - now, pw); TimeUtils.formatDuration(job.madeActive - nowUptime, pw); pw.print(", pending for "); TimeUtils.formatDuration(job.madeActive - job.madePending, pw); pw.println(); Loading services/core/java/com/android/server/job/JobSchedulerShellCommand.java +97 −34 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ public class JobSchedulerShellCommand extends ShellCommand { return getStorageSeq(pw); case "get-storage-not-low": return getStorageNotLow(pw); case "get-job-state": return getJobState(pw); default: return handleDefaultCommands(cmd); } Loading @@ -83,6 +85,43 @@ public class JobSchedulerShellCommand extends ShellCommand { } } private boolean printError(int errCode, String pkgName, int userId, int jobId) { PrintWriter pw; switch (errCode) { case CMD_ERR_NO_PACKAGE: pw = getErrPrintWriter(); pw.print("Package not found: "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); return true; case CMD_ERR_NO_JOB: pw = getErrPrintWriter(); pw.print("Could not find job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); return true; case CMD_ERR_CONSTRAINTS: pw = getErrPrintWriter(); pw.print("Job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.print(userId); pw.println(" has functional constraints but --force not specified"); return true; default: return false; } } private int runJob(PrintWriter pw) throws Exception { checkPermission("force scheduled jobs"); Loading Loading @@ -114,42 +153,17 @@ public class JobSchedulerShellCommand extends ShellCommand { final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force); switch (ret) { case CMD_ERR_NO_PACKAGE: pw.print("Package not found: "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); break; case CMD_ERR_NO_JOB: pw.print("Could not find job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); break; case CMD_ERR_CONSTRAINTS: pw.print("Job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.print(userId); pw.println(" has functional constraints but --force not specified"); break; if (printError(ret, pkgName, userId, jobId)) { return ret; } default: // success! pw.print("Running job"); if (force) { pw.print(" [FORCED]"); } pw.println(); break; } return ret; } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -244,6 +258,43 @@ public class JobSchedulerShellCommand extends ShellCommand { return 0; } private int getJobState(PrintWriter pw) throws Exception { checkPermission("force timeout jobs"); int userId = UserHandle.USER_SYSTEM; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-u": case "--user": userId = UserHandle.parseUserArg(getNextArgRequired()); break; default: pw.println("Error: unknown option '" + opt + "'"); return -1; } } if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final String pkgName = getNextArgRequired(); final String jobIdStr = getNextArgRequired(); final int jobId = Integer.parseInt(jobIdStr); final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.getJobState(pw, pkgName, userId, jobId); printError(ret, pkgName, userId, jobId); return ret; } finally { Binder.restoreCallingIdentity(ident); } } @Override public void onHelp() { final PrintWriter pw = getOutPrintWriter(); Loading Loading @@ -277,6 +328,18 @@ public class JobSchedulerShellCommand extends ShellCommand { pw.println(" Return the last storage update sequence number that was received."); pw.println(" get-storage-not-low"); pw.println(" Return whether storage is currently considered to not be low."); pw.println(" get-job-state [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the current state of a job, may be any combination of:"); pw.println(" pending: currently on the pending list, waiting to be active"); pw.println(" active: job is actively running"); pw.println(" user-stopped: job can't run because its user is stopped"); pw.println(" backing-up: job can't run because app is currently backing up its data"); pw.println(" no-component: job can't run because its component is not available"); pw.println(" ready: job is ready to run (all constraints satisfied or bypassed)"); pw.println(" waiting: if nothing else above is printed, job not ready to run"); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(); } Loading services/core/java/com/android/server/job/controllers/BatteryController.java +50 −49 Original line number Diff line number Diff line Loading @@ -93,14 +93,13 @@ public class BatteryController extends StateController { } } private void maybeReportNewChargingState() { private void maybeReportNewChargingStateLocked() { final boolean stablePower = mChargeTracker.isOnStablePower(); final boolean batteryNotLow = mChargeTracker.isBatteryNotLow(); if (DEBUG) { Slog.d(TAG, "maybeReportNewChargingState: " + stablePower); Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower); } boolean reportChange = false; synchronized (mLock) { for (int i = mTrackedTasks.size() - 1; i >= 0; i--) { final JobStatus ts = mTrackedTasks.valueAt(i); boolean previous = ts.setChargingConstraintSatisfied(stablePower); Loading @@ -112,15 +111,13 @@ public class BatteryController extends StateController { reportChange = true; } } } // Let the scheduler know that state has changed. This may or may not result in an // execution. if (reportChange) { mStateChangedListener.onControllerStateChanged(); } // Also tell the scheduler that any ready jobs should be flushed. if (stablePower || batteryNotLow) { // If one of our conditions has been satisfied, always schedule any newly ready jobs. mStateChangedListener.onRunJobNow(null); } else if (reportChange) { // Otherwise, just let the job scheduler know the state has changed and take care of it // as it thinks is best. mStateChangedListener.onControllerStateChanged(); } } Loading Loading @@ -201,6 +198,7 @@ public class BatteryController extends StateController { @VisibleForTesting public void onReceiveInternal(Intent intent) { synchronized (mLock) { final String action = intent.getAction(); if (Intent.ACTION_BATTERY_LOW.equals(action)) { if (DEBUG) { Loading @@ -211,28 +209,31 @@ public class BatteryController extends StateController { // there's no work to cancel. We track this variable for the case where it is // charging, but hasn't been for long enough to be healthy. mBatteryHealthy = false; maybeReportNewChargingStateLocked(); } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) { if (DEBUG) { Slog.d(TAG, "Battery life healthy enough to do work. @ " + SystemClock.elapsedRealtime()); } mBatteryHealthy = true; maybeReportNewChargingState(); maybeReportNewChargingStateLocked(); } else if (BatteryManager.ACTION_CHARGING.equals(action)) { if (DEBUG) { Slog.d(TAG, "Received charging intent, fired @ " + SystemClock.elapsedRealtime()); } mCharging = true; maybeReportNewChargingState(); maybeReportNewChargingStateLocked(); } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) { if (DEBUG) { Slog.d(TAG, "Disconnected from power."); } mCharging = false; maybeReportNewChargingState(); maybeReportNewChargingStateLocked(); } mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq); } mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq); } } Loading Loading
services/core/java/com/android/server/job/JobSchedulerService.java +99 −23 Original line number Diff line number Diff line Loading @@ -1270,6 +1270,17 @@ public final class JobSchedulerService extends com.android.server.SystemService } } private void stopNonReadyActiveJobsLocked() { for (int i=0; i<mActiveServices.size(); i++) { JobServiceContext serviceContext = mActiveServices.get(i); final JobStatus running = serviceContext.getRunningJobLocked(); if (running != null && !running.isReady()) { serviceContext.cancelExecutingJobLocked( JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } } } /** * Run through list of jobs and execute all possible - at least one is expired so we do * as many as we can. Loading @@ -1280,6 +1291,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } noteJobsNonpending(mPendingJobs); mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mReadyQueueFunctor); mReadyQueueFunctor.postProcess(); Loading @@ -1306,9 +1318,6 @@ public final class JobSchedulerService extends com.android.server.SystemService newReadyJobs = new ArrayList<JobStatus>(); } newReadyJobs.add(job); } else if (areJobConstraintsNotSatisfiedLocked(job)) { stopJobOnServiceContextLocked(job, JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } } Loading Loading @@ -1387,9 +1396,6 @@ public final class JobSchedulerService extends com.android.server.SystemService runnableJobs = new ArrayList<>(); } runnableJobs.add(job); } else if (areJobConstraintsNotSatisfiedLocked(job)) { stopJobOnServiceContextLocked(job, JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED); } } Loading Loading @@ -1439,6 +1445,7 @@ public final class JobSchedulerService extends com.android.server.SystemService noteJobsNonpending(mPendingJobs); mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mMaybeQueueFunctor); mMaybeQueueFunctor.postProcess(); } Loading Loading @@ -1515,15 +1522,6 @@ public final class JobSchedulerService extends com.android.server.SystemService return componentPresent; } /** * Criteria for cancelling an active job: * - It's not ready * - It's running on a JSC. */ private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) { return !job.isReady() && isCurrentlyActiveLocked(job); } /** * Reconcile jobs in the pending queue against available execution contexts. * A controller can force a job into the pending queue even if it's already running, but Loading Loading @@ -2088,6 +2086,83 @@ public final class JobSchedulerService extends com.android.server.SystemService } } int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) { try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM); if (uid < 0) { pw.print("unknown("); pw.print(pkgName); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE; } synchronized (mLock) { final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId); if (DEBUG) Slog.d(TAG, "get-job-state " + uid + "/" + jobId + ": " + js); if (js == null) { pw.print("unknown("); UserHandle.formatUid(pw, uid); pw.print("/jid"); pw.print(jobId); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } boolean printed = false; if (mPendingJobs.contains(js)) { pw.print("pending"); printed = true; } if (isCurrentlyActiveLocked(js)) { if (printed) { pw.print(" "); } printed = true; pw.println("active"); } if (!ArrayUtils.contains(mStartedUsers, js.getUserId())) { if (printed) { pw.print(" "); } printed = true; pw.println("user-stopped"); } if (mBackingUpUids.indexOfKey(js.getSourceUid()) >= 0) { if (printed) { pw.print(" "); } printed = true; pw.println("backing-up"); } boolean componentPresent = false; try { componentPresent = (AppGlobals.getPackageManager().getServiceInfo( js.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, js.getUserId()) != null); } catch (RemoteException e) { } if (!componentPresent) { if (printed) { pw.print(" "); } printed = true; pw.println("no-component"); } if (js.isReady()) { if (printed) { pw.print(" "); } printed = true; pw.println("ready"); } if (!printed) { pw.print("waiting"); } pw.println(); } } catch (RemoteException e) { // can't happen } return 0; } private String printContextIdToJobMap(JobStatus[] map, String initial) { StringBuilder s = new StringBuilder(initial + ": "); for (int i=0; i<map.length; i++) { Loading Loading @@ -2152,7 +2227,8 @@ public final class JobSchedulerService extends com.android.server.SystemService } final int filterUidFinal = UserHandle.getAppId(filterUid); final long now = SystemClock.elapsedRealtime(); final long nowElapsed = SystemClock.elapsedRealtime(); final long nowUptime = SystemClock.uptimeMillis(); synchronized (mLock) { mConstants.dump(pw); pw.println(); Loading Loading @@ -2184,7 +2260,7 @@ public final class JobSchedulerService extends com.android.server.SystemService continue; } job.dump(pw, " ", true, now); job.dump(pw, " ", true, nowElapsed); pw.print(" Ready: "); pw.print(isReadyToBeExecutedLocked(job)); pw.print(" (job="); Loading Loading @@ -2254,14 +2330,14 @@ public final class JobSchedulerService extends com.android.server.SystemService JobStatus job = mPendingJobs.get(i); pw.print(" Pending #"); pw.print(i); pw.print(": "); pw.println(job.toShortString()); job.dump(pw, " ", false, now); job.dump(pw, " ", false, nowElapsed); int priority = evaluateJobPriorityLocked(job); if (priority != JobInfo.PRIORITY_DEFAULT) { pw.print(" Evaluated priority: "); pw.println(priority); } pw.print(" Tag: "); pw.println(job.getTag()); pw.print(" Enq: "); TimeUtils.formatDuration(job.madePending - now, pw); TimeUtils.formatDuration(job.madePending - nowUptime, pw); pw.println(); } pw.println(); Loading @@ -2276,17 +2352,17 @@ public final class JobSchedulerService extends com.android.server.SystemService } else { pw.println(job.toShortString()); pw.print(" Running for: "); TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw); TimeUtils.formatDuration(nowElapsed - jsc.getExecutionStartTimeElapsed(), pw); pw.print(", timeout at: "); TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw); TimeUtils.formatDuration(jsc.getTimeoutElapsed() - nowElapsed, pw); pw.println(); job.dump(pw, " ", false, now); job.dump(pw, " ", false, nowElapsed); int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked()); if (priority != JobInfo.PRIORITY_DEFAULT) { pw.print(" Evaluated priority: "); pw.println(priority); } pw.print(" Active at "); TimeUtils.formatDuration(job.madeActive - now, pw); TimeUtils.formatDuration(job.madeActive - nowUptime, pw); pw.print(", pending for "); TimeUtils.formatDuration(job.madeActive - job.madePending, pw); pw.println(); Loading
services/core/java/com/android/server/job/JobSchedulerShellCommand.java +97 −34 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ public class JobSchedulerShellCommand extends ShellCommand { return getStorageSeq(pw); case "get-storage-not-low": return getStorageNotLow(pw); case "get-job-state": return getJobState(pw); default: return handleDefaultCommands(cmd); } Loading @@ -83,6 +85,43 @@ public class JobSchedulerShellCommand extends ShellCommand { } } private boolean printError(int errCode, String pkgName, int userId, int jobId) { PrintWriter pw; switch (errCode) { case CMD_ERR_NO_PACKAGE: pw = getErrPrintWriter(); pw.print("Package not found: "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); return true; case CMD_ERR_NO_JOB: pw = getErrPrintWriter(); pw.print("Could not find job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); return true; case CMD_ERR_CONSTRAINTS: pw = getErrPrintWriter(); pw.print("Job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.print(userId); pw.println(" has functional constraints but --force not specified"); return true; default: return false; } } private int runJob(PrintWriter pw) throws Exception { checkPermission("force scheduled jobs"); Loading Loading @@ -114,42 +153,17 @@ public class JobSchedulerShellCommand extends ShellCommand { final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force); switch (ret) { case CMD_ERR_NO_PACKAGE: pw.print("Package not found: "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); break; case CMD_ERR_NO_JOB: pw.print("Could not find job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.println(userId); break; case CMD_ERR_CONSTRAINTS: pw.print("Job "); pw.print(jobId); pw.print(" in package "); pw.print(pkgName); pw.print(" / user "); pw.print(userId); pw.println(" has functional constraints but --force not specified"); break; if (printError(ret, pkgName, userId, jobId)) { return ret; } default: // success! pw.print("Running job"); if (force) { pw.print(" [FORCED]"); } pw.println(); break; } return ret; } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -244,6 +258,43 @@ public class JobSchedulerShellCommand extends ShellCommand { return 0; } private int getJobState(PrintWriter pw) throws Exception { checkPermission("force timeout jobs"); int userId = UserHandle.USER_SYSTEM; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-u": case "--user": userId = UserHandle.parseUserArg(getNextArgRequired()); break; default: pw.println("Error: unknown option '" + opt + "'"); return -1; } } if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final String pkgName = getNextArgRequired(); final String jobIdStr = getNextArgRequired(); final int jobId = Integer.parseInt(jobIdStr); final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.getJobState(pw, pkgName, userId, jobId); printError(ret, pkgName, userId, jobId); return ret; } finally { Binder.restoreCallingIdentity(ident); } } @Override public void onHelp() { final PrintWriter pw = getOutPrintWriter(); Loading Loading @@ -277,6 +328,18 @@ public class JobSchedulerShellCommand extends ShellCommand { pw.println(" Return the last storage update sequence number that was received."); pw.println(" get-storage-not-low"); pw.println(" Return whether storage is currently considered to not be low."); pw.println(" get-job-state [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the current state of a job, may be any combination of:"); pw.println(" pending: currently on the pending list, waiting to be active"); pw.println(" active: job is actively running"); pw.println(" user-stopped: job can't run because its user is stopped"); pw.println(" backing-up: job can't run because app is currently backing up its data"); pw.println(" no-component: job can't run because its component is not available"); pw.println(" ready: job is ready to run (all constraints satisfied or bypassed)"); pw.println(" waiting: if nothing else above is printed, job not ready to run"); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(); } Loading
services/core/java/com/android/server/job/controllers/BatteryController.java +50 −49 Original line number Diff line number Diff line Loading @@ -93,14 +93,13 @@ public class BatteryController extends StateController { } } private void maybeReportNewChargingState() { private void maybeReportNewChargingStateLocked() { final boolean stablePower = mChargeTracker.isOnStablePower(); final boolean batteryNotLow = mChargeTracker.isBatteryNotLow(); if (DEBUG) { Slog.d(TAG, "maybeReportNewChargingState: " + stablePower); Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower); } boolean reportChange = false; synchronized (mLock) { for (int i = mTrackedTasks.size() - 1; i >= 0; i--) { final JobStatus ts = mTrackedTasks.valueAt(i); boolean previous = ts.setChargingConstraintSatisfied(stablePower); Loading @@ -112,15 +111,13 @@ public class BatteryController extends StateController { reportChange = true; } } } // Let the scheduler know that state has changed. This may or may not result in an // execution. if (reportChange) { mStateChangedListener.onControllerStateChanged(); } // Also tell the scheduler that any ready jobs should be flushed. if (stablePower || batteryNotLow) { // If one of our conditions has been satisfied, always schedule any newly ready jobs. mStateChangedListener.onRunJobNow(null); } else if (reportChange) { // Otherwise, just let the job scheduler know the state has changed and take care of it // as it thinks is best. mStateChangedListener.onControllerStateChanged(); } } Loading Loading @@ -201,6 +198,7 @@ public class BatteryController extends StateController { @VisibleForTesting public void onReceiveInternal(Intent intent) { synchronized (mLock) { final String action = intent.getAction(); if (Intent.ACTION_BATTERY_LOW.equals(action)) { if (DEBUG) { Loading @@ -211,28 +209,31 @@ public class BatteryController extends StateController { // there's no work to cancel. We track this variable for the case where it is // charging, but hasn't been for long enough to be healthy. mBatteryHealthy = false; maybeReportNewChargingStateLocked(); } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) { if (DEBUG) { Slog.d(TAG, "Battery life healthy enough to do work. @ " + SystemClock.elapsedRealtime()); } mBatteryHealthy = true; maybeReportNewChargingState(); maybeReportNewChargingStateLocked(); } else if (BatteryManager.ACTION_CHARGING.equals(action)) { if (DEBUG) { Slog.d(TAG, "Received charging intent, fired @ " + SystemClock.elapsedRealtime()); } mCharging = true; maybeReportNewChargingState(); maybeReportNewChargingStateLocked(); } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) { if (DEBUG) { Slog.d(TAG, "Disconnected from power."); } mCharging = false; maybeReportNewChargingState(); maybeReportNewChargingStateLocked(); } mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq); } mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq); } } Loading