DelegateManager.java revision 4f291d33e14e62b3301acc056a82fe206c74835f
14f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet/*
24f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
34f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
44f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
54f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * you may not use this file except in compliance with the License.
64f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * You may obtain a copy of the License at
74f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
84f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
94f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
104f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
114f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
124f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * See the License for the specific language governing permissions and
144f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * limitations under the License.
154f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet */
164f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
174f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetpackage com.android.layoutlib.bridge;
184f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
194f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetimport android.util.SparseArray;
204f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
214f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet/**
224f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Manages native delegates.
234f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
244f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * This is used in conjunction with layoublib_create: certain Android java classes are mere
254f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * wrappers around a heavily native based implementation, and we need a way to run these classes
264f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * in our Eclipse rendering framework without bringing all the native code from the Android
274f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * platform.
284f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
294f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Thus we instruct layoutlib_create to modify the bytecode of these classes to replace their
304f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * native methods by "delegate calls".
314f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
324f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * For example, a native method android.graphics.Matrix.init(...) will actually become
334f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * a call to android.graphics.Matrix_Delegate.init(...).
344f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
354f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * The Android java classes that use native code uses an int (Java side) to reference native
364f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * objects. This int is generally directly the pointer to the C structure counterpart.
374f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Typically a creation method will return such an int, and then this int will be passed later
384f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * to a Java method to identify the C object to manipulate.
394f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
404f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Since we cannot use the Java object reference as the int directly, DelegateManager manages the
414f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * int -> Delegate class link.
424f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
434f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Native methods usually always have the int as parameters. The first thing the delegate method
444f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * will do is call {@link #getDelegate(int)} to get the Java object matching the int.
454f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
464f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * Typical native init methods are returning a new int back to the Java class, so
474f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * {@link #addDelegate(Object)} does the same.
484f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet *
494f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet * @param <T> the delegate class to manage
504f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet */
514f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohetpublic final class DelegateManager<T> {
524f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
534f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private final SparseArray<T> mDelegates = new SparseArray<T>();
544f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    private int mDelegateCounter = 0;
554f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
564f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
574f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Returns the delegate from the given native int.
584f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param native_object the native int.
594f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @return the delegate or null if not found.
604f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
614f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public T getDelegate(int native_object) {
624f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        synchronized (mDelegates) {
634f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return mDelegates.get(native_object);
644f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
654f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
664f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
674f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
684f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Adds a delegate to the manager and returns the native int used to identify it.
694f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param newDelegate the delegate to add
704f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @return a unique native int to identify the delegate
714f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
724f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public int addDelegate(T newDelegate) {
734f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        synchronized (mDelegates) {
744f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            int native_object = ++mDelegateCounter;
754f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mDelegates.put(native_object, newDelegate);
764f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            return native_object;
774f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
784f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
794f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet
804f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    /**
814f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * Removes the delegate matching the given native int.
824f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     * @param native_object the native int.
834f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet     */
844f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    public void removeDelegate(int native_object) {
854f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        synchronized (mDelegates) {
864f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet            mDelegates.remove(native_object);
874f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet        }
884f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet    }
894f291d33e14e62b3301acc056a82fe206c74835fXavier Ducrohet}
90