1bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey/*
2bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * Copyright (C) 2016 The Android Open Source Project
3bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *
4bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * you may not use this file except in compliance with the License.
6bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * You may obtain a copy of the License at
7bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *
8bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *
10bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * See the License for the specific language governing permissions and
14bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * limitations under the License.
15bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey */
16bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
17bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeypackage com.android.internal.util;
18bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
19bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.annotation.Nullable;
20bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.content.Intent;
21bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.os.Bundle;
22bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.os.IProgressListener;
2384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkeyimport android.os.RemoteCallbackList;
24bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.os.RemoteException;
25bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.util.MathUtils;
26bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
2784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkeyimport com.android.internal.annotations.GuardedBy;
2884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey
29bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey/**
30bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * Tracks and reports progress of a single task to a {@link IProgressListener}.
31bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * The reported progress of a task ranges from 0-100, but the task can be
32bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * segmented into smaller pieces using {@link #startSegment(int)} and
33bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * {@link #endSegment(int[])}, and segments can be nested.
34bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * <p>
35bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * Here's an example in action; when finished the overall task progress will be
36bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * at 60.
37bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *
38bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * <pre>
39bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * prog.setProgress(20);
40bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * {
41bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *     final int restore = prog.startSegment(40);
42bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *     for (int i = 0; i < N; i++) {
43bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *         prog.setProgress(i, N);
44bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *         ...
45bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *     }
46bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *     prog.endSegment(restore);
47bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * }
48bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * </pre>
49bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey *
50bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey * @hide
51bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey */
52bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeypublic class ProgressReporter {
5384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private static final int STATE_INIT = 0;
5484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private static final int STATE_STARTED = 1;
5584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private static final int STATE_FINISHED = 2;
56bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
57bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    private final int mId;
58bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
5984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    @GuardedBy("this")
6084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private final RemoteCallbackList<IProgressListener> mListeners = new RemoteCallbackList<>();
61bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
6284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    @GuardedBy("this")
6384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private int mState = STATE_INIT;
6484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    @GuardedBy("this")
65bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    private int mProgress = 0;
6684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    @GuardedBy("this")
6784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private Bundle mExtras = new Bundle();
68bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
69bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
70bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Current segment range: first element is starting progress of this
71bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * segment, second element is length of segment.
72bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
7384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    @GuardedBy("this")
74bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    private int[] mSegmentRange = new int[] { 0, 100 };
75bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
76bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
77bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Create a new task with the given identifier whose progress will be
78bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * reported to the given listener.
79bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
8084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    public ProgressReporter(int id) {
81bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        mId = id;
8284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    }
8384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey
8484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    /**
8584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey     * Add given listener to watch for progress events. The current state will
8684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey     * be immediately dispatched to the given listener.
8784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey     */
8884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    public void addListener(@Nullable IProgressListener listener) {
8984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        if (listener == null) return;
9084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        synchronized (this) {
9184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mListeners.register(listener);
9284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            switch (mState) {
9384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                case STATE_INIT:
9484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    // Nothing has happened yet
9584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    break;
9684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                case STATE_STARTED:
9784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    try {
9884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                        listener.onStarted(mId, null);
9984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                        listener.onProgress(mId, mProgress, mExtras);
10084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    } catch (RemoteException ignored) {
10184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    }
10284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    break;
10384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                case STATE_FINISHED:
10484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    try {
10584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                        listener.onFinished(mId, null);
10684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    } catch (RemoteException ignored) {
10784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    }
10884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    break;
10984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            }
11084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        }
111bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
112bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
113bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
114bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Set the progress of the currently active segment.
115bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     *
116bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * @param progress Segment progress between 0-100.
117bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
118bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public void setProgress(int progress) {
119bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        setProgress(progress, 100, null);
120bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
121bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
122bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
123bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Set the progress of the currently active segment.
124bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     *
125bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * @param progress Segment progress between 0-100.
126bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
127bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public void setProgress(int progress, @Nullable CharSequence title) {
128bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        setProgress(progress, 100, title);
129bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
130bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
131bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
132bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Set the fractional progress of the currently active segment.
133bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
134bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public void setProgress(int n, int m) {
135bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        setProgress(n, m, null);
136bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
137bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
138bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
139bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Set the fractional progress of the currently active segment.
140bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
141bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public void setProgress(int n, int m, @Nullable CharSequence title) {
14284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        synchronized (this) {
14384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            if (mState != STATE_STARTED) {
14484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                throw new IllegalStateException("Must be started to change progress");
14584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            }
14684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mProgress = mSegmentRange[0]
14784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                    + MathUtils.constrain((n * mSegmentRange[1]) / m, 0, mSegmentRange[1]);
14884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            if (title != null) {
14984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                mExtras.putCharSequence(Intent.EXTRA_TITLE, title);
15084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            }
15184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            notifyProgress(mId, mProgress, mExtras);
152bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        }
153bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
154bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
155bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
156bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Start a new inner segment that will contribute the given range towards
157bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * the currently active segment. You must pass the returned value to
158bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * {@link #endSegment(int[])} when finished.
159bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
160bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public int[] startSegment(int size) {
16184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        synchronized (this) {
16284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            final int[] lastRange = mSegmentRange;
16384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mSegmentRange = new int[] { mProgress, (size * mSegmentRange[1] / 100) };
16484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            return lastRange;
16584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        }
166bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
167bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
168bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
169bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * End the current segment.
170bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
171bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public void endSegment(int[] lastRange) {
17284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        synchronized (this) {
17384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mProgress = mSegmentRange[0] + mSegmentRange[1];
17484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mSegmentRange = lastRange;
17584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        }
176bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
177bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
178bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    int getProgress() {
179bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        return mProgress;
180bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
181bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
182bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    int[] getSegmentRange() {
183bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        return mSegmentRange;
184bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
185bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
186bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    /**
18784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey     * Report this entire task as being started.
18884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey     */
18984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    public void start() {
19084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        synchronized (this) {
19184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mState = STATE_STARTED;
19284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            notifyStarted(mId, null);
19384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            notifyProgress(mId, mProgress, mExtras);
19484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        }
19584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    }
19684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey
19784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    /**
198bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     * Report this entire task as being finished.
199bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey     */
200bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    public void finish() {
20184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        synchronized (this) {
20284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mState = STATE_FINISHED;
20384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            notifyFinished(mId, null);
20484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            mListeners.kill();
20584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        }
20684a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    }
20784a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey
20884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private void notifyStarted(int id, Bundle extras) {
20984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        for (int i = mListeners.beginBroadcast() - 1; i >= 0; i--) {
21084a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            try {
21184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                mListeners.getBroadcastItem(i).onStarted(id, extras);
21284a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            } catch (RemoteException ignored) {
21384a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey            }
21484a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        }
21584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        mListeners.finishBroadcast();
216bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
217bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
218bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    private void notifyProgress(int id, int progress, Bundle extras) {
21984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        for (int i = mListeners.beginBroadcast() - 1; i >= 0; i--) {
220bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            try {
22184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                mListeners.getBroadcastItem(i).onProgress(id, progress, extras);
222bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            } catch (RemoteException ignored) {
223bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            }
224bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        }
22584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        mListeners.finishBroadcast();
226bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
227bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
22884a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey    private void notifyFinished(int id, Bundle extras) {
22984a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        for (int i = mListeners.beginBroadcast() - 1; i >= 0; i--) {
230bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            try {
23184a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey                mListeners.getBroadcastItem(i).onFinished(id, extras);
232bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            } catch (RemoteException ignored) {
233bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            }
234bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        }
23584a4c971c484f05f2a2494d6353f36f4d954a5e0Jeff Sharkey        mListeners.finishBroadcast();
236bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey    }
237bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey}
238