1ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin/* 2ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Copyright (C) 2014 The Android Open Source Project 3ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * 4ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * you may not use this file except in compliance with the License. 6ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * You may obtain a copy of the License at 7ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * 8ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * http://www.apache.org/licenses/LICENSE-2.0 9ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * 10ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * Unless required by applicable law or agreed to in writing, software 11ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * distributed under the License is distributed on an "AS IS" BASIS, 12ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * See the License for the specific language governing permissions and 14ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin * limitations under the License. 15ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin */ 16ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 173830d419691ef865f01b362fee9618bac2aa8888Sascha Haeberlingpackage com.android.camera.processing.imagebackend; 18ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 19ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport android.net.Uri; 20ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 21ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport com.android.camera.debug.Log; 2230ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Linimport com.android.camera.one.v2.camera2proxy.ImageProxy; 23ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 240f0329889f69182648fe8f535335e48978d63cc0I-Jong Linimport com.google.common.annotations.VisibleForTesting; 250f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin 26ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.util.ArrayList; 27ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.util.HashMap; 28ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linimport java.util.List; 29ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 300f0329889f69182648fe8f535335e48978d63cc0I-Jong Linimport javax.annotation.Nullable; 310f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin 32ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin/** 3330ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin * Implements the ability for the object to send events to multiple listeners in 3430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin * a thread-safe manner. Also, listeners can also filter messages based on the a 350f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * specific image result. 360f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * <p> 370f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * TODO: Replace this object with a more generic listener class. TODO: Replace 380f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * the image filter code with something more efficient. 39ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin */ 40ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Linpublic class ImageProcessorProxyListener implements ImageProcessorListener { 41ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 42ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin private final static Log.Tag TAG = new Log.Tag("IProxyListener"); 43ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 440f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin private final List<ImageProcessorListener> mRegisteredListeners; 45ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 460f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin private final HashMap<ImageProcessorListener, Long> mImageFilter; 47ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 4830ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin /** 490f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * Wrapper for the log to avoid direct references to Android Log objects 500f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * that will crash unit tests. Subclasses may override this method for 510f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * debugging. 520f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * 5330ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin * @param message 5430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin */ 5530ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin protected void logWrapper(String message) { 560f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin // Uncomment for more verbose messaging. 570f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin // Log.v(TAG, message); 5830ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin } 5930ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin 60ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin ImageProcessorProxyListener() { 61ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin mRegisteredListeners = new ArrayList<ImageProcessorListener>(); 62ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin mImageFilter = new HashMap<ImageProcessorListener, Long>(); 63ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 64ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 650f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin /** 660f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * Returns the size of the ImageFilter so that we ensure that there are no 670f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * reference leaks. 680f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * 690f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * @return the number of elements in the mapping between 700f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * ImageProcessorListener and their ids. 710f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin */ 720f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin @VisibleForTesting 730f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin public int getMapSize() { 740f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin synchronized (mRegisteredListeners) { 750f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin return mImageFilter.size(); 760f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin } 770f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin } 780f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin 790f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin /** 800f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * Returns the number of ImageProcessorListener held by the system so that 810f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * we ensure that there are no reference leaks. 820f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * 830f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * @return the number of registered ImageProcessorListener 840f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin */ 850f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin @VisibleForTesting 860f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin public int getNumRegisteredListeners() { 87ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin synchronized (mRegisteredListeners) { 880f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin return mRegisteredListeners.size(); 890f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin } 900f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin } 910f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin 920f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin /** 930f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * Register a listener filtered by a particular image object. If image is 940f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * null, then events from all image processing will be sent to the 950f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * registered listener. 960f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * 970f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * @param listener The listener to be registered. 980f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * @param image The specific image to filter the events to the listener. If 990f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * null, then the listener receives events from all images that 1000f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * are being processed. 1010f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin */ 1020f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin public void registerListener(ImageProcessorListener listener, 1030f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin @Nullable ImageProxy image) { 1040f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin synchronized (mRegisteredListeners) { 1050f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin logWrapper("There are " + mRegisteredListeners.size() 1060f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin + " listeners before addition"); 1070f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin if (!mRegisteredListeners.contains(listener)) { 1080f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin mRegisteredListeners.add(listener); 1090f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin logWrapper("Listener will be overwritten."); 1100f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin } 1110f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin 112ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin if (image == null) { 113ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin mImageFilter.put(listener, null); 114ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } else { 115ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin mImageFilter.put(listener, image.getTimestamp()); 116ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 1170f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin logWrapper("There are " + mRegisteredListeners.size() 1180f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin + " listeners after addition"); 119ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 120ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 1210f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin return; 122ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 123ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 124ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin private List<ImageProcessorListener> filteredListeners(long imageId) { 125ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin List<ImageProcessorListener> filteredList = new ArrayList<ImageProcessorListener>(); 126ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 127ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin for (ImageProcessorListener l : mRegisteredListeners) { 128ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin if (mImageFilter.get(l) == null || mImageFilter.get(l) == imageId) { 129ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin filteredList.add(l); 130ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 131ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 132ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 133ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin return filteredList; 134ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 135ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 136ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void unregisterListener(ImageProcessorListener listener) { 137ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin synchronized (mRegisteredListeners) { 138ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin if (mRegisteredListeners.contains(listener)) { 139ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin mRegisteredListeners.remove(listener); 140ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin mImageFilter.remove(listener); 1410f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin logWrapper("There are " + mRegisteredListeners.size() 1420f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin + " listeners after removal"); 143ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } else { 14430ef96534cc65c0ba4665f6da2fc36e879edf196I-Jong Lin logWrapper("Couldn't find listener. There are " + mRegisteredListeners.size() 145ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin + " listeners after removal"); 146ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 147ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 148ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 149ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 150ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void onStart(TaskImageContainer.TaskInfo job) { 15122f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde final List<ImageProcessorListener> listeners; 152ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin synchronized (mRegisteredListeners) { 15322f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde listeners = filteredListeners(job.contentId); 15422f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde } 15522f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde 15622f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde for (ImageProcessorListener l : listeners) { 15722f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde l.onStart(job); 158ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 159ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 160ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 161ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void onResultCompressed(TaskImageContainer.TaskInfo job, 162ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin TaskImageContainer.CompressedPayload payload) { 16322f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde final List<ImageProcessorListener> listeners; 164ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin synchronized (mRegisteredListeners) { 16522f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde listeners = filteredListeners(job.contentId); 16622f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde } 16722f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde 16822f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde for (ImageProcessorListener l : listeners) { 16922f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde l.onResultCompressed(job, payload); 170ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 171ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 172ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 173ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void onResultUncompressed(TaskImageContainer.TaskInfo job, 174ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin TaskImageContainer.UncompressedPayload payload) { 17522f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde final List<ImageProcessorListener> listeners; 176ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin synchronized (mRegisteredListeners) { 17722f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde listeners = filteredListeners(job.contentId); 17822f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde } 17922f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde 18022f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde for (ImageProcessorListener l : listeners) { 18122f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde l.onResultUncompressed(job, payload); 182ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 183ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 184ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 185ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin public void onResultUri(TaskImageContainer.TaskInfo job, Uri uri) { 18622f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde final List<ImageProcessorListener> listeners; 187ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin synchronized (mRegisteredListeners) { 18822f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde listeners = filteredListeners(job.contentId); 18922f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde } 19022f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde 19122f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde for (ImageProcessorListener l : listeners) { 19222f00c96114a150ed75f02810a3fff1fa6461564Paul Rohde l.onResultUri(job, uri); 193ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 194ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin } 195ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin 196ed68932f91b4b4ad6766e4e38732deb8be772426I-Jong Lin} 197