1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2011 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17d6db8eab6df048b9065834113a6d46a885af01d3Owen Linpackage com.android.gallery3d.gadget;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
192b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.graphics.Bitmap;
202b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.net.Uri;
212b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.os.Binder;
222b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils;
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.ContentListener;
25ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiwareimport com.android.gallery3d.data.DataManager;
26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem;
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaObject;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet;
29ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiwareimport com.android.gallery3d.data.Path;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList;
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Arrays;
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class MediaSetSource implements WidgetSource, ContentListener {
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "MediaSetSource";
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
37ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private DataManager mDataManager;
38ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private Path mAlbumPath;
39ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
40ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private WidgetSource mSource;
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
42ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private MediaSet mRootSet;
43ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private ContentListener mListener;
44ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
45ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public MediaSetSource(DataManager manager, String albumPath) {
46ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        MediaSet mediaSet = (MediaSet) manager.getMediaObject(albumPath);
47ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        if (mediaSet != null) {
48ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mSource = new CheckedMediaSetSource(mediaSet);
49ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            return;
50ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
52ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        // Initialize source to an empty source until the album path can be resolved
53ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mDataManager = Utils.checkNotNull(manager);
54ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mAlbumPath = Path.fromString(albumPath);
55ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mSource = new EmptySource();
56ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        monitorRootPath();
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
60ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public int size() {
61ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        return mSource.size();
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
64ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    @Override
65ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public Bitmap getImage(int index) {
66ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        return mSource.getImage(index);
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
70ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public Uri getContentUri(int index) {
71ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        return mSource.getContentUri(index);
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
75ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public synchronized void setContentListener(ContentListener listener) {
76ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        if (mRootSet != null) {
77ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mListener = listener;
78ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        } else {
79ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mSource.setContentListener(listener);
80ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void reload() {
85ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mSource.reload();
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
89ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public void close() {
90ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mSource.close();
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
94ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    public void onContentDirty() {
95ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        resolveAlbumPath();
96ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    }
97ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
98ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private void monitorRootPath() {
99ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        String rootPath = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
100ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mRootSet = (MediaSet) mDataManager.getMediaObject(rootPath);
101ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        mRootSet.addContentListener(this);
102ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    }
103ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
104ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private synchronized void resolveAlbumPath() {
105ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        if (mDataManager == null) return;
106ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        MediaSet mediaSet = (MediaSet) mDataManager.getMediaObject(mAlbumPath);
107ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        if (mediaSet != null) {
108ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            // Clear the reference instead of removing the listener
109ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            // to get around a concurrent modification exception.
110ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mRootSet = null;
111ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
112ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mSource = new CheckedMediaSetSource(mediaSet);
113ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            if (mListener != null) {
114ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mListener.onContentDirty();
115ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mSource.setContentListener(mListener);
116ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mListener = null;
117ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            }
118ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mDataManager = null;
119ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mAlbumPath = null;
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
123ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private static class CheckedMediaSetSource implements WidgetSource, ContentListener {
124ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private static final int CACHE_SIZE = 32;
125ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
126ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @SuppressWarnings("unused")
127ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private static final String TAG = "CheckedMediaSetSource";
128ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
129ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private MediaSet mSource;
130ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private MediaItem mCache[] = new MediaItem[CACHE_SIZE];
131ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private int mCacheStart;
132ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private int mCacheEnd;
133ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
134ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
135ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private ContentListener mContentListener;
136ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
137ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public CheckedMediaSetSource(MediaSet source) {
138ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mSource = Utils.checkNotNull(source);
139ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mSource.addContentListener(this);
140ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
141ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
142ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
143ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void close() {
144ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mSource.removeContentListener(this);
145ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
146ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
147ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        private void ensureCacheRange(int index) {
148ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            if (index >= mCacheStart && index < mCacheEnd) return;
149ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
150ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            long token = Binder.clearCallingIdentity();
151ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            try {
152ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mCacheStart = index;
153ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                ArrayList<MediaItem> items = mSource.getMediaItem(mCacheStart, CACHE_SIZE);
154ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mCacheEnd = mCacheStart + items.size();
155ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                items.toArray(mCache);
156ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            } finally {
157ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                Binder.restoreCallingIdentity(token);
158ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            }
159ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
160ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
161ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
162ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public synchronized Uri getContentUri(int index) {
163ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            ensureCacheRange(index);
164ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            if (index < mCacheStart || index >= mCacheEnd) return null;
165ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            return mCache[index - mCacheStart].getContentUri();
166ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
167ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
168ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
169ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public synchronized Bitmap getImage(int index) {
170ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            ensureCacheRange(index);
171ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            if (index < mCacheStart || index >= mCacheEnd) return null;
172ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            return WidgetUtils.createWidgetBitmap(mCache[index - mCacheStart]);
173ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
174ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
175ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
176ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void reload() {
177ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            long version = mSource.reload();
178ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            if (mSourceVersion != version) {
179ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mSourceVersion = version;
180ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mCacheStart = 0;
181ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                mCacheEnd = 0;
182ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                Arrays.fill(mCache, null);
183ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            }
184ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
185ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
186ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
187ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void setContentListener(ContentListener listener) {
188ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            mContentListener = listener;
189ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
190ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
191ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
192ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public int size() {
193ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            long token = Binder.clearCallingIdentity();
194ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            try {
195ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                return mSource.getMediaItemCount();
196ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            } finally {
197ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware                Binder.restoreCallingIdentity(token);
198ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            }
199ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
200ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
201ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
202ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void onContentDirty() {
203ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            if (mContentListener != null) mContentListener.onContentDirty();
204ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
205ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    }
206ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
207ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware    private static class EmptySource implements WidgetSource {
208ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
209ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
210ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public int size() {
211ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            return 0;
212ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
213ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
214ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
215ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public Bitmap getImage(int index) {
216ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            throw new UnsupportedOperationException();
217ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
218ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
219ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
220ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public Uri getContentUri(int index) {
221ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware            throw new UnsupportedOperationException();
222ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        }
223ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
224ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
225ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void setContentListener(ContentListener listener) {}
226ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
227ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
228ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void reload() {}
229ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware
230ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        @Override
231ba0c994c63b5dd8b8c36efa6b7c0a7cb4537d0eeMangesh Ghiware        public void close() {}
232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
234