165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/* 265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project 365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License. 665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at 765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software 1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and 1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License. 1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterfw.core; 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Frame; 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameFormat; 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.SimpleFrameManager; 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.Map; 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.SortedMap; 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.TreeMap; 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/** 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class CachedFrameManager extends SimpleFrameManager { 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private SortedMap<Integer, Frame> mAvailableFrames; 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private int mStorageCapacity = 24 * 1024 * 1024; // Cap default storage to 24MB 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private int mStorageSize = 0; 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private int mTimeStamp = 0; 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public CachedFrameManager() { 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super(); 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mAvailableFrames = new TreeMap<Integer, Frame>(); 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public Frame newFrame(FrameFormat format) { 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Frame result = findAvailableFrame(format, Frame.NO_BINDING, 0); 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (result == null) { 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = super.newFrame(format); 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result.setTimestamp(Frame.TIMESTAMP_NOT_SET); 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public Frame newBoundFrame(FrameFormat format, int bindingType, long bindingId) { 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Frame result = findAvailableFrame(format, bindingType, bindingId); 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (result == null) { 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = super.newBoundFrame(format, bindingType, bindingId); 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result.setTimestamp(Frame.TIMESTAMP_NOT_SET); 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public Frame retainFrame(Frame frame) { 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return super.retainFrame(frame); 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public Frame releaseFrame(Frame frame) { 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (frame.isReusable()) { 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int refCount = frame.decRefCount(); 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (refCount == 0 && frame.hasNativeAllocation()) { 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!storeFrame(frame)) { 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn frame.releaseNativeAllocation(); 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return null; 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (refCount < 0) { 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Frame reference count dropped below 0!"); 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super.releaseFrame(frame); 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return frame; 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void clearCache() { 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (Frame frame : mAvailableFrames.values()) { 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn frame.releaseNativeAllocation(); 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mAvailableFrames.clear(); 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void tearDown() { 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clearCache(); 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private boolean storeFrame(Frame frame) { 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn synchronized(mAvailableFrames) { 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure this frame alone does not exceed capacity 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int frameSize = frame.getFormat().getSize(); 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (frameSize > mStorageCapacity) { 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Drop frames if adding this frame would exceed capacity 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int newStorageSize = mStorageSize + frameSize; 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn while (newStorageSize > mStorageCapacity) { 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn dropOldestFrame(); 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn newStorageSize = mStorageSize + frameSize; 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Store new frame 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn frame.onFrameStore(); 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mStorageSize = newStorageSize; 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mAvailableFrames.put(mTimeStamp, frame); 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ++mTimeStamp; 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void dropOldestFrame() { 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int oldest = mAvailableFrames.firstKey(); 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Frame frame = mAvailableFrames.get(oldest); 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mStorageSize -= frame.getFormat().getSize(); 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn frame.releaseNativeAllocation(); 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mAvailableFrames.remove(oldest); 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private Frame findAvailableFrame(FrameFormat format, int bindingType, long bindingId) { 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Look for a frame that is compatible with the requested format 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn synchronized(mAvailableFrames) { 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (Map.Entry<Integer, Frame> entry : mAvailableFrames.entrySet()) { 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Frame frame = entry.getValue(); 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check that format is compatible 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (frame.getFormat().isReplaceableBy(format)) { 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check that binding is compatible (if frame is bound) 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if ((bindingType == frame.getBindingType()) 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn && (bindingType == Frame.NO_BINDING || bindingId == frame.getBindingId())) { 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // We found one! Take it out of the set of available frames and attach the 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // requested format to it. 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super.retainFrame(frame); 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mAvailableFrames.remove(entry.getKey()); 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn frame.onFrameFetch(); 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn frame.reset(format); 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mStorageSize -= format.getSize(); 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return frame; 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return null; 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 156