1851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate/*
2851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * Copyright (C) 2014 The Android Open Source Project
3851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate *
4851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
5851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * you may not use this file except in compliance with the License.
6851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * You may obtain a copy of the License at
7851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate *
8851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
9851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate *
10851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * Unless required by applicable law or agreed to in writing, software
11851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
12851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * See the License for the specific language governing permissions and
14851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate * limitations under the License
15851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate */
16851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
177060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tatepackage com.android.server.job.controllers;
18851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
19effacfa75bd9c2ebc889a7bc4f002c07f82f4c31Matthew Williamsimport java.io.PrintWriter;
20851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
21851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.app.AlarmManager;
22851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.app.PendingIntent;
23851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.content.BroadcastReceiver;
24851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.content.Context;
25851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.content.Intent;
26851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.content.IntentFilter;
27851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.os.SystemClock;
28e9a988caca733d2f292991a52a0047685a69812fDianne Hackbornimport android.os.UserHandle;
29f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackbornimport android.util.ArraySet;
30851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tateimport android.util.Slog;
31851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
3227d92e4e397728d56f4f951dd4ce99668c7c447bChristopher Tateimport com.android.server.am.ActivityManagerService;
337060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tateimport com.android.server.job.JobSchedulerService;
347060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tateimport com.android.server.job.StateChangedListener;
35851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
366466c1cc5efc4ff05fabdd670cf78a6a7ca45afbDianne Hackbornpublic final class IdleController extends StateController {
37851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    private static final String TAG = "IdleController";
38851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
39ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen    // Policy: we decide that we're "idle" if the device has been unused /
40ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen    // screen off or dreaming for at least this long
41ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen    private long mInactivityIdleThreshold;
42ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen    private long mIdleWindowSlop;
43f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn    final ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
44851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    IdlenessTracker mIdleTracker;
45851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
46851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    // Singleton factory
47851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    private static Object sCreationLock = new Object();
48851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    private static volatile IdleController sController;
49851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
507060b04f6d92351b67222e636ab378a0273bf3e7Christopher Tate    public static IdleController get(JobSchedulerService service) {
51851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        synchronized (sCreationLock) {
52851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            if (sController == null) {
5333d31c5b70c7d056e799e34bb6eccbe6939714eaDianne Hackborn                sController = new IdleController(service, service.getContext(), service.getLock());
54851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            }
55851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            return sController;
56851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
57851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
58851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
5933d31c5b70c7d056e799e34bb6eccbe6939714eaDianne Hackborn    private IdleController(StateChangedListener stateChangedListener, Context context,
6033d31c5b70c7d056e799e34bb6eccbe6939714eaDianne Hackborn                Object lock) {
6133d31c5b70c7d056e799e34bb6eccbe6939714eaDianne Hackborn        super(stateChangedListener, context, lock);
62851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        initIdleStateTracking();
63851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
64851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
65851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    /**
66851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     * StateController interface
67851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     */
68851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    @Override
69b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
70851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        if (taskStatus.hasIdleConstraint()) {
71b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn            mTrackedTasks.add(taskStatus);
72f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn            taskStatus.setTrackingController(JobStatus.TRACKING_IDLE);
73b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn            taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle());
74851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
75851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
76851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
77851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    @Override
78f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
79f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn            boolean forUpdate) {
80f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn        if (taskStatus.clearTrackingController(JobStatus.TRACKING_IDLE)) {
81f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn            mTrackedTasks.remove(taskStatus);
82f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn        }
83851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
84851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
85851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    /**
86851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     * Interaction with the task manager service
87851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     */
88851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    void reportNewIdleState(boolean isIdle) {
8933d31c5b70c7d056e799e34bb6eccbe6939714eaDianne Hackborn        synchronized (mLock) {
90f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn            for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
91f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn                mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle);
92851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            }
93851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
949b9244b6941110ea2d940d9fc8eed0cdff96a016Matthew Williams        mStateChangedListener.onControllerStateChanged();
95851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
96851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
97851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    /**
98851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     * Idle state tracking, and messaging with the task manager when
99851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     * significant state changes occur
100851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate     */
101851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    private void initIdleStateTracking() {
102ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen        mInactivityIdleThreshold = mContext.getResources().getInteger(
103ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen                com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
104ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen        mIdleWindowSlop = mContext.getResources().getInteger(
105ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen                com.android.internal.R.integer.config_jobSchedulerIdleWindowSlop);
106851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        mIdleTracker = new IdlenessTracker();
107851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        mIdleTracker.startTracking();
108851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
109851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
1106466c1cc5efc4ff05fabdd670cf78a6a7ca45afbDianne Hackborn    final class IdlenessTracker extends BroadcastReceiver {
111851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        private AlarmManager mAlarm;
112851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        private PendingIntent mIdleTriggerIntent;
113851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        boolean mIdle;
114ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu        boolean mScreenOn;
115851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
116851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        public IdlenessTracker() {
117851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
118851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
11927d92e4e397728d56f4f951dd4ce99668c7c447bChristopher Tate            Intent intent = new Intent(ActivityManagerService.ACTION_TRIGGER_IDLE)
120be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams                    .setPackage("android")
121be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams                    .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
122851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            mIdleTriggerIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
123851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
124be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams            // At boot we presume that the user has just "interacted" with the
125be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams            // device in some meaningful way.
126851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            mIdle = false;
127ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu            mScreenOn = true;
128851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
129851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
130851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        public boolean isIdle() {
131851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            return mIdle;
132851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
133851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
134851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        public void startTracking() {
135851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            IntentFilter filter = new IntentFilter();
136851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
137851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            // Screen state
138851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            filter.addAction(Intent.ACTION_SCREEN_ON);
139851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            filter.addAction(Intent.ACTION_SCREEN_OFF);
140851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
141851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            // Dreaming state
142851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            filter.addAction(Intent.ACTION_DREAMING_STARTED);
143851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            filter.addAction(Intent.ACTION_DREAMING_STOPPED);
144851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
145b9583c9d93bd1d2c9d506dffae87a5ca2b7f7307Christopher Tate            // Debugging/instrumentation
14627d92e4e397728d56f4f951dd4ce99668c7c447bChristopher Tate            filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
147b9583c9d93bd1d2c9d506dffae87a5ca2b7f7307Christopher Tate
148851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            mContext.registerReceiver(this, filter);
149851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
150851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate
151851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        @Override
152851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        public void onReceive(Context context, Intent intent) {
153851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            final String action = intent.getAction();
154851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            if (action.equals(Intent.ACTION_SCREEN_ON)
155851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    || action.equals(Intent.ACTION_DREAMING_STOPPED)) {
156ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                if (DEBUG) {
157ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                    Slog.v(TAG,"exiting idle : " + action);
158ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                }
159ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                mScreenOn = true;
160ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                //cancel the alarm
161ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                mAlarm.cancel(mIdleTriggerIntent);
162851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                if (mIdle) {
163ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                // possible transition to not-idle
164851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    mIdle = false;
165851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    reportNewIdleState(mIdle);
166851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                }
167851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            } else if (action.equals(Intent.ACTION_SCREEN_OFF)
168851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    || action.equals(Intent.ACTION_DREAMING_STARTED)) {
169851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                // when the screen goes off or dreaming starts, we schedule the
170851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                // alarm that will tell us when we have decided the device is
171851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                // truly idle.
172be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams                final long nowElapsed = SystemClock.elapsedRealtime();
173ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen                final long when = nowElapsed + mInactivityIdleThreshold;
174851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                if (DEBUG) {
175be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams                    Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
176be0c4175398ff5d7e13209e833b3037cdd0207d7Matthew Williams                            + when);
177851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                }
178ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                mScreenOn = false;
179851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
180ca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7Yao Chen                        when, mIdleWindowSlop, mIdleTriggerIntent);
18127d92e4e397728d56f4f951dd4ce99668c7c447bChristopher Tate            } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
182ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                // idle time starts now. Do not set mIdle if screen is on.
183ccfe87356fb961a4e85e4fce7cc5e0fac410f131Kevin Zhu                if (!mIdle && !mScreenOn) {
184851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    if (DEBUG) {
185851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                        Slog.v(TAG, "Idle trigger fired @ " + SystemClock.elapsedRealtime());
186851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    }
187851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    mIdle = true;
188851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                    reportNewIdleState(mIdle);
1897234fc6fef781e33842bc598a6e9e04bbff4f898Christopher Tate                } else {
1907234fc6fef781e33842bc598a6e9e04bbff4f898Christopher Tate                    if (DEBUG) {
1917234fc6fef781e33842bc598a6e9e04bbff4f898Christopher Tate                        Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
1927234fc6fef781e33842bc598a6e9e04bbff4f898Christopher Tate                                + mIdle + " screen=" + mScreenOn);
1937234fc6fef781e33842bc598a6e9e04bbff4f898Christopher Tate                    }
194851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate                }
195851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate            }
196851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate        }
197851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate    }
198effacfa75bd9c2ebc889a7bc4f002c07f82f4c31Matthew Williams
199effacfa75bd9c2ebc889a7bc4f002c07f82f4c31Matthew Williams    @Override
200ef3aa6ee53c5e4f1c50dd5a9b5821c54e449d4b3Dianne Hackborn    public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
201b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn        pw.print("Idle: ");
2027234fc6fef781e33842bc598a6e9e04bbff4f898Christopher Tate        pw.println(mIdleTracker.isIdle());
203e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn        pw.print("Tracking ");
204e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn        pw.print(mTrackedTasks.size());
205e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn        pw.println(":");
206b0001f6fb1383d9824c2733896b0b348e7f77240Dianne Hackborn        for (int i = 0; i < mTrackedTasks.size(); i++) {
207f9bac16d61db0fceb15484587ecf876c2b802c37Dianne Hackborn            final JobStatus js = mTrackedTasks.valueAt(i);
208ef3aa6ee53c5e4f1c50dd5a9b5821c54e449d4b3Dianne Hackborn            if (!js.shouldDump(filterUid)) {
209ef3aa6ee53c5e4f1c50dd5a9b5821c54e449d4b3Dianne Hackborn                continue;
210ef3aa6ee53c5e4f1c50dd5a9b5821c54e449d4b3Dianne Hackborn            }
211e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn            pw.print("  #");
212e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn            js.printUniqueId(pw);
213e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn            pw.print(" from ");
214e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn            UserHandle.formatUid(pw, js.getSourceUid());
215e9a988caca733d2f292991a52a0047685a69812fDianne Hackborn            pw.println();
2165eeb59cceb1f95813c548c1c5937f161c1ed3571Christopher Tate        }
217effacfa75bd9c2ebc889a7bc4f002c07f82f4c31Matthew Williams    }
218851f3d5110c48bcdba4762739c4ad9b9b479d9afChristopher Tate}
219