1c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal/* 2c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * Copyright (C) 2015 The Android Open Source Project 3c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * 4c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * Licensed under the Apache License, Version 2.0 (the "License"); 5c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * you may not use this file except in compliance with the License. 6c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * You may obtain a copy of the License at 7c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * 8c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * http://www.apache.org/licenses/LICENSE-2.0 9c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * 10c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * Unless required by applicable law or agreed to in writing, software 11c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * distributed under the License is distributed on an "AS IS" BASIS, 12c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * See the License for the specific language governing permissions and 14c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * limitations under the License. 15c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal */ 16c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.core.app; 18c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal 19c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysalimport android.os.Build; 20c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysalimport android.os.Bundle; 21c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysalimport android.os.IBinder; 229dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikasimport android.util.Log; 239dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikas 24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable; 26eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 27eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikasimport java.lang.reflect.InvocationTargetException; 28eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikasimport java.lang.reflect.Method; 29c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal 30c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal/** 31645e5c8aa6b31961c5f73f3d30bb5261d5e04aebKirill Grouchnikov * Helper for accessing features in {@link Bundle}. 32c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal */ 33c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class BundleCompat { 34c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes 35eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas static class BundleCompatBaseImpl { 36eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas private static final String TAG = "BundleCompatBaseImpl"; 37eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 38eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas private static Method sGetIBinderMethod; 39eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas private static boolean sGetIBinderMethodFetched; 40eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 41eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas private static Method sPutIBinderMethod; 42eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas private static boolean sPutIBinderMethodFetched; 43eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 440f4ca634bbc43ddff900c35f7d2a43b55d8c830dJake Wharton private BundleCompatBaseImpl() { 450f4ca634bbc43ddff900c35f7d2a43b55d8c830dJake Wharton } 460f4ca634bbc43ddff900c35f7d2a43b55d8c830dJake Wharton 47eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas public static IBinder getBinder(Bundle bundle, String key) { 48eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas if (!sGetIBinderMethodFetched) { 49eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas try { 50eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sGetIBinderMethod = Bundle.class.getMethod("getIBinder", String.class); 51eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sGetIBinderMethod.setAccessible(true); 52eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } catch (NoSuchMethodException e) { 53eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas Log.i(TAG, "Failed to retrieve getIBinder method", e); 54eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 55eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sGetIBinderMethodFetched = true; 56eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 57eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 58eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas if (sGetIBinderMethod != null) { 59eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas try { 60eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas return (IBinder) sGetIBinderMethod.invoke(bundle, key); 61eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } catch (InvocationTargetException | IllegalAccessException 62eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas | IllegalArgumentException e) { 63eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas Log.i(TAG, "Failed to invoke getIBinder via reflection", e); 64eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sGetIBinderMethod = null; 65eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 66eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 67eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas return null; 68eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 69eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 70eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas public static void putBinder(Bundle bundle, String key, IBinder binder) { 71eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas if (!sPutIBinderMethodFetched) { 72eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas try { 73eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sPutIBinderMethod = 74eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas Bundle.class.getMethod("putIBinder", String.class, IBinder.class); 75eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sPutIBinderMethod.setAccessible(true); 76eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } catch (NoSuchMethodException e) { 77eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas Log.i(TAG, "Failed to retrieve putIBinder method", e); 78eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 79eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sPutIBinderMethodFetched = true; 80eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 81eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 82eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas if (sPutIBinderMethod != null) { 83eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas try { 84eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sPutIBinderMethod.invoke(bundle, key, binder); 85eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } catch (InvocationTargetException | IllegalAccessException 86eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas | IllegalArgumentException e) { 87eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas Log.i(TAG, "Failed to invoke putIBinder via reflection", e); 88eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas sPutIBinderMethod = null; 89eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 90eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 91eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 92eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas } 93eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas 94c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes private BundleCompat() {} 95c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes 96c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal /** 97c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * A convenience method to handle getting an {@link IBinder} inside a {@link Bundle} for all 98c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * Android versions. 99c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * @param bundle The bundle to get the {@link IBinder}. 100c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * @param key The key to use while getting the {@link IBinder}. 101c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * @return The {@link IBinder} that was obtained. 102c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal */ 103cbfc663268973c9541708d3c4321e5fb906a3586Jake Wharton @Nullable 104cbfc663268973c9541708d3c4321e5fb906a3586Jake Wharton public static IBinder getBinder(@NonNull Bundle bundle, @Nullable String key) { 105c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal if (Build.VERSION.SDK_INT >= 18) { 106eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas return bundle.getBinder(key); 107c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal } else { 108eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas return BundleCompatBaseImpl.getBinder(bundle, key); 109c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal } 110c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal } 111c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal 112c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal /** 113c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * A convenience method to handle putting an {@link IBinder} inside a {@link Bundle} for all 114c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * Android versions. 115c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * @param bundle The bundle to insert the {@link IBinder}. 116c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * @param key The key to use while putting the {@link IBinder}. 117c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal * @param binder The {@link IBinder} to put. 118c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal */ 119cbfc663268973c9541708d3c4321e5fb906a3586Jake Wharton public static void putBinder(@NonNull Bundle bundle, @Nullable String key, 120cbfc663268973c9541708d3c4321e5fb906a3586Jake Wharton @Nullable IBinder binder) { 121c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal if (Build.VERSION.SDK_INT >= 18) { 122eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas bundle.putBinder(key, binder); 123c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal } else { 124eedd63f194a4bf7de284e3771fea451f1724bf26Aurimas Liutikas BundleCompatBaseImpl.putBinder(bundle, key, binder); 125c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal } 126c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal } 127c5c0045de7c8848144a570665e0d3c950816f314Yusuf Ozuysal} 128