19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.layoutlib.bridge; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 2019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 2119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet 2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Capability; 23fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.ide.common.rendering.api.DrawableParams; 2419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog; 2519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 2619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 28c3f979f6fecb8b46e9315fddb2a1f344bf1f1447Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams; 29c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.impl.FontLoader; 30fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetimport com.android.layoutlib.bridge.impl.RenderDrawable; 3119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.layoutlib.bridge.impl.RenderSessionImpl; 32a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohetimport com.android.layoutlib.bridge.util.DynamicIdMap; 332d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport com.android.ninepatch.NinePatchChunk; 3435ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.tools.layoutlib.create.MethodAdapter; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.tools.layoutlib.create.OverrideMethod; 37b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 397f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.content.res.BridgeAssetManager; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 417f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.graphics.Typeface_Accessor; 425e7ed8da0d990cbc55071d16b5db270231ff0c89Xavier Ducrohetimport android.graphics.Typeface_Delegate; 439eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohetimport android.os.Looper; 447f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.os.Looper_Accessor; 452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.view.View; 462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.view.ViewGroup; 472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.view.ViewParent; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport java.io.File; 504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport java.lang.ref.SoftReference; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Field; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Modifier; 53755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohetimport java.util.Arrays; 54b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport java.util.EnumMap; 553c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohetimport java.util.EnumSet; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport java.util.concurrent.locks.ReentrantLock; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Main entry point of the LayoutLib Bridge. 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call 63ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet * {@link #createScene(SceneParams)} 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetpublic final class Bridge extends com.android.ide.common.rendering.api.Bridge { 6683189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class StaticMethodNotImplementedException extends RuntimeException { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long serialVersionUID = 1L; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public StaticMethodNotImplementedException(String msg) { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(msg); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Lock to ensure only one rendering/inflating happens at a time. 772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * This is due to some singleton in the Android framework. 782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet private final static ReentrantLock sLock = new ReentrantLock(); 802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 82a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet * Maps from id to resource type/name. This is for com.android.internal.R 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 84b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet private final static Map<Integer, Pair<ResourceType, String>> sRMap = 85b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet new HashMap<Integer, Pair<ResourceType, String>>(); 86b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8883189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet * Same as sRMap except for int[] instead of int resources. This is for android.R only. 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 90755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private final static Map<IntArray, String> sRArrayMap = new HashMap<IntArray, String>(); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9283189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet * Reverse map compared to sRMap, resource type -> (resource name -> id). 93a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet * This is for com.android.internal.R. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 95a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet private final static Map<ResourceType, Map<String, Integer>> sRevRMap = 96b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet new EnumMap<ResourceType, Map<String,Integer>>(ResourceType.class); 9783189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 98a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet // framework resources are defined as 0x01XX#### where XX is the resource type (layout, 99a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet // drawable, etc...). Using FF as the type allows for 255 resource types before we get a 100a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet // collision which should be fine. 101a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet private final static int DYNAMIC_ID_SEED_START = 0x01ff0000; 102a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet private final static DynamicIdMap sDynamicIds = new DynamicIdMap(DYNAMIC_ID_SEED_START); 103a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet 1044df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache = 1054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project new HashMap<Object, Map<String, SoftReference<Bitmap>>>(); 1062d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet private final static Map<Object, Map<String, SoftReference<NinePatchChunk>>> sProject9PatchCache = 1072d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet new HashMap<Object, Map<String, SoftReference<NinePatchChunk>>>(); 1084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project 1094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private final static Map<String, SoftReference<Bitmap>> sFrameworkBitmapCache = 1104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project new HashMap<String, SoftReference<Bitmap>>(); 1112d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet private final static Map<String, SoftReference<NinePatchChunk>> sFramework9PatchCache = 1122d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet new HashMap<String, SoftReference<NinePatchChunk>>(); 11383189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Map<String, Map<String, Integer>> sEnumValueMap; 1157d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private static Map<String, String> sPlatformProperties; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 118755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet * int[] wrapper to use as keys in maps. 119755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet */ 120755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private final static class IntArray { 121755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private int[] mArray; 122755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 123755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private IntArray() { 124755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet // do nothing 125755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet } 126755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 127755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private IntArray(int[] a) { 128755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet mArray = a; 129755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet } 130755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 131755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private void set(int[] a) { 132755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet mArray = a; 133755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet } 134755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 135755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet @Override 136755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet public int hashCode() { 137755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet return Arrays.hashCode(mArray); 138755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet } 139755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 140755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet @Override 141755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet public boolean equals(Object obj) { 142755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet if (this == obj) return true; 143755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet if (obj == null) return false; 144755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet if (getClass() != obj.getClass()) return false; 145755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 146755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet IntArray other = (IntArray) obj; 147755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet if (!Arrays.equals(mArray, other.mArray)) return false; 148755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet return true; 149755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet } 150755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet } 151755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 152b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet /** Instance of IntArrayWrapper to be reused in {@link #resolveResourceId(int[])}. */ 153755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet private final static IntArray sIntArrayWrapper = new IntArray(); 154755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet 155755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet /** 156168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet * A default log than prints to stdout/stderr. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 158168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet private final static LayoutLog sDefaultLog = new LayoutLog() { 159168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet @Override 16051a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet public void error(String tag, String message, Object data) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.err.println(message); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 164168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet @Override 16551a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet public void error(String tag, String message, Throwable throwable, Object data) { 166168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet System.err.println(message); 167168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet } 168168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet 169168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet @Override 17051a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet public void warning(String tag, String message, Object data) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println(message); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 175168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet /** 176168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet * Current log. 177168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet */ 178168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet private static LayoutLog sCurrentLog = sDefaultLog; 179168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet 180ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet private EnumSet<Capability> mCapabilities; 1813c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet 182c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet @Override 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getApiLevel() { 18419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return com.android.ide.common.rendering.api.Bridge.API_CURRENT; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1873c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet @Override 188ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet public EnumSet<Capability> getCapabilities() { 1893c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet return mCapabilities; 1903c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet } 1913c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet 192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet @Override 1937d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public boolean init(Map<String,String> platformProperties, 1947d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet File fontLocation, 1957d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet Map<String, Map<String, Integer>> enumValueMap, 19629c288da5260ac221b941e69b960aa2127cbdef0Xavier Ducrohet LayoutLog log) { 1977d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet sPlatformProperties = platformProperties; 1985a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet sEnumValueMap = enumValueMap; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet // don't use EnumSet.allOf(), because the bridge doesn't come with its specific version 2013c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet // of layoutlib_api. It is provided by the client which could have a more recent version 2023c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet // with newer, unsupported capabilities. 2033c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet mCapabilities = EnumSet.of( 204ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet Capability.UNBOUND_RENDERING, 2054dd2299d5766bf14479578772a0946c5399a0158Xavier Ducrohet Capability.CUSTOM_BACKGROUND_COLOR, 206ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet Capability.RENDER, 207fb93ce9684120a36862b5b5e67b1865a652907e9Xavier Ducrohet Capability.LAYOUT_ONLY, 208ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet Capability.EMBEDDED_LAYOUT, 209ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet Capability.VIEW_MANIPULATION, 210479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Capability.PLAY_ANIMATION, 2112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Capability.ANIMATED_VIEW_MANIPULATION, 21205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet Capability.ADAPTER_BINDING, 213891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet Capability.EXTENDED_VIEWINFO, 214891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet Capability.FIXED_SCALABLE_NINE_PATCH); 2153c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet 2163c78f2de353df3e287444dd9f9fbab3bd4456217Xavier Ducrohet 2175a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet BridgeAssetManager.initSystem(); 218c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // on static (native) methods which prints the signature on the console and 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // throws an exception. 22283189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet // This is useful when testing the rendering in ADT to identify static native 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // methods that are ignored -- layoutlib_create makes them returns 0/false/null 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // which is generally OK yet might be a problem, so this is how you'd find out. 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Currently layoutlib_create only overrides static native method. 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Static non-natives are not overridden and thus do not get here. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String debug = System.getenv("DEBUG_LAYOUT"); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (debug != null && !debug.equals("0") && !debug.equals("false")) { 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OverrideMethod.setDefaultListener(new MethodAdapter() { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onInvokeV(String signature, boolean isNative, Object caller) { 234168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet sDefaultLog.error(null, "Missing Stub: " + signature + 23551a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet (isNative ? " (native)" : ""), null /*data*/); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (debug.equalsIgnoreCase("throw")) { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Throwing this exception doesn't seem that useful. It breaks 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the layout editor yet doesn't display anything meaningful to the 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // user. Having the error in the console is just as useful. We'll 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // throw it only if the environment variable is "throw" or "THROW". 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new StaticMethodNotImplementedException(signature); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // load the fonts. 24919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet FontLoader fontLoader = FontLoader.create(fontLocation.getAbsolutePath()); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fontLoader != null) { 2515e7ed8da0d990cbc55071d16b5db270231ff0c89Xavier Ducrohet Typeface_Delegate.init(fontLoader); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 253c3f979f6fecb8b46e9315fddb2a1f344bf1f1447Xavier Ducrohet log.error(LayoutLog.TAG_BROKEN, 254c3f979f6fecb8b46e9315fddb2a1f344bf1f1447Xavier Ducrohet "Failed create FontLoader in layout lib.", null); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25783189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now parse com.android.internal.R (and only this one as android.R is a subset of 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the internal version), and put the content in the maps. 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class<?> r = com.android.internal.R.class; 26283189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Class<?> inner : r.getDeclaredClasses()) { 264b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet String resTypeName = inner.getSimpleName(); 265b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet ResourceType resType = ResourceType.getEnum(resTypeName); 266b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet if (resType != null) { 267b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet Map<String, Integer> fullMap = new HashMap<String, Integer>(); 268a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet sRevRMap.put(resType, fullMap); 269b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet 270b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet for (Field f : inner.getDeclaredFields()) { 271b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet // only process static final fields. Since the final attribute may have 272b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet // been altered by layoutlib_create, we only check static 273b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet int modifiers = f.getModifiers(); 274b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet if (Modifier.isStatic(modifiers)) { 275b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet Class<?> type = f.getType(); 276b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet if (type.isArray() && type.getComponentType() == int.class) { 277b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet // if the object is an int[] we put it in sRArrayMap using an IntArray 278b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet // wrapper that properly implements equals and hashcode for the array 279b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet // objects, as required by the map contract. 280b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet sRArrayMap.put(new IntArray((int[]) f.get(null)), f.getName()); 281b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet } else if (type == int.class) { 282b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet Integer value = (Integer) f.get(null); 283b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet sRMap.put(value, Pair.of(resType, f.getName())); 284b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet fullMap.put(f.getName(), value); 285b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet } else { 286b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet assert false; 287b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet } 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29229c288da5260ac221b941e69b960aa2127cbdef0Xavier Ducrohet } catch (Throwable throwable) { 29329c288da5260ac221b941e69b960aa2127cbdef0Xavier Ducrohet if (log != null) { 294918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet log.error(LayoutLog.TAG_BROKEN, 29529c288da5260ac221b941e69b960aa2127cbdef0Xavier Ducrohet "Failed to load com.android.internal.R from the layout library jar", 29629c288da5260ac221b941e69b960aa2127cbdef0Xavier Ducrohet throwable); 29729c288da5260ac221b941e69b960aa2127cbdef0Xavier Ducrohet } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3045a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet @Override 3055a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet public boolean dispose() { 3065a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet BridgeAssetManager.clearSystem(); 30746a329244db12b6f7afc3c9a6409d420241a1058Xavier Ducrohet 30846a329244db12b6f7afc3c9a6409d420241a1058Xavier Ducrohet // dispose of the default typeface. 3097f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet Typeface_Accessor.resetDefaults(); 31046a329244db12b6f7afc3c9a6409d420241a1058Xavier Ducrohet 3115a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet return true; 3125a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet } 3135a09488a158b669577cd8eb557ce4feb62929e75Xavier Ducrohet 314c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 315c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Starts a layout session by inflating and rendering it. The method returns a 316bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * {@link RenderSession} on which further actions can be taken. 317c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 3181126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet * @param params the {@link SessionParams} object with all the information necessary to create 319ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet * the scene. 320bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @return a new {@link RenderSession} object that contains the result of the layout. 321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @since 5 322d604ad1ad442790af53847d24060ecb097106d26Xavier Ducrohet */ 323c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet @Override 3241126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet public RenderSession createSession(SessionParams params) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 32619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result lastResult = SUCCESS.createResult(); 32719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet RenderSessionImpl scene = new RenderSessionImpl(params); 3282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 3299eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet prepareThread(); 3302eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet lastResult = scene.init(params.getTimeout()); 331c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (lastResult.isSuccess()) { 332c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet lastResult = scene.inflate(); 333c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (lastResult.isSuccess()) { 3345a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet lastResult = scene.render(true /*freshRender*/); 335c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 336d604ad1ad442790af53847d24060ecb097106d26Xavier Ducrohet } 3372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } finally { 3382eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet scene.release(); 3399eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet cleanupThread(); 340d604ad1ad442790af53847d24060ecb097106d26Xavier Ducrohet } 341d604ad1ad442790af53847d24060ecb097106d26Xavier Ducrohet 34219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return new BridgeRenderSession(scene, lastResult); 343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable t) { 344c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 345c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t2 = t; 346c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t2.getCause() != null) { 347c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t2 = t.getCause(); 348c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 34919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return new BridgeRenderSession(null, 350639e1bd35231a8f71e7acc95fedaf13ace9b65a9Xavier Ducrohet ERROR_UNKNOWN.createResult(t2.getMessage(), t)); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 354c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet @Override 355fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet public Result renderDrawable(DrawableParams params) { 356fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet try { 357fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet Result lastResult = SUCCESS.createResult(); 358fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet RenderDrawable action = new RenderDrawable(params); 359fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet try { 360fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet prepareThread(); 361fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet lastResult = action.init(params.getTimeout()); 362fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet if (lastResult.isSuccess()) { 363fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet lastResult = action.render(); 364fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 365fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } finally { 366fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet action.release(); 367fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet cleanupThread(); 368fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 369fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 370fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet return lastResult; 371fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } catch (Throwable t) { 372fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet // get the real cause of the exception. 373fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet Throwable t2 = t; 374fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet while (t2.getCause() != null) { 375fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet t2 = t.getCause(); 376fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 377fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet return ERROR_UNKNOWN.createResult(t2.getMessage(), t); 378fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 379fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet } 380fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet 381fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet @Override 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearCaches(Object projectKey) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (projectKey != null) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sProjectBitmapCache.remove(projectKey); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sProject9PatchCache.remove(projectKey); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38883189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 3892fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet @Override 3902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet public Result getViewParent(Object viewObject) { 3912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (viewObject instanceof View) { 3922fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet return Status.SUCCESS.createResult(((View)viewObject).getParent()); 3932fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 3942fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 3952fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet throw new IllegalArgumentException("viewObject is not a View"); 3962fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 3972fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 3982fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet @Override 3992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet public Result getViewIndex(Object viewObject) { 4002fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (viewObject instanceof View) { 4012fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet View view = (View) viewObject; 4022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ViewParent parentView = view.getParent(); 4032fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 4042fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (parentView instanceof ViewGroup) { 4052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Status.SUCCESS.createResult(((ViewGroup) parentView).indexOfChild(view)); 4062fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 4072fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 4082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet return Status.SUCCESS.createResult(); 4092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 4102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 4112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet throw new IllegalArgumentException("viewObject is not a View"); 4122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 4132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4152eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Returns the lock for the bridge 4162eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 4172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet public static ReentrantLock getLock() { 4182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return sLock; 4192eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 4202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 4212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 4229eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * Prepares the current thread for rendering. 4239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 4249eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * Note that while this can be called several time, the first call to {@link #cleanupThread()} 4259eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * will do the clean-up, and make the thread unable to do further scene actions. 4269eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet */ 4279eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet public static void prepareThread() { 4289eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // we need to make sure the Looper has been initialized for this thread. 4299eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // this is required for View that creates Handler objects. 4309eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (Looper.myLooper() == null) { 4319eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Looper.prepare(); 4329eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 4339eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 4349eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 4359eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet /** 4369eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * Cleans up thread-specific data. After this, the thread cannot be used for scene actions. 4379eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * <p> 4389eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * Note that it doesn't matter how many times {@link #prepareThread()} was called, a single 4399eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * call to this will prevent the thread from doing further scene actions 4409eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet */ 4419eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet public static void cleanupThread() { 4429eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // clean up the looper 4437f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet Looper_Accessor.cleanupThread(); 4449eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 4459eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 446168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet public static LayoutLog getLog() { 447168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return sCurrentLog; 448168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet } 449168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet 450168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet public static void setLog(LayoutLog log) { 451168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet // check only the thread currently owning the lock can do this. 452168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet if (sLock.isHeldByCurrentThread() == false) { 453168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); 454168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet } 455168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet 456168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet if (log != null) { 457168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet sCurrentLog = log; 458168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet } else { 459168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet sCurrentLog = sDefaultLog; 460168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet } 461168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet } 462168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet 4639eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet /** 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns details of a framework resource from its integer value. 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the integer value 466b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet * @return a Pair containing the resource type and name, or null if the id 467b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet * does not match any resource. 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 469b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet public static Pair<ResourceType, String> resolveResourceId(int value) { 470a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet Pair<ResourceType, String> pair = sRMap.get(value); 471a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet if (pair == null) { 472a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet pair = sDynamicIds.resolveId(value); 473a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet if (pair == null) { 4744d7f301f94b9d2dda0ef109e9991ad2d77442f75Xavier Ducrohet //System.out.println(String.format("Missing id: %1$08X (%1$d)", value)); 475a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet } 476a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet } 477a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet return pair; 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 47983189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name of a framework resource whose value is an int array. 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param array 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 484b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet public static String resolveResourceId(int[] array) { 485755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet sIntArrayWrapper.set(array); 486755b46d597b8e8a616d53e2a7dfea295dd78d713Xavier Ducrohet return sRArrayMap.get(sIntArrayWrapper); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 48883189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the integer id of a framework resource, from a given resource type and resource name. 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param type the type of the resource 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name the name of the resource. 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return an {@link Integer} containing the resource id, or null if no resource were found. 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 495b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet public static Integer getResourceId(ResourceType type, String name) { 496a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet Map<String, Integer> map = sRevRMap.get(type); 497a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet Integer value = null; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (map != null) { 499a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet value = map.get(name); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 50183189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 502a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet if (value == null) { 503a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet value = sDynamicIds.getId(type, name); 504a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet } 505a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet 506a421f6c0ba8c354e2a81830e6402654bbf732780Xavier Ducrohet return value; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 50883189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 510c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Returns the list of possible enums for a given attribute name. 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 512c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public static Map<String, Integer> getEnumValues(String attributeName) { 513c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (sEnumValueMap != null) { 514c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return sEnumValueMap.get(attributeName); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 51683189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 51983189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5217d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet * Returns the platform build properties. 5227d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet */ 5237d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public static Map<String, String> getPlatformProperties() { 5247d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return sPlatformProperties; 5257d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 5267d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 5277d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet /** 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the bitmap for a specific path, from a specific project cache, or from the 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * framework cache. 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the path of the bitmap 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param projectKey the key of the project, or null to query the framework cache. 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the cached Bitmap or null if not found. 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 534c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public static Bitmap getCachedBitmap(String value, Object projectKey) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (projectKey != null) { 5364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (map != null) { 5384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project SoftReference<Bitmap> ref = map.get(value); 5394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (ref != null) { 5404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return ref.get(); 5414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 5424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 5434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 5444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project SoftReference<Bitmap> ref = sFrameworkBitmapCache.get(value); 5454df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (ref != null) { 5464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return ref.get(); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project 5504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return null; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets a bitmap in a project cache or in the framework cache. 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the path of the bitmap 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bmp the Bitmap object 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param projectKey the key of the project, or null to put the bitmap in the framework cache. 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (projectKey != null) { 5614df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (map == null) { 5644df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project map = new HashMap<String, SoftReference<Bitmap>>(); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sProjectBitmapCache.put(projectKey, map); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 56783189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 5684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project map.put(value, new SoftReference<Bitmap>(bmp)); 5694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 5704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project sFrameworkBitmapCache.put(value, new SoftReference<Bitmap>(bmp)); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5752d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet * Returns the 9 patch chunk for a specific path, from a specific project cache, or from the 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * framework cache. 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the path of the 9 patch 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param projectKey the key of the project, or null to query the framework cache. 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the cached 9 patch or null if not found. 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5812d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet public static NinePatchChunk getCached9Patch(String value, Object projectKey) { 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (projectKey != null) { 5832d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); 58483189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (map != null) { 5862d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet SoftReference<NinePatchChunk> ref = map.get(value); 5874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (ref != null) { 5884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return ref.get(); 5894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 5904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 5914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 5922d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet SoftReference<NinePatchChunk> ref = sFramework9PatchCache.get(value); 5934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (ref != null) { 5944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return ref.get(); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 59783189c985a0e617ba7856343ea8b7080c37396a7Xavier Ducrohet 5984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return null; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 6012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 6022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Sets a 9 patch chunk in a project cache or in the framework cache. 6032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param value the path of the 9 patch 6042eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param ninePatch the 9 patch object 6052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param projectKey the key of the project, or null to put the bitmap in the framework cache. 6062eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 6072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet public static void setCached9Patch(String value, NinePatchChunk ninePatch, Object projectKey) { 6082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (projectKey != null) { 6092eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); 6102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 6112eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (map == null) { 6122eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet map = new HashMap<String, SoftReference<NinePatchChunk>>(); 6132eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet sProject9PatchCache.put(projectKey, map); 6142eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6152eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 6162eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet map.put(value, new SoftReference<NinePatchChunk>(ninePatch)); 6172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 6182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet sFramework9PatchCache.put(value, new SoftReference<NinePatchChunk>(ninePatch)); 6192eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 622