Loading services/core/java/com/android/server/DeviceIdleController.java +19 −22 Original line number Diff line number Diff line Loading @@ -198,7 +198,6 @@ public class DeviceIdleController extends SystemService private int mActiveIdleOpCount; private IBinder mDownloadServiceActive; private boolean mSyncActive; private boolean mJobsActive; private boolean mAlarmsActive; private boolean mReportedMaintenanceActivity; Loading Loading @@ -944,7 +943,7 @@ public class DeviceIdleController extends SystemService null, mIdleStartedDoneReceiver, null, 0, null, null); } // Always start with one active op for the message being sent here. // Now we we done! // Now we are done! decActiveIdleOps(); EventLogTags.writeDeviceIdleOffComplete(); } break; Loading Loading @@ -1145,10 +1144,6 @@ public class DeviceIdleController extends SystemService setNetworkPolicyTempWhitelistCallbackInternal(callback); } public void setSyncActive(boolean active) { DeviceIdleController.this.setSyncActive(active); } public void setJobsActive(boolean active) { DeviceIdleController.this.setJobsActive(active); } Loading @@ -1157,6 +1152,16 @@ public class DeviceIdleController extends SystemService public void setAlarmsActive(boolean active) { DeviceIdleController.this.setAlarmsActive(active); } /** * Returns the array of app ids whitelisted by user. Take care not to * modify this, as it is a reference to the original copy. But the reference * can change when the list changes, so it needs to be re-acquired when * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent. */ public int[] getPowerSaveWhitelistUserAppIds() { return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds(); } } public DeviceIdleController(Context context) { Loading @@ -1165,6 +1170,12 @@ public class DeviceIdleController extends SystemService mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); } int[] getPowerSaveWhitelistUserAppIds() { synchronized (this) { return mPowerSaveWhitelistUserAppIdArray; } } private static File getSystemDir() { return new File(Environment.getDataDirectory(), "system"); } Loading Loading @@ -1288,7 +1299,6 @@ public class DeviceIdleController extends SystemService mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray); mDisplayManager.registerDisplayListener(mDisplayListener, null); updateDisplayLocked(); } Loading Loading @@ -1877,16 +1887,6 @@ public class DeviceIdleController extends SystemService } } void setSyncActive(boolean active) { synchronized (this) { mSyncActive = active; reportMaintenanceActivityIfNeededLocked(); if (!active) { exitMaintenanceEarlyIfNeededLocked(); } } } void setJobsActive(boolean active) { synchronized (this) { mJobsActive = active; Loading Loading @@ -1920,7 +1920,7 @@ public class DeviceIdleController extends SystemService } void reportMaintenanceActivityIfNeededLocked() { boolean active = mJobsActive | mSyncActive | (mDownloadServiceActive != null); boolean active = mJobsActive | (mDownloadServiceActive != null); if (active == mReportedMaintenanceActivity) { return; } Loading @@ -1933,7 +1933,7 @@ public class DeviceIdleController extends SystemService void exitMaintenanceEarlyIfNeededLocked() { if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE) { if (mActiveIdleOpCount <= 0 && mDownloadServiceActive == null && !mSyncActive && !mJobsActive && !mAlarmsActive) { && !mJobsActive && !mAlarmsActive) { final long now = SystemClock.elapsedRealtime(); if (DEBUG) { StringBuilder sb = new StringBuilder(); Loading Loading @@ -2741,9 +2741,6 @@ public class DeviceIdleController extends SystemService TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw); pw.println(); } if (mSyncActive) { pw.print(" mSyncActive="); pw.println(mSyncActive); } if (mJobsActive) { pw.print(" mJobsActive="); pw.println(mJobsActive); } Loading services/core/java/com/android/server/job/JobSchedulerService.java +21 −52 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ import com.android.server.job.controllers.AppIdleController; import com.android.server.job.controllers.BatteryController; import com.android.server.job.controllers.ConnectivityController; import com.android.server.job.controllers.ContentObserverController; import com.android.server.job.controllers.DeviceIdleJobsController; import com.android.server.job.controllers.IdleController; import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.StateController; Loading Loading @@ -163,11 +164,6 @@ public final class JobSchedulerService extends com.android.server.SystemService */ boolean mReadyToRock; /** * True when in device idle mode, so we don't want to schedule any jobs. */ boolean mDeviceIdleMode; /** * What we last reported to DeviceIdleController about whether we are active. */ Loading Loading @@ -228,12 +224,6 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "Removing jobs for user: " + userId); } cancelJobsForUser(userId); } else if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction()) || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) { updateIdleMode(mPowerManager != null ? (mPowerManager.isDeviceIdleMode() || mPowerManager.isLightDeviceIdleMode()) : false); } } }; Loading Loading @@ -418,24 +408,10 @@ public final class JobSchedulerService extends com.android.server.SystemService } } void updateIdleMode(boolean enabled) { boolean changed = false; boolean rocking; synchronized (mLock) { if (mDeviceIdleMode != enabled) { changed = true; } rocking = mReadyToRock; } if (changed) { if (rocking) { for (int i=0; i<mControllers.size(); i++) { mControllers.get(i).deviceIdleModeChanged(enabled); } } @Override public void onDeviceIdleStateChanged(boolean deviceIdle) { synchronized (mLock) { mDeviceIdleMode = enabled; if (enabled) { if (deviceIdle) { // When becoming idle, make sure no jobs are actively running. for (int i=0; i<mActiveServices.size(); i++) { JobServiceContext jsc = mActiveServices.get(i); Loading @@ -446,7 +422,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } } else { // When coming out of idle, allow thing to start back up. if (rocking) { if (mReadyToRock) { if (mLocalDeviceIdleController != null) { if (!mReportedActive) { mReportedActive = true; Loading @@ -458,7 +434,6 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } } void reportActive() { // active is true if pending queue contains jobs OR some job is running. Loading Loading @@ -500,6 +475,7 @@ public final class JobSchedulerService extends com.android.server.SystemService mControllers.add(BatteryController.get(this)); mControllers.add(AppIdleController.get(this)); mControllers.add(ContentObserverController.get(this)); mControllers.add(DeviceIdleJobsController.get(this)); mHandler = new JobHandler(context.getMainLooper()); mJobSchedulerStub = new JobSchedulerStub(); Loading @@ -521,8 +497,6 @@ public final class JobSchedulerService extends com.android.server.SystemService getContext().registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, filter, null, null); final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED); userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); userFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED); getContext().registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, userFilter, null, null); mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE); Loading Loading @@ -553,7 +527,6 @@ public final class JobSchedulerService extends com.android.server.SystemService public void process(JobStatus job) { for (int controller = 0; controller < mControllers.size(); controller++) { final StateController sc = mControllers.get(controller); sc.deviceIdleModeChanged(mDeviceIdleMode); sc.maybeStartTrackingJobLocked(job, null); } } Loading Loading @@ -1015,10 +988,6 @@ public final class JobSchedulerService extends com.android.server.SystemService */ private void maybeRunPendingJobsH() { synchronized (mLock) { if (mDeviceIdleMode) { // If device is idle, we will not schedule jobs to run. return; } if (DEBUG) { Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs."); } Loading Loading @@ -1188,6 +1157,7 @@ public final class JobSchedulerService extends com.android.server.SystemService * Returns a list of all pending jobs. A running job is not considered pending. Periodic * jobs are always considered pending. */ @Override public List<JobInfo> getSystemScheduledPendingJobs() { synchronized (mLock) { final List<JobInfo> pendingJobs = new ArrayList<JobInfo>(); Loading Loading @@ -1509,7 +1479,6 @@ public final class JobSchedulerService extends com.android.server.SystemService } pw.println(); pw.print("mReadyToRock="); pw.println(mReadyToRock); pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode); pw.print("mReportedActive="); pw.println(mReportedActive); pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs); } Loading services/core/java/com/android/server/job/StateChangedListener.java +2 −0 Original line number Diff line number Diff line Loading @@ -37,4 +37,6 @@ public interface StateChangedListener { * indicates to the scheduler that any ready jobs should be flushed.</strong> */ public void onRunJobNow(JobStatus jobStatus); public void onDeviceIdleStateChanged(boolean deviceIdle); } services/core/java/com/android/server/job/controllers/AppIdleController.java +1 −1 Original line number Diff line number Diff line Loading @@ -87,7 +87,7 @@ public class AppIdleController extends StateController { pw.println("Parole On: " + mAppIdleParoleOn); for (JobStatus task : mTrackedTasks) { pw.print(task.getSourcePackageName()); pw.print(":idle=" pw.print(":runnable=" + ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0)); pw.print(", "); } Loading services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java 0 → 100644 +184 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.job.controllers; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.PowerManager; import android.os.UserHandle; import android.util.Slog; import com.android.internal.util.ArrayUtils; import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateChangedListener; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; /** * When device is dozing, set constraint for all jobs, except whitelisted apps, as not satisfied. * When device is not dozing, set constraint for all jobs as satisfied. */ public class DeviceIdleJobsController extends StateController { private static final String LOG_TAG = "DeviceIdleJobsController"; private static final boolean LOG_DEBUG = false; // Singleton factory private static Object sCreationLock = new Object(); final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>(); private static DeviceIdleJobsController sController; private final PowerManager mPowerManager; private final DeviceIdleController.LocalService mLocalDeviceIdleController; /** * True when in device idle mode, so we don't want to schedule any jobs. */ private boolean mDeviceIdleMode; private int[] mDeviceIdleWhitelistAppIds; /** * Returns a singleton for the DeviceIdleJobsController */ public static DeviceIdleJobsController get(JobSchedulerService service) { synchronized (sCreationLock) { if (sController == null) { sController = new DeviceIdleJobsController(service, service.getContext(), service.getLock()); } return sController; } } // onReceive private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(action) || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) { updateIdleMode(mPowerManager != null ? (mPowerManager.isDeviceIdleMode() || mPowerManager.isLightDeviceIdleMode()) : false); } else if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(action)) { updateWhitelist(); } } }; private DeviceIdleJobsController(StateChangedListener stateChangedListener, Context context, Object lock) { super(stateChangedListener, context, lock); // Register for device idle mode changes mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class); final IntentFilter filter = new IntentFilter(); filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); mContext.registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, filter, null, null); } void updateIdleMode(boolean enabled) { boolean changed = false; // Need the whitelist to be ready when going into idle if (mDeviceIdleWhitelistAppIds == null) { updateWhitelist(); } synchronized (mLock) { if (mDeviceIdleMode != enabled) { changed = true; } mDeviceIdleMode = enabled; if (LOG_DEBUG) Slog.d(LOG_TAG, "mDeviceIdleMode=" + mDeviceIdleMode); for (JobStatus task : mTrackedTasks) { updateTaskStateLocked(task); } } // Inform the job scheduler service about idle mode changes if (changed) { mStateChangedListener.onDeviceIdleStateChanged(enabled); } } /** * Fetches the latest whitelist from the device idle controller. */ void updateWhitelist() { synchronized (mLock) { if (mLocalDeviceIdleController != null) { mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds(); if (LOG_DEBUG) { Slog.d(LOG_TAG, "Got whitelist " + Arrays.toString(mDeviceIdleWhitelistAppIds)); } } } } /** * Checks if the given job's scheduling app id exists in the device idle user whitelist. */ boolean isWhitelistedLocked(JobStatus job) { if (mDeviceIdleWhitelistAppIds != null && ArrayUtils.contains(mDeviceIdleWhitelistAppIds, UserHandle.getAppId(job.getSourceUid()))) { return true; } return false; } private void updateTaskStateLocked(JobStatus task) { boolean enableTask = !mDeviceIdleMode || isWhitelistedLocked(task); task.setDeviceNotDozingConstraintSatisfied(enableTask); } @Override public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { synchronized (mLock) { mTrackedTasks.add(jobStatus); updateTaskStateLocked(jobStatus); } } @Override public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { mTrackedTasks.remove(jobStatus); } @Override public void dumpControllerStateLocked(PrintWriter pw) { pw.println("DeviceIdleJobsController"); for (JobStatus task : mTrackedTasks) { pw.print(task.getSourcePackageName()); pw.print(":runnable=" + ((task.satisfiedConstraints & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0)); pw.print(", "); } pw.println(); } } No newline at end of file Loading
services/core/java/com/android/server/DeviceIdleController.java +19 −22 Original line number Diff line number Diff line Loading @@ -198,7 +198,6 @@ public class DeviceIdleController extends SystemService private int mActiveIdleOpCount; private IBinder mDownloadServiceActive; private boolean mSyncActive; private boolean mJobsActive; private boolean mAlarmsActive; private boolean mReportedMaintenanceActivity; Loading Loading @@ -944,7 +943,7 @@ public class DeviceIdleController extends SystemService null, mIdleStartedDoneReceiver, null, 0, null, null); } // Always start with one active op for the message being sent here. // Now we we done! // Now we are done! decActiveIdleOps(); EventLogTags.writeDeviceIdleOffComplete(); } break; Loading Loading @@ -1145,10 +1144,6 @@ public class DeviceIdleController extends SystemService setNetworkPolicyTempWhitelistCallbackInternal(callback); } public void setSyncActive(boolean active) { DeviceIdleController.this.setSyncActive(active); } public void setJobsActive(boolean active) { DeviceIdleController.this.setJobsActive(active); } Loading @@ -1157,6 +1152,16 @@ public class DeviceIdleController extends SystemService public void setAlarmsActive(boolean active) { DeviceIdleController.this.setAlarmsActive(active); } /** * Returns the array of app ids whitelisted by user. Take care not to * modify this, as it is a reference to the original copy. But the reference * can change when the list changes, so it needs to be re-acquired when * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent. */ public int[] getPowerSaveWhitelistUserAppIds() { return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds(); } } public DeviceIdleController(Context context) { Loading @@ -1165,6 +1170,12 @@ public class DeviceIdleController extends SystemService mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); } int[] getPowerSaveWhitelistUserAppIds() { synchronized (this) { return mPowerSaveWhitelistUserAppIdArray; } } private static File getSystemDir() { return new File(Environment.getDataDirectory(), "system"); } Loading Loading @@ -1288,7 +1299,6 @@ public class DeviceIdleController extends SystemService mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray); mDisplayManager.registerDisplayListener(mDisplayListener, null); updateDisplayLocked(); } Loading Loading @@ -1877,16 +1887,6 @@ public class DeviceIdleController extends SystemService } } void setSyncActive(boolean active) { synchronized (this) { mSyncActive = active; reportMaintenanceActivityIfNeededLocked(); if (!active) { exitMaintenanceEarlyIfNeededLocked(); } } } void setJobsActive(boolean active) { synchronized (this) { mJobsActive = active; Loading Loading @@ -1920,7 +1920,7 @@ public class DeviceIdleController extends SystemService } void reportMaintenanceActivityIfNeededLocked() { boolean active = mJobsActive | mSyncActive | (mDownloadServiceActive != null); boolean active = mJobsActive | (mDownloadServiceActive != null); if (active == mReportedMaintenanceActivity) { return; } Loading @@ -1933,7 +1933,7 @@ public class DeviceIdleController extends SystemService void exitMaintenanceEarlyIfNeededLocked() { if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE) { if (mActiveIdleOpCount <= 0 && mDownloadServiceActive == null && !mSyncActive && !mJobsActive && !mAlarmsActive) { && !mJobsActive && !mAlarmsActive) { final long now = SystemClock.elapsedRealtime(); if (DEBUG) { StringBuilder sb = new StringBuilder(); Loading Loading @@ -2741,9 +2741,6 @@ public class DeviceIdleController extends SystemService TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw); pw.println(); } if (mSyncActive) { pw.print(" mSyncActive="); pw.println(mSyncActive); } if (mJobsActive) { pw.print(" mJobsActive="); pw.println(mJobsActive); } Loading
services/core/java/com/android/server/job/JobSchedulerService.java +21 −52 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ import com.android.server.job.controllers.AppIdleController; import com.android.server.job.controllers.BatteryController; import com.android.server.job.controllers.ConnectivityController; import com.android.server.job.controllers.ContentObserverController; import com.android.server.job.controllers.DeviceIdleJobsController; import com.android.server.job.controllers.IdleController; import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.StateController; Loading Loading @@ -163,11 +164,6 @@ public final class JobSchedulerService extends com.android.server.SystemService */ boolean mReadyToRock; /** * True when in device idle mode, so we don't want to schedule any jobs. */ boolean mDeviceIdleMode; /** * What we last reported to DeviceIdleController about whether we are active. */ Loading Loading @@ -228,12 +224,6 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "Removing jobs for user: " + userId); } cancelJobsForUser(userId); } else if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction()) || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) { updateIdleMode(mPowerManager != null ? (mPowerManager.isDeviceIdleMode() || mPowerManager.isLightDeviceIdleMode()) : false); } } }; Loading Loading @@ -418,24 +408,10 @@ public final class JobSchedulerService extends com.android.server.SystemService } } void updateIdleMode(boolean enabled) { boolean changed = false; boolean rocking; synchronized (mLock) { if (mDeviceIdleMode != enabled) { changed = true; } rocking = mReadyToRock; } if (changed) { if (rocking) { for (int i=0; i<mControllers.size(); i++) { mControllers.get(i).deviceIdleModeChanged(enabled); } } @Override public void onDeviceIdleStateChanged(boolean deviceIdle) { synchronized (mLock) { mDeviceIdleMode = enabled; if (enabled) { if (deviceIdle) { // When becoming idle, make sure no jobs are actively running. for (int i=0; i<mActiveServices.size(); i++) { JobServiceContext jsc = mActiveServices.get(i); Loading @@ -446,7 +422,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } } else { // When coming out of idle, allow thing to start back up. if (rocking) { if (mReadyToRock) { if (mLocalDeviceIdleController != null) { if (!mReportedActive) { mReportedActive = true; Loading @@ -458,7 +434,6 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } } void reportActive() { // active is true if pending queue contains jobs OR some job is running. Loading Loading @@ -500,6 +475,7 @@ public final class JobSchedulerService extends com.android.server.SystemService mControllers.add(BatteryController.get(this)); mControllers.add(AppIdleController.get(this)); mControllers.add(ContentObserverController.get(this)); mControllers.add(DeviceIdleJobsController.get(this)); mHandler = new JobHandler(context.getMainLooper()); mJobSchedulerStub = new JobSchedulerStub(); Loading @@ -521,8 +497,6 @@ public final class JobSchedulerService extends com.android.server.SystemService getContext().registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, filter, null, null); final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED); userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); userFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED); getContext().registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, userFilter, null, null); mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE); Loading Loading @@ -553,7 +527,6 @@ public final class JobSchedulerService extends com.android.server.SystemService public void process(JobStatus job) { for (int controller = 0; controller < mControllers.size(); controller++) { final StateController sc = mControllers.get(controller); sc.deviceIdleModeChanged(mDeviceIdleMode); sc.maybeStartTrackingJobLocked(job, null); } } Loading Loading @@ -1015,10 +988,6 @@ public final class JobSchedulerService extends com.android.server.SystemService */ private void maybeRunPendingJobsH() { synchronized (mLock) { if (mDeviceIdleMode) { // If device is idle, we will not schedule jobs to run. return; } if (DEBUG) { Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs."); } Loading Loading @@ -1188,6 +1157,7 @@ public final class JobSchedulerService extends com.android.server.SystemService * Returns a list of all pending jobs. A running job is not considered pending. Periodic * jobs are always considered pending. */ @Override public List<JobInfo> getSystemScheduledPendingJobs() { synchronized (mLock) { final List<JobInfo> pendingJobs = new ArrayList<JobInfo>(); Loading Loading @@ -1509,7 +1479,6 @@ public final class JobSchedulerService extends com.android.server.SystemService } pw.println(); pw.print("mReadyToRock="); pw.println(mReadyToRock); pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode); pw.print("mReportedActive="); pw.println(mReportedActive); pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs); } Loading
services/core/java/com/android/server/job/StateChangedListener.java +2 −0 Original line number Diff line number Diff line Loading @@ -37,4 +37,6 @@ public interface StateChangedListener { * indicates to the scheduler that any ready jobs should be flushed.</strong> */ public void onRunJobNow(JobStatus jobStatus); public void onDeviceIdleStateChanged(boolean deviceIdle); }
services/core/java/com/android/server/job/controllers/AppIdleController.java +1 −1 Original line number Diff line number Diff line Loading @@ -87,7 +87,7 @@ public class AppIdleController extends StateController { pw.println("Parole On: " + mAppIdleParoleOn); for (JobStatus task : mTrackedTasks) { pw.print(task.getSourcePackageName()); pw.print(":idle=" pw.print(":runnable=" + ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0)); pw.print(", "); } Loading
services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java 0 → 100644 +184 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.job.controllers; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.PowerManager; import android.os.UserHandle; import android.util.Slog; import com.android.internal.util.ArrayUtils; import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateChangedListener; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; /** * When device is dozing, set constraint for all jobs, except whitelisted apps, as not satisfied. * When device is not dozing, set constraint for all jobs as satisfied. */ public class DeviceIdleJobsController extends StateController { private static final String LOG_TAG = "DeviceIdleJobsController"; private static final boolean LOG_DEBUG = false; // Singleton factory private static Object sCreationLock = new Object(); final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>(); private static DeviceIdleJobsController sController; private final PowerManager mPowerManager; private final DeviceIdleController.LocalService mLocalDeviceIdleController; /** * True when in device idle mode, so we don't want to schedule any jobs. */ private boolean mDeviceIdleMode; private int[] mDeviceIdleWhitelistAppIds; /** * Returns a singleton for the DeviceIdleJobsController */ public static DeviceIdleJobsController get(JobSchedulerService service) { synchronized (sCreationLock) { if (sController == null) { sController = new DeviceIdleJobsController(service, service.getContext(), service.getLock()); } return sController; } } // onReceive private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(action) || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) { updateIdleMode(mPowerManager != null ? (mPowerManager.isDeviceIdleMode() || mPowerManager.isLightDeviceIdleMode()) : false); } else if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(action)) { updateWhitelist(); } } }; private DeviceIdleJobsController(StateChangedListener stateChangedListener, Context context, Object lock) { super(stateChangedListener, context, lock); // Register for device idle mode changes mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class); final IntentFilter filter = new IntentFilter(); filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); mContext.registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, filter, null, null); } void updateIdleMode(boolean enabled) { boolean changed = false; // Need the whitelist to be ready when going into idle if (mDeviceIdleWhitelistAppIds == null) { updateWhitelist(); } synchronized (mLock) { if (mDeviceIdleMode != enabled) { changed = true; } mDeviceIdleMode = enabled; if (LOG_DEBUG) Slog.d(LOG_TAG, "mDeviceIdleMode=" + mDeviceIdleMode); for (JobStatus task : mTrackedTasks) { updateTaskStateLocked(task); } } // Inform the job scheduler service about idle mode changes if (changed) { mStateChangedListener.onDeviceIdleStateChanged(enabled); } } /** * Fetches the latest whitelist from the device idle controller. */ void updateWhitelist() { synchronized (mLock) { if (mLocalDeviceIdleController != null) { mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds(); if (LOG_DEBUG) { Slog.d(LOG_TAG, "Got whitelist " + Arrays.toString(mDeviceIdleWhitelistAppIds)); } } } } /** * Checks if the given job's scheduling app id exists in the device idle user whitelist. */ boolean isWhitelistedLocked(JobStatus job) { if (mDeviceIdleWhitelistAppIds != null && ArrayUtils.contains(mDeviceIdleWhitelistAppIds, UserHandle.getAppId(job.getSourceUid()))) { return true; } return false; } private void updateTaskStateLocked(JobStatus task) { boolean enableTask = !mDeviceIdleMode || isWhitelistedLocked(task); task.setDeviceNotDozingConstraintSatisfied(enableTask); } @Override public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { synchronized (mLock) { mTrackedTasks.add(jobStatus); updateTaskStateLocked(jobStatus); } } @Override public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { mTrackedTasks.remove(jobStatus); } @Override public void dumpControllerStateLocked(PrintWriter pw) { pw.println("DeviceIdleJobsController"); for (JobStatus task : mTrackedTasks) { pw.print(task.getSourcePackageName()); pw.print(":runnable=" + ((task.satisfiedConstraints & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0)); pw.print(", "); } pw.println(); } } No newline at end of file