1a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling/* 2a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Copyright (C) 2013 The Android Open Source Project 3a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 4a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License"); 5a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * you may not use this file except in compliance with the License. 6a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * You may obtain a copy of the License at 7a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 8a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * http://www.apache.org/licenses/LICENSE-2.0 9a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 10a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Unless required by applicable law or agreed to in writing, software 11a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS, 12a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * See the License for the specific language governing permissions and 14a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * limitations under the License. 15a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 16a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 17a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingpackage com.android.camera.app; 18a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 1910809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberlingimport android.app.ActivityManager; 20a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport android.content.ComponentCallbacks2; 21a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport android.content.Context; 22a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport android.content.res.Configuration; 23a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 24a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport com.android.camera.app.MediaSaver.QueueListener; 255596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 2623262280ef73104d909d23d0fa811c217a349497Sascha Haeberlingimport com.android.camera.util.GservicesHelper; 27a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 280aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayanimport java.util.HashMap; 29a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport java.util.LinkedList; 30a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 31a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling/** 32a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Default implementation of the {@link MemoryManager}. 33a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * <p> 34a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * TODO: Add GCam signals. 35a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 36a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingpublic class MemoryManagerImpl implements MemoryManager, QueueListener, ComponentCallbacks2 { 375596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("MemoryManagerImpl"); 38366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling /** 39366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling * Let's signal only 70% of max memory is allowed to be used by native code 40366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling * to allow a buffer for special captures. 41366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling */ 42366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling private static final float MAX_MEM_ALLOWED = 0.70f; 434417e2a9bc380e0386dccfcd73c4782ab9a9444eSascha Haeberling 44a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling private static final int[] sCriticalStates = new int[] { 45a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling ComponentCallbacks2.TRIM_MEMORY_COMPLETE, 46a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL 47a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling }; 48a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 49a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling private final LinkedList<MemoryListener> mListeners = new LinkedList<MemoryListener>(); 50a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 51a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling /** 5210809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling * The maximum amount of memory allowed to be allocated in native code (in 5310809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling * megabytes) 5410809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling */ 5577d24065a133adfb4f94db367aafea176aa56270Sascha Haeberling private final int mMaxAllowedNativeMemory; 5610809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling 5710809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling /** 580aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan * Used to query a breakdown of current memory consumption and memory 590aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan * thresholds. 600aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan */ 610aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan private final MemoryQuery mMemoryQuery; 620aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan 630aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan /** 64a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Use this to create a wired-up memory manager. 65a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 66a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * @param context this is used to register for system memory events. 67a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * @param mediaSaver this used to check if the saving queue is full. 68a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * @return A wired-up memory manager instance. 69a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 70a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public static MemoryManagerImpl create(Context context, MediaSaver mediaSaver) { 710aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan ActivityManager activityManager = 720aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 730aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan int maxAllowedNativeMemory = getMaxAllowedNativeMemory(context); 740aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan MemoryQuery mMemoryQuery = new MemoryQuery(activityManager); 750aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan MemoryManagerImpl memoryManager = new MemoryManagerImpl(maxAllowedNativeMemory, 760aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan mMemoryQuery); 77a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling context.registerComponentCallbacks(memoryManager); 78a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling mediaSaver.setQueueListener(memoryManager); 79a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling return memoryManager; 80a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 81a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 82a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling /** 83a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Use {@link #create(Context, MediaSaver)} to make sure it's wired up 84a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * correctly. 85a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 860aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan private MemoryManagerImpl(int maxAllowedNativeMemory, MemoryQuery memoryQuery) { 870aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan mMaxAllowedNativeMemory = maxAllowedNativeMemory; 880aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan mMemoryQuery = memoryQuery; 8977d24065a133adfb4f94db367aafea176aa56270Sascha Haeberling Log.d(TAG, "Max native memory: " + mMaxAllowedNativeMemory + " MB"); 900aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan 91a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 92a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 93a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 94a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void addListener(MemoryListener listener) { 95a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling synchronized (mListeners) { 96f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling if (!mListeners.contains(listener)) { 97f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling mListeners.add(listener); 98f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling } else { 99f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling Log.w(TAG, "Listener already added."); 100a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 101a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 102a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 103a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 104a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 105a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void removeListener(MemoryListener listener) { 106a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling synchronized (mListeners) { 107f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling if (mListeners.contains(listener)) { 108f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling mListeners.remove(listener); 109f66eb70a66bb194f4bef54fe74a04d6c9a3515deSascha Haeberling } else { 1104417e2a9bc380e0386dccfcd73c4782ab9a9444eSascha Haeberling Log.w(TAG, "Cannot remove listener that was never added."); 111a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 112a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 113a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 114a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 115a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 116a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void onConfigurationChanged(Configuration newConfig) { 117a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 118a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 119a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 120a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void onLowMemory() { 121a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling notifyLowMemory(); 122a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 123a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 124a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 125a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void onTrimMemory(int level) { 126a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling for (int i = 0; i < sCriticalStates.length; ++i) { 127a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling if (level == sCriticalStates[i]) { 128a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling notifyLowMemory(); 129a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling return; 130a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 131a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 132a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 133a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 134a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 135a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void onQueueStatus(boolean full) { 136a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling notifyCaptureStateUpdate(full ? STATE_LOW_MEMORY : STATE_OK); 137a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 138a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 13910809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling @Override 14077d24065a133adfb4f94db367aafea176aa56270Sascha Haeberling public int getMaxAllowedNativeMemoryAllocation() { 14177d24065a133adfb4f94db367aafea176aa56270Sascha Haeberling return mMaxAllowedNativeMemory; 14210809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling } 14310809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling 1440aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan @Override 1451fc61197e36b25c593e8b0e95a10a9167d7d621eSascha Häberling public HashMap queryMemory() { 1460aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan return mMemoryQuery.queryMemory(); 1470aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan } 1480aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan 14977d24065a133adfb4f94db367aafea176aa56270Sascha Haeberling /** Helper to determine max allowed native memory allocation (in megabytes). */ 15077d24065a133adfb4f94db367aafea176aa56270Sascha Haeberling private static int getMaxAllowedNativeMemory(Context context) { 15123262280ef73104d909d23d0fa811c217a349497Sascha Haeberling // First check whether we have a system override. 15223262280ef73104d909d23d0fa811c217a349497Sascha Haeberling int maxAllowedOverrideMb = GservicesHelper.getMaxAllowedNativeMemoryMb(context); 15323262280ef73104d909d23d0fa811c217a349497Sascha Haeberling if (maxAllowedOverrideMb > 0) { 15423262280ef73104d909d23d0fa811c217a349497Sascha Haeberling Log.d(TAG, "Max native memory overridden: " + maxAllowedOverrideMb); 15523262280ef73104d909d23d0fa811c217a349497Sascha Haeberling return maxAllowedOverrideMb; 15623262280ef73104d909d23d0fa811c217a349497Sascha Haeberling } 15723262280ef73104d909d23d0fa811c217a349497Sascha Haeberling 15810809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling ActivityManager activityManager = (ActivityManager) context 15910809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling .getSystemService(Context.ACTIVITY_SERVICE); 16010809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling 16110809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling // Use the max of the regular memory class and the large memory class. 16210809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling // This is defined as the maximum memory allowed to be used by the 16310809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling // Dalvik heap, but it's safe to assume the app can use the same amount 16410809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling // once more in native code. 165366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling return (int) (Math.max(activityManager.getMemoryClass(), 166366c13baa640bc597cac360c5a1ffad5a3618b11Sascha Haeberling activityManager.getLargeMemoryClass()) * MAX_MEM_ALLOWED); 16710809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling } 16810809bdc41ec2203e5f4f4aa3d1016c0e94b97dfSascha Haeberling 169a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling /** Notify our listener that memory is running low. */ 170a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling private void notifyLowMemory() { 171a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling synchronized (mListeners) { 172a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling for (MemoryListener listener : mListeners) { 173a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling listener.onLowMemory(); 174a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 175a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 176a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 177a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 178a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling private void notifyCaptureStateUpdate(int captureState) { 179a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling synchronized (mListeners) { 180a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling for (MemoryListener listener : mListeners) { 181a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling listener.onMemoryStateChanged(captureState); 182a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 183a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 184a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 185a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling} 186