1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.layoutlib.bridge.android; 18 19 import com.android.ide.common.rendering.api.AndroidConstants; 20 import com.android.ide.common.rendering.api.AssetRepository; 21 import com.android.ide.common.rendering.api.ILayoutLog; 22 import com.android.ide.common.rendering.api.ILayoutPullParser; 23 import com.android.ide.common.rendering.api.LayoutlibCallback; 24 import com.android.ide.common.rendering.api.RenderResources; 25 import com.android.ide.common.rendering.api.ResourceNamespace; 26 import com.android.ide.common.rendering.api.ResourceNamespace.Resolver; 27 import com.android.ide.common.rendering.api.ResourceReference; 28 import com.android.ide.common.rendering.api.ResourceValue; 29 import com.android.ide.common.rendering.api.ResourceValueImpl; 30 import com.android.ide.common.rendering.api.StyleResourceValue; 31 import com.android.layoutlib.bridge.Bridge; 32 import com.android.layoutlib.bridge.BridgeConstants; 33 import com.android.layoutlib.bridge.SessionInteractiveData; 34 import com.android.layoutlib.bridge.impl.ParserFactory; 35 import com.android.layoutlib.bridge.impl.ResourceHelper; 36 import com.android.layoutlib.bridge.impl.Stack; 37 import com.android.resources.ResourceType; 38 import com.android.tools.layoutlib.annotations.NotNull; 39 40 import org.xmlpull.v1.XmlPullParser; 41 import org.xmlpull.v1.XmlPullParserException; 42 43 import android.annotation.NonNull; 44 import android.annotation.Nullable; 45 import android.app.ActivityManager; 46 import android.app.ActivityManager_Accessor; 47 import android.app.SystemServiceRegistry; 48 import android.content.BroadcastReceiver; 49 import android.content.ClipboardManager; 50 import android.content.ComponentCallbacks; 51 import android.content.ComponentName; 52 import android.content.ContentResolver; 53 import android.content.Context; 54 import android.content.ContextWrapper; 55 import android.content.Intent; 56 import android.content.IntentFilter; 57 import android.content.IntentSender; 58 import android.content.ServiceConnection; 59 import android.content.SharedPreferences; 60 import android.content.pm.ApplicationInfo; 61 import android.content.pm.PackageManager; 62 import android.content.res.AssetManager; 63 import android.content.res.BridgeAssetManager; 64 import android.content.res.BridgeTypedArray; 65 import android.content.res.Configuration; 66 import android.content.res.Resources; 67 import android.content.res.Resources.Theme; 68 import android.content.res.Resources_Delegate; 69 import android.database.DatabaseErrorHandler; 70 import android.database.sqlite.SQLiteDatabase; 71 import android.database.sqlite.SQLiteDatabase.CursorFactory; 72 import android.graphics.Bitmap; 73 import android.graphics.drawable.Drawable; 74 import android.hardware.display.DisplayManager; 75 import android.media.AudioManager; 76 import android.net.ConnectivityManager; 77 import android.net.Uri; 78 import android.os.Bundle; 79 import android.os.Handler; 80 import android.os.IBinder; 81 import android.os.IInterface; 82 import android.os.Looper; 83 import android.os.Parcel; 84 import android.os.PowerManager; 85 import android.os.RemoteException; 86 import android.os.ResultReceiver; 87 import android.os.ShellCallback; 88 import android.os.UserHandle; 89 import android.util.AttributeSet; 90 import android.util.DisplayMetrics; 91 import android.util.Pair; 92 import android.util.TypedValue; 93 import android.view.BridgeInflater; 94 import android.view.Display; 95 import android.view.DisplayAdjustments; 96 import android.view.View; 97 import android.view.ViewGroup; 98 import android.view.WindowManager; 99 import android.view.WindowManagerImpl; 100 import android.view.accessibility.AccessibilityManager; 101 import android.view.autofill.AutofillManager; 102 import android.view.autofill.IAutoFillManager.Default; 103 import android.view.inputmethod.InputMethodManager; 104 import android.view.textservice.TextServicesManager; 105 106 import java.io.File; 107 import java.io.FileDescriptor; 108 import java.io.FileInputStream; 109 import java.io.FileNotFoundException; 110 import java.io.FileOutputStream; 111 import java.io.IOException; 112 import java.io.InputStream; 113 import java.util.ArrayList; 114 import java.util.HashMap; 115 import java.util.IdentityHashMap; 116 import java.util.List; 117 import java.util.Map; 118 import java.util.concurrent.Executor; 119 120 import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1; 121 import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; 122 123 /** 124 * Custom implementation of Context/Activity to handle non compiled resources. 125 */ 126 public class BridgeContext extends Context { 127 private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; 128 129 private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2); 130 private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3); 131 132 static { 133 FRAMEWORK_PATCHED_VALUES.put("animateFirstView", 134 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.BOOL, 135 "animateFirstView", "false")); 136 FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", 137 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.BOOL, 138 "animateLayoutChanges", "false")); 139 140 141 FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout", 142 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.LAYOUT, 143 "textEditSuggestionItemLayout", "text_edit_suggestion_item")); 144 FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout", 145 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.LAYOUT, 146 "textEditSuggestionContainerLayout", "text_edit_suggestion_container")); 147 FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle", 148 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.STYLE, 149 "textEditSuggestionHighlightStyle", 150 "TextAppearance.Holo.SuggestionHighlight")); 151 } 152 153 /** The map adds cookies to each view so that IDE can link xml tags to views. */ 154 private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); 155 /** 156 * In some cases, when inflating an xml, some objects are created. Then later, the objects are 157 * converted to views. This map stores the mapping from objects to cookies which can then be 158 * used to populate the mViewKeyMap. 159 */ 160 private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>(); 161 private final BridgeAssetManager mAssets; 162 private Resources mSystemResources; 163 private final Object mProjectKey; 164 private final DisplayMetrics mMetrics; 165 private final RenderResources mRenderResources; 166 private final Configuration mConfig; 167 private final ApplicationInfo mApplicationInfo; 168 private final LayoutlibCallback mLayoutlibCallback; 169 private final WindowManager mWindowManager; 170 private final DisplayManager mDisplayManager; 171 private final AutofillManager mAutofillManager; 172 private final ClipboardManager mClipboardManager; 173 private final ActivityManager mActivityManager; 174 private final ConnectivityManager mConnectivityManager; 175 private final AudioManager mAudioManager; 176 private final HashMap<View, Integer> mScrollYPos = new HashMap<>(); 177 private final HashMap<View, Integer> mScrollXPos = new HashMap<>(); 178 179 private Resources.Theme mTheme; 180 181 private final Map<Object, Map<ResourceReference, ResourceValue>> mDefaultPropMaps = 182 new IdentityHashMap<>(); 183 private final Map<Object, ResourceReference> mDefaultStyleMap = new IdentityHashMap<>(); 184 185 // cache for TypedArray generated from StyleResourceValue object 186 private TypedArrayCache mTypedArrayCache; 187 private BridgeInflater mBridgeInflater; 188 189 private BridgeContentResolver mContentResolver; 190 191 private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>(); 192 private SharedPreferences mSharedPreferences; 193 private ClassLoader mClassLoader; 194 private IBinder mBinder; 195 private PackageManager mPackageManager; 196 private Boolean mIsThemeAppCompat; 197 private final ResourceNamespace mAppCompatNamespace; 198 private final Map<Key<?>, Object> mUserData = new HashMap<>(); 199 200 private final SessionInteractiveData mSessionInteractiveData; 201 202 /** 203 * Some applications that target both pre API 17 and post API 17, set the newer attrs to 204 * reference the older ones. For example, android:paddingStart will resolve to 205 * android:paddingLeft. This way the apps need to only define paddingLeft at any other place. 206 * This a map from value to attribute name. Warning for missing references shouldn't be logged 207 * if value and attr name pair is the same as an entry in this map. 208 */ 209 private static Map<String, String> RTL_ATTRS = new HashMap<>(10); 210 211 static { 212 RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart"); 213 RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd"); 214 RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart"); 215 RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd"); 216 RTL_ATTRS.put("?android:attr/layout_toLeftOf", "layout_toStartOf"); 217 RTL_ATTRS.put("?android:attr/layout_toRightOf", "layout_toEndOf"); 218 RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart"); 219 RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd"); 220 RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart"); 221 RTL_ATTRS.put("?android:attr/drawableRight", "drawableEnd"); 222 } 223 224 /** 225 * @param projectKey An Object identifying the project. This is used for the cache mechanism. 226 * @param metrics the {@link DisplayMetrics}. 227 * @param renderResources the configured resources (both framework and projects) for this 228 * render. 229 * @param config the Configuration object for this render. 230 * @param targetSdkVersion the targetSdkVersion of the application. 231 */ BridgeContext(Object projectKey, @NonNull DisplayMetrics metrics, @NonNull RenderResources renderResources, @NonNull AssetRepository assets, @NonNull LayoutlibCallback layoutlibCallback, @NonNull Configuration config, int targetSdkVersion, boolean hasRtlSupport)232 public BridgeContext(Object projectKey, @NonNull DisplayMetrics metrics, 233 @NonNull RenderResources renderResources, 234 @NonNull AssetRepository assets, 235 @NonNull LayoutlibCallback layoutlibCallback, 236 @NonNull Configuration config, 237 int targetSdkVersion, 238 boolean hasRtlSupport) { 239 mProjectKey = projectKey; 240 mMetrics = metrics; 241 mLayoutlibCallback = layoutlibCallback; 242 243 mRenderResources = renderResources; 244 mConfig = config; 245 AssetManager systemAssetManager = AssetManager.getSystem(); 246 if (systemAssetManager instanceof BridgeAssetManager) { 247 mAssets = (BridgeAssetManager) systemAssetManager; 248 } else { 249 throw new AssertionError("Creating BridgeContext without initializing Bridge"); 250 } 251 mAssets.setAssetRepository(assets); 252 253 mApplicationInfo = new ApplicationInfo(); 254 mApplicationInfo.targetSdkVersion = targetSdkVersion; 255 if (hasRtlSupport) { 256 mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL; 257 } 258 259 mWindowManager = new WindowManagerImpl(this, mMetrics); 260 mDisplayManager = new DisplayManager(this); 261 mAutofillManager = new AutofillManager(this, new Default()); 262 mClipboardManager = new ClipboardManager(this, null); 263 mActivityManager = ActivityManager_Accessor.getActivityManagerInstance(this); 264 mConnectivityManager = new ConnectivityManager(this, null); 265 mAudioManager = new AudioManager(this); 266 267 if (mLayoutlibCallback.isResourceNamespacingRequired()) { 268 if (mLayoutlibCallback.hasAndroidXAppCompat()) { 269 mAppCompatNamespace = ResourceNamespace.APPCOMPAT; 270 } else { 271 mAppCompatNamespace = ResourceNamespace.APPCOMPAT_LEGACY; 272 } 273 } else { 274 mAppCompatNamespace = ResourceNamespace.RES_AUTO; 275 } 276 277 mSessionInteractiveData = new SessionInteractiveData(); 278 } 279 280 /** 281 * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its 282 * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}. 283 * 284 * @see #disposeResources() 285 */ initResources(@onNull AssetRepository assetRepository)286 public void initResources(@NonNull AssetRepository assetRepository) { 287 AssetManager assetManager = AssetManager.getSystem(); 288 289 mAssets.setAssetRepository(assetRepository); 290 291 mSystemResources = Resources_Delegate.initSystem( 292 this, 293 assetManager, 294 mMetrics, 295 mConfig, 296 mLayoutlibCallback); 297 mTheme = mSystemResources.newTheme(); 298 } 299 300 /** 301 * Disposes the {@link Resources} singleton and the AssetRepository inside BridgeAssetManager. 302 */ disposeResources()303 public void disposeResources() { 304 Resources_Delegate.disposeSystem(); 305 306 // The BridgeAssetManager pointed to by the mAssets field is a long-lived object, but 307 // the AssetRepository is not. To prevent it from leaking clear a reference to it from 308 // the BridgeAssetManager. 309 mAssets.releaseAssetRepository(); 310 } 311 setBridgeInflater(BridgeInflater inflater)312 public void setBridgeInflater(BridgeInflater inflater) { 313 mBridgeInflater = inflater; 314 } 315 addViewKey(View view, Object viewKey)316 public void addViewKey(View view, Object viewKey) { 317 mViewKeyMap.put(view, viewKey); 318 } 319 getViewKey(View view)320 public Object getViewKey(View view) { 321 return mViewKeyMap.get(view); 322 } 323 addCookie(Object o, Object cookie)324 public void addCookie(Object o, Object cookie) { 325 mViewKeyHelpMap.put(o, cookie); 326 } 327 getCookie(Object o)328 public Object getCookie(Object o) { 329 return mViewKeyHelpMap.get(o); 330 } 331 getProjectKey()332 public Object getProjectKey() { 333 return mProjectKey; 334 } 335 getMetrics()336 public DisplayMetrics getMetrics() { 337 return mMetrics; 338 } 339 getLayoutlibCallback()340 public LayoutlibCallback getLayoutlibCallback() { 341 return mLayoutlibCallback; 342 } 343 getRenderResources()344 public RenderResources getRenderResources() { 345 return mRenderResources; 346 } 347 getDefaultProperties()348 public Map<Object, Map<ResourceReference, ResourceValue>> getDefaultProperties() { 349 return mDefaultPropMaps; 350 } 351 getDefaultNamespacedStyles()352 public Map<Object, ResourceReference> getDefaultNamespacedStyles() { 353 return mDefaultStyleMap; 354 } 355 getConfiguration()356 public Configuration getConfiguration() { 357 return mConfig; 358 } 359 360 /** 361 * Adds a parser to the stack. 362 * @param parser the parser to add. 363 */ pushParser(BridgeXmlBlockParser parser)364 public void pushParser(BridgeXmlBlockParser parser) { 365 if (ParserFactory.LOG_PARSER) { 366 System.out.println("PUSH " + parser.getParser().toString()); 367 } 368 mParserStack.push(parser); 369 } 370 371 /** 372 * Removes the parser at the top of the stack 373 */ popParser()374 public void popParser() { 375 BridgeXmlBlockParser parser = mParserStack.pop(); 376 if (ParserFactory.LOG_PARSER) { 377 System.out.println("POPD " + parser.getParser().toString()); 378 } 379 } 380 381 /** 382 * Returns the current parser at the top the of the stack. 383 * @return a parser or null. 384 */ getCurrentParser()385 private BridgeXmlBlockParser getCurrentParser() { 386 return mParserStack.peek(); 387 } 388 389 /** 390 * Returns the previous parser. 391 * @return a parser or null if there isn't any previous parser 392 */ getPreviousParser()393 public BridgeXmlBlockParser getPreviousParser() { 394 if (mParserStack.size() < 2) { 395 return null; 396 } 397 return mParserStack.get(mParserStack.size() - 2); 398 } 399 resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs)400 public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) { 401 ResourceReference resourceInfo = Bridge.resolveResourceId(resId); 402 if (resourceInfo == null) { 403 resourceInfo = mLayoutlibCallback.resolveResourceId(resId); 404 } 405 406 if (resourceInfo == null || resourceInfo.getResourceType() != ResourceType.ATTR) { 407 return false; 408 } 409 410 ResourceValue value = mRenderResources.findItemInTheme(resourceInfo); 411 if (resolveRefs) { 412 value = mRenderResources.resolveResValue(value); 413 } 414 415 if (value == null) { 416 // unable to find the attribute. 417 return false; 418 } 419 420 // check if this is a style resource 421 if (value instanceof StyleResourceValue) { 422 // get the id that will represent this style. 423 outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value); 424 return true; 425 } 426 427 String stringValue = value.getValue(); 428 if (!stringValue.isEmpty()) { 429 if (stringValue.charAt(0) == '#') { 430 outValue.data = ResourceHelper.getColor(stringValue); 431 switch (stringValue.length()) { 432 case 4: 433 outValue.type = TypedValue.TYPE_INT_COLOR_RGB4; 434 break; 435 case 5: 436 outValue.type = TypedValue.TYPE_INT_COLOR_ARGB4; 437 break; 438 case 7: 439 outValue.type = TypedValue.TYPE_INT_COLOR_RGB8; 440 break; 441 default: 442 outValue.type = TypedValue.TYPE_INT_COLOR_ARGB8; 443 } 444 } 445 else if (stringValue.charAt(0) == '@') { 446 outValue.type = TypedValue.TYPE_REFERENCE; 447 } 448 else if ("true".equals(stringValue) || "false".equals(stringValue)) { 449 outValue.type = TypedValue.TYPE_INT_BOOLEAN; 450 outValue.data = "true".equals(stringValue) ? 1 : 0; 451 } 452 } 453 454 int a = getResourceId(value.asReference(), 0 /*defValue*/); 455 456 if (a != 0) { 457 outValue.resourceId = a; 458 return true; 459 } 460 461 // If the value is not a valid reference, fallback to pass the value as a string. 462 outValue.string = stringValue; 463 return true; 464 } 465 466 resolveId(int id)467 public ResourceReference resolveId(int id) { 468 // first get the String related to this id in the framework 469 ResourceReference resourceInfo = Bridge.resolveResourceId(id); 470 471 if (resourceInfo != null) { 472 return resourceInfo; 473 } 474 475 // didn't find a match in the framework? look in the project. 476 if (mLayoutlibCallback != null) { 477 resourceInfo = mLayoutlibCallback.resolveResourceId(id); 478 479 if (resourceInfo != null) { 480 return resourceInfo; 481 } 482 } 483 484 return null; 485 } 486 inflateView(ResourceReference layout, ViewGroup parent, @SuppressWarnings("SameParameterValue") boolean attachToRoot, boolean skipCallbackParser)487 public Pair<View, Boolean> inflateView(ResourceReference layout, ViewGroup parent, 488 @SuppressWarnings("SameParameterValue") boolean attachToRoot, 489 boolean skipCallbackParser) { 490 boolean isPlatformLayout = layout.getNamespace().equals(ResourceNamespace.ANDROID); 491 492 if (!isPlatformLayout && !skipCallbackParser) { 493 // check if the project callback can provide us with a custom parser. 494 ILayoutPullParser parser = null; 495 ResourceValue layoutValue = mRenderResources.getResolvedResource(layout); 496 if (layoutValue != null) { 497 parser = getLayoutlibCallback().getParser(layoutValue); 498 } 499 500 if (parser != null) { 501 BridgeXmlBlockParser blockParser = 502 new BridgeXmlBlockParser(parser, this, layout.getNamespace()); 503 try { 504 pushParser(blockParser); 505 return Pair.create( 506 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 507 Boolean.TRUE); 508 } finally { 509 popParser(); 510 } 511 } 512 } 513 514 ResourceValue resValue = mRenderResources.getResolvedResource(layout); 515 516 if (resValue != null) { 517 String path = resValue.getValue(); 518 // We need to create a pull parser around the layout XML file, and then 519 // give that to our XmlBlockParser. 520 try { 521 XmlPullParser parser = ParserFactory.create(path, true); 522 if (parser != null) { 523 // Set the layout ref to have correct view cookies. 524 mBridgeInflater.setResourceReference(layout); 525 526 BridgeXmlBlockParser blockParser = 527 new BridgeXmlBlockParser(parser, this, layout.getNamespace()); 528 try { 529 pushParser(blockParser); 530 return Pair.create(mBridgeInflater.inflate(blockParser, parent, 531 attachToRoot), 532 Boolean.FALSE); 533 } finally { 534 popParser(); 535 } 536 } else { 537 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 538 String.format("File %s is missing!", path), null, null); 539 } 540 } catch (XmlPullParserException e) { 541 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 542 "Failed to parse file " + path, e, null, null /*data*/); 543 // we'll return null below. 544 } finally { 545 mBridgeInflater.setResourceReference(null); 546 } 547 } else { 548 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 549 String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", 550 layout.getName()), null, null); 551 } 552 553 return Pair.create(null, Boolean.FALSE); 554 } 555 556 /** 557 * Returns whether the current selected theme is based on AppCompat 558 */ isAppCompatTheme()559 public boolean isAppCompatTheme() { 560 // If a cached value exists, return it. 561 if (mIsThemeAppCompat != null) { 562 return mIsThemeAppCompat; 563 } 564 // Ideally, we should check if the corresponding activity extends 565 // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. 566 StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme(); 567 // We can't simply check for parent using resources.themeIsParentOf() since the 568 // inheritance structure isn't really what one would expect. The first common parent 569 // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). 570 boolean isThemeAppCompat = false; 571 for (int i = 0; i < 50; i++) { 572 if (defaultTheme == null) { 573 break; 574 } 575 // for loop ensures that we don't run into cyclic theme inheritance. 576 if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { 577 isThemeAppCompat = true; 578 break; 579 } 580 defaultTheme = mRenderResources.getParent(defaultTheme); 581 } 582 mIsThemeAppCompat = isThemeAppCompat; 583 return isThemeAppCompat; 584 } 585 586 // ------------ Context methods 587 588 @Override getResources()589 public Resources getResources() { 590 return mSystemResources; 591 } 592 593 @Override getTheme()594 public Theme getTheme() { 595 return mTheme; 596 } 597 598 @Override getClassLoader()599 public ClassLoader getClassLoader() { 600 // The documentation for this method states that it should return a class loader one can 601 // use to retrieve classes in this package. However, when called by LayoutInflater, we do 602 // not want the class loader to return app's custom views. 603 // This is so that the IDE can instantiate the custom views and also generate proper error 604 // messages in case of failure. This also enables the IDE to fallback to MockView in case 605 // there's an exception thrown when trying to inflate the custom view. 606 // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to 607 // replace invocations of this method to a new method: getFrameworkClassLoader(). Also, 608 // the method is injected into Context. The implementation of getFrameworkClassLoader() is: 609 // "return getClass().getClassLoader();". This means that when LayoutInflater asks for 610 // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have 611 // access to the apps's custom views. 612 // This method can now return the right ClassLoader, which CustomViews can use to do the 613 // right thing. 614 if (mClassLoader == null) { 615 mClassLoader = new ClassLoader(getClass().getClassLoader()) { 616 @Override 617 protected Class<?> findClass(String name) throws ClassNotFoundException { 618 for (String prefix : BridgeInflater.getClassPrefixList()) { 619 if (name.startsWith(prefix)) { 620 // These are framework classes and should not be loaded from the app. 621 throw new ClassNotFoundException(name + " not found"); 622 } 623 } 624 return BridgeContext.this.mLayoutlibCallback.findClass(name); 625 } 626 }; 627 } 628 return mClassLoader; 629 } 630 631 @Override getSystemService(String service)632 public Object getSystemService(String service) { 633 switch (service) { 634 case LAYOUT_INFLATER_SERVICE: 635 return mBridgeInflater; 636 637 case TEXT_SERVICES_MANAGER_SERVICE: 638 // we need to return a valid service to avoid NPE 639 return TextServicesManager.getInstance(); 640 641 case WINDOW_SERVICE: 642 return mWindowManager; 643 644 case POWER_SERVICE: 645 return new PowerManager(this, new BridgePowerManager(), new BridgeThermalService(), 646 new Handler()); 647 648 case DISPLAY_SERVICE: 649 return mDisplayManager; 650 651 case ACCESSIBILITY_SERVICE: 652 return AccessibilityManager.getInstance(this); 653 654 case INPUT_METHOD_SERVICE: // needed by SearchView and Compose 655 return InputMethodManager.forContext(this); 656 657 case AUTOFILL_MANAGER_SERVICE: 658 return mAutofillManager; 659 660 case CLIPBOARD_SERVICE: 661 return mClipboardManager; 662 663 case ACTIVITY_SERVICE: 664 return mActivityManager; 665 666 case CONNECTIVITY_SERVICE: 667 return mConnectivityManager; 668 669 case AUDIO_SERVICE: 670 return mAudioManager; 671 672 case TEXT_CLASSIFICATION_SERVICE: 673 case CONTENT_CAPTURE_MANAGER_SERVICE: 674 case ALARM_SERVICE: 675 return null; 676 default: 677 // Only throw exception if the required service is unsupported but recognized as 678 // an existing system service. 679 assert SystemServiceRegistry.getSystemServiceClassName(service) == null : 680 "Unsupported Service: " + service; 681 Bridge.getLog().warning(ILayoutLog.TAG_UNSUPPORTED, "Service " + service + 682 " was not found or is unsupported", null, null); 683 } 684 685 return null; 686 } 687 688 @Override getSystemServiceName(Class<?> serviceClass)689 public String getSystemServiceName(Class<?> serviceClass) { 690 return SystemServiceRegistry.getSystemServiceName(serviceClass); 691 } 692 693 /** 694 * Same as Context#obtainStyledAttributes. We do not override the base method to give the 695 * original Context the chance to override the theme when needed. 696 */ 697 @Nullable internalObtainStyledAttributes(int resId, int[] attrs)698 public final BridgeTypedArray internalObtainStyledAttributes(int resId, int[] attrs) 699 throws Resources.NotFoundException { 700 StyleResourceValue style = null; 701 // get the StyleResourceValue based on the resId; 702 if (resId != 0) { 703 style = getStyleByDynamicId(resId); 704 705 if (style == null) { 706 // In some cases, style may not be a dynamic id, so we do a full search. 707 ResourceReference ref = resolveId(resId); 708 if (ref != null) { 709 style = mRenderResources.getStyle(ref); 710 } 711 } 712 713 if (style == null) { 714 Bridge.getLog().error(ILayoutLog.TAG_RESOURCES_RESOLVE, 715 "Failed to find style with " + resId, null, null); 716 return null; 717 } 718 } 719 720 if (mTypedArrayCache == null) { 721 mTypedArrayCache = new TypedArrayCache(); 722 } 723 724 List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes(); 725 726 Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> typeArrayAndPropertiesPair = 727 mTypedArrayCache.get(attrs, currentThemes, resId); 728 729 if (typeArrayAndPropertiesPair == null) { 730 typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs); 731 mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair); 732 } 733 // Add value to defaultPropsMap if needed 734 if (typeArrayAndPropertiesPair.second != null) { 735 BridgeXmlBlockParser parser = getCurrentParser(); 736 Object key = parser != null ? parser.getViewCookie() : null; 737 if (key != null) { 738 Map<ResourceReference, ResourceValue> defaultPropMap = mDefaultPropMaps.get(key); 739 if (defaultPropMap == null) { 740 defaultPropMap = typeArrayAndPropertiesPair.second; 741 mDefaultPropMaps.put(key, defaultPropMap); 742 } else { 743 defaultPropMap.putAll(typeArrayAndPropertiesPair.second); 744 } 745 } 746 } 747 return typeArrayAndPropertiesPair.first; 748 } 749 750 /** 751 * Same as Context#obtainStyledAttributes. We do not override the base method to give the 752 * original Context the chance to override the theme when needed. 753 */ 754 @Nullable internalObtainStyledAttributes(@ullable AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)755 public BridgeTypedArray internalObtainStyledAttributes(@Nullable AttributeSet set, int[] attrs, 756 int defStyleAttr, int defStyleRes) { 757 758 Map<ResourceReference, ResourceValue> defaultPropMap = null; 759 Object key = null; 760 761 ResourceNamespace currentFileNamespace; 762 ResourceNamespace.Resolver resolver; 763 764 // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java 765 if (set instanceof BridgeXmlBlockParser) { 766 BridgeXmlBlockParser parser; 767 parser = (BridgeXmlBlockParser)set; 768 769 key = parser.getViewCookie(); 770 if (key != null) { 771 defaultPropMap = mDefaultPropMaps.computeIfAbsent(key, k -> new HashMap<>()); 772 } 773 774 currentFileNamespace = parser.getFileResourceNamespace(); 775 resolver = new XmlPullParserResolver(parser, mLayoutlibCallback.getImplicitNamespaces()); 776 } else if (set instanceof BridgeLayoutParamsMapAttributes) { 777 // This is for temp layout params generated dynamically in MockView. The set contains 778 // hardcoded values and we don't need to worry about resolving them. 779 currentFileNamespace = ResourceNamespace.RES_AUTO; 780 resolver = Resolver.EMPTY_RESOLVER; 781 } else if (set != null) { 782 // really this should not be happening since its instantiated in Bridge 783 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 784 "Parser is not a BridgeXmlBlockParser!", null, null); 785 return null; 786 } else { 787 // `set` is null, so there will be no values to resolve. 788 currentFileNamespace = ResourceNamespace.RES_AUTO; 789 resolver = Resolver.EMPTY_RESOLVER; 790 } 791 792 List<AttributeHolder> attributeList = searchAttrs(attrs); 793 794 BridgeTypedArray ta = 795 Resources_Delegate.newTypeArray(mSystemResources, attrs.length); 796 797 // Look for a custom style. 798 StyleResourceValue customStyleValues = null; 799 if (set != null) { 800 String customStyle = set.getAttributeValue(null, "style"); 801 if (customStyle != null) { 802 ResourceValue resolved = mRenderResources.resolveResValue( 803 new UnresolvedResourceValue(customStyle, currentFileNamespace, resolver)); 804 805 if (resolved instanceof StyleResourceValue) { 806 customStyleValues = (StyleResourceValue) resolved; 807 } 808 } 809 } 810 811 // resolve the defStyleAttr value into a StyleResourceValue 812 StyleResourceValue defStyleValues = null; 813 814 if (defStyleAttr != 0) { 815 // get the name from the int. 816 ResourceReference defStyleAttribute = searchAttr(defStyleAttr); 817 818 if (defStyleAttribute == null) { 819 // This should be rare. Happens trying to map R.style.foo to @style/foo fails. 820 // This will happen if the user explicitly used a non existing int value for 821 // defStyleAttr or there's something wrong with the project structure/build. 822 Bridge.getLog().error(ILayoutLog.TAG_RESOURCES_RESOLVE, 823 "Failed to find the style corresponding to the id " + defStyleAttr, null, 824 null); 825 } else { 826 // look for the style in the current theme, and its parent: 827 ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute); 828 829 if (item != null) { 830 if (key != null) { 831 mDefaultStyleMap.put(key, defStyleAttribute); 832 } 833 // item is a reference to a style entry. Search for it. 834 item = mRenderResources.resolveResValue(item); 835 if (item instanceof StyleResourceValue) { 836 defStyleValues = (StyleResourceValue) item; 837 } 838 } 839 } 840 } 841 842 if (defStyleValues == null && defStyleRes != 0) { 843 StyleResourceValue item = getStyleByDynamicId(defStyleRes); 844 if (item != null) { 845 defStyleValues = item; 846 } else { 847 ResourceReference value = Bridge.resolveResourceId(defStyleRes); 848 if (value == null) { 849 value = mLayoutlibCallback.resolveResourceId(defStyleRes); 850 } 851 852 if (value != null) { 853 if ((value.getResourceType() == ResourceType.STYLE)) { 854 // look for the style in all resources: 855 item = mRenderResources.getStyle(value); 856 if (item != null) { 857 if (key != null) { 858 mDefaultStyleMap.put(key, item.asReference()); 859 } 860 861 defStyleValues = item; 862 } else { 863 Bridge.getLog().error(null, 864 String.format( 865 "Style with id 0x%x (resolved to '%s') does not exist.", 866 defStyleRes, value.getName()), 867 null, null); 868 } 869 } else { 870 Bridge.getLog().error(null, 871 String.format( 872 "Resource id 0x%x is not of type STYLE (instead %s)", 873 defStyleRes, value.getResourceType().name()), 874 null, null); 875 } 876 } else { 877 Bridge.getLog().error(null, 878 String.format( 879 "Failed to find style with id 0x%x in current theme", 880 defStyleRes), 881 null, null); 882 } 883 } 884 } 885 886 if (attributeList != null) { 887 for (int index = 0 ; index < attributeList.size() ; index++) { 888 AttributeHolder attributeHolder = attributeList.get(index); 889 890 if (attributeHolder == null) { 891 continue; 892 } 893 894 String attrName = attributeHolder.getName(); 895 String value = null; 896 if (set != null) { 897 value = set.getAttributeValue( 898 attributeHolder.getNamespace().getXmlNamespaceUri(), attrName); 899 900 // if this is an app attribute, and the first get fails, try with the 901 // new res-auto namespace as well 902 if (attributeHolder.getNamespace() != ResourceNamespace.ANDROID && value == null) { 903 value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); 904 } 905 } 906 907 // Calculate the default value from the Theme in two cases: 908 // - If defaultPropMap is not null, get the default value to add it to the list 909 // of default values of properties. 910 // - If value is null, it means that the attribute is not directly set as an 911 // attribute in the XML so try to get the default value. 912 ResourceValue defaultValue = null; 913 if (defaultPropMap != null || value == null) { 914 // look for the value in the custom style first (and its parent if needed) 915 ResourceReference attrRef = attributeHolder.asReference(); 916 if (customStyleValues != null) { 917 defaultValue = 918 mRenderResources.findItemInStyle(customStyleValues, attrRef); 919 } 920 921 // then look for the value in the default Style (and its parent if needed) 922 if (defaultValue == null && defStyleValues != null) { 923 defaultValue = 924 mRenderResources.findItemInStyle(defStyleValues, attrRef); 925 } 926 927 // if the item is not present in the defStyle, we look in the main theme (and 928 // its parent themes) 929 if (defaultValue == null) { 930 defaultValue = 931 mRenderResources.findItemInTheme(attrRef); 932 } 933 934 // if we found a value, we make sure this doesn't reference another value. 935 // So we resolve it. 936 if (defaultValue != null) { 937 if (defaultPropMap != null) { 938 defaultPropMap.put(attrRef, defaultValue); 939 } 940 941 defaultValue = mRenderResources.resolveResValue(defaultValue); 942 } 943 } 944 // Done calculating the defaultValue. 945 946 // If there's no direct value for this attribute in the XML, we look for default 947 // values in the widget defStyle, and then in the theme. 948 if (value == null) { 949 if (attributeHolder.getNamespace() == ResourceNamespace.ANDROID) { 950 // For some framework values, layoutlib patches the actual value in the 951 // theme when it helps to improve the final preview. In most cases 952 // we just disable animations. 953 ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName); 954 if (patchedValue != null) { 955 defaultValue = patchedValue; 956 } 957 } 958 959 // If we found a value, we make sure this doesn't reference another value. 960 // So we resolve it. 961 if (defaultValue != null) { 962 // If the value is a reference to another theme attribute that doesn't 963 // exist, we should log a warning and omit it. 964 String val = defaultValue.getValue(); 965 if (val != null && val.startsWith(AndroidConstants.PREFIX_THEME_REF)) { 966 // Because we always use the latest framework code, some resources might 967 // fail to resolve when using old themes (they haven't been backported). 968 // Since this is an artifact caused by us using always the latest 969 // code, we check for some of those values and replace them here. 970 ResourceReference reference = defaultValue.getReference(); 971 defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName); 972 973 // Only log a warning if the referenced value isn't one of the RTL 974 // attributes, or the app targets old API. 975 if (defaultValue == null && 976 (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 || 977 !attrName.equals(RTL_ATTRS.get(val)))) { 978 if (reference != null) { 979 val = reference.getResourceUrl().toString(); 980 } 981 Bridge.getLog().warning(ILayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 982 String.format("Failed to find '%s' in current theme.", val), 983 null, val); 984 } 985 } 986 } 987 988 ta.bridgeSetValue( 989 index, 990 attrName, attributeHolder.getNamespace(), 991 attributeHolder.getResourceId(), 992 defaultValue); 993 } else { 994 // There is a value in the XML, but we need to resolve it in case it's 995 // referencing another resource or a theme value. 996 ta.bridgeSetValue( 997 index, 998 attrName, attributeHolder.getNamespace(), 999 attributeHolder.getResourceId(), 1000 mRenderResources.resolveResValue( 1001 new UnresolvedResourceValue( 1002 value, currentFileNamespace, resolver))); 1003 } 1004 } 1005 } 1006 1007 ta.sealArray(); 1008 1009 return ta; 1010 } 1011 1012 @Override getMainLooper()1013 public Looper getMainLooper() { 1014 return Looper.myLooper(); 1015 } 1016 1017 1018 @Override getPackageName()1019 public String getPackageName() { 1020 if (mApplicationInfo.packageName == null) { 1021 mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE); 1022 } 1023 return mApplicationInfo.packageName; 1024 } 1025 1026 @Override getPackageManager()1027 public PackageManager getPackageManager() { 1028 if (mPackageManager == null) { 1029 mPackageManager = new BridgePackageManager(); 1030 } 1031 return mPackageManager; 1032 } 1033 1034 @Override registerComponentCallbacks(ComponentCallbacks callback)1035 public void registerComponentCallbacks(ComponentCallbacks callback) {} 1036 1037 @Override unregisterComponentCallbacks(ComponentCallbacks callback)1038 public void unregisterComponentCallbacks(ComponentCallbacks callback) {} 1039 1040 // ------------- private new methods 1041 1042 /** 1043 * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the 1044 * values found in the given style. If no style is specified, the default theme, along with the 1045 * styles applied to it are used. 1046 * 1047 * @see #obtainStyledAttributes(int, int[]) 1048 */ createStyleBasedTypedArray( @ullable StyleResourceValue style, int[] attrs)1049 private Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> createStyleBasedTypedArray( 1050 @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { 1051 List<AttributeHolder> attributes = searchAttrs(attrs); 1052 1053 BridgeTypedArray ta = 1054 Resources_Delegate.newTypeArray(mSystemResources, attrs.length); 1055 1056 Map<ResourceReference, ResourceValue> defaultPropMap = new HashMap<>(); 1057 // for each attribute, get its name so that we can search it in the style 1058 for (int i = 0; i < attrs.length; i++) { 1059 AttributeHolder attrHolder = attributes.get(i); 1060 1061 if (attrHolder != null) { 1062 // look for the value in the given style 1063 ResourceValue resValue; 1064 if (style != null) { 1065 resValue = mRenderResources.findItemInStyle(style, attrHolder.asReference()); 1066 } else { 1067 resValue = mRenderResources.findItemInTheme(attrHolder.asReference()); 1068 } 1069 1070 if (resValue != null) { 1071 defaultPropMap.put(attrHolder.asReference(), resValue); 1072 // resolve it to make sure there are no references left. 1073 resValue = mRenderResources.resolveResValue(resValue); 1074 ta.bridgeSetValue( 1075 i, attrHolder.getName(), attrHolder.getNamespace(), 1076 attrHolder.getResourceId(), 1077 resValue); 1078 } 1079 } 1080 } 1081 1082 ta.sealArray(); 1083 1084 return Pair.create(ta, defaultPropMap); 1085 } 1086 1087 /** 1088 * The input int[] attributeIds is a list of attributes. The returns a list of information about 1089 * each attributes. The information is (name, isFramework) 1090 * <p/> 1091 * 1092 * @param attributeIds An attribute array reference given to obtainStyledAttributes. 1093 * @return List of attribute information. 1094 */ searchAttrs(int[] attributeIds)1095 private List<AttributeHolder> searchAttrs(int[] attributeIds) { 1096 List<AttributeHolder> results = new ArrayList<>(attributeIds.length); 1097 1098 // for each attribute, get its name so that we can search it in the style 1099 for (int id : attributeIds) { 1100 ResourceReference refForId = Bridge.resolveResourceId(id); 1101 if (refForId == null) { 1102 refForId = mLayoutlibCallback.resolveResourceId(id); 1103 } 1104 1105 if (refForId != null) { 1106 results.add(new AttributeHolder(id, refForId)); 1107 } else { 1108 results.add(null); 1109 } 1110 } 1111 1112 return results; 1113 } 1114 1115 /** 1116 * Searches for the attribute referenced by its internal id. 1117 */ searchAttr(int attrId)1118 private ResourceReference searchAttr(int attrId) { 1119 ResourceReference attr = Bridge.resolveResourceId(attrId); 1120 if (attr == null) { 1121 attr = mLayoutlibCallback.resolveResourceId(attrId); 1122 } 1123 1124 return attr; 1125 } 1126 1127 /** 1128 * Maps a given style to a numeric id. 1129 * 1130 * <p>For now Bridge handles numeric ids (both fixed and dynamic) for framework and the callback 1131 * for non-framework. TODO(b/156609434): teach the IDE about fixed framework ids and handle this 1132 * all in the callback. 1133 */ getDynamicIdByStyle(StyleResourceValue resValue)1134 public int getDynamicIdByStyle(StyleResourceValue resValue) { 1135 if (resValue.isFramework()) { 1136 return Bridge.getResourceId(resValue.getResourceType(), resValue.getName()); 1137 } else { 1138 return mLayoutlibCallback.getOrGenerateResourceId(resValue.asReference()); 1139 } 1140 } 1141 1142 /** 1143 * Maps a numeric id back to {@link StyleResourceValue}. 1144 * 1145 * <p>For now framework numeric ids are handled by Bridge, so try there first and fall back to 1146 * the callback, which manages ids for non-framework resources. TODO(b/156609434): manage all 1147 * ids in the IDE. 1148 * 1149 * <p>Once we the resource for the given id, we ask the IDE to get the 1150 * {@link StyleResourceValue} for it. 1151 */ 1152 @Nullable getStyleByDynamicId(int id)1153 private StyleResourceValue getStyleByDynamicId(int id) { 1154 ResourceReference reference = Bridge.resolveResourceId(id); 1155 if (reference == null) { 1156 reference = mLayoutlibCallback.resolveResourceId(id); 1157 } 1158 1159 if (reference == null) { 1160 return null; 1161 } 1162 1163 return mRenderResources.getStyle(reference); 1164 } 1165 getResourceId(@onNull ResourceReference resource, int defValue)1166 public int getResourceId(@NonNull ResourceReference resource, int defValue) { 1167 if (getRenderResources().getUnresolvedResource(resource) != null) { 1168 if (resource.getNamespace().equals(ResourceNamespace.ANDROID)) { 1169 return Bridge.getResourceId(resource.getResourceType(), resource.getName()); 1170 } else if (mLayoutlibCallback != null) { 1171 return mLayoutlibCallback.getOrGenerateResourceId(resource); 1172 } 1173 } 1174 1175 return defValue; 1176 } 1177 getBaseContext(Context context)1178 public static Context getBaseContext(Context context) { 1179 while (context instanceof ContextWrapper) { 1180 context = ((ContextWrapper) context).getBaseContext(); 1181 } 1182 return context; 1183 } 1184 1185 /** 1186 * Returns the Framework attr resource reference with the given name. 1187 */ 1188 @NonNull createFrameworkAttrReference(@onNull String name)1189 public static ResourceReference createFrameworkAttrReference(@NonNull String name) { 1190 return createFrameworkResourceReference(ResourceType.ATTR, name); 1191 } 1192 1193 /** 1194 * Returns the Framework resource reference with the given type and name. 1195 */ 1196 @NonNull createFrameworkResourceReference(@onNull ResourceType type, @NonNull String name)1197 public static ResourceReference createFrameworkResourceReference(@NonNull ResourceType type, 1198 @NonNull String name) { 1199 return new ResourceReference(ResourceNamespace.ANDROID, type, name); 1200 } 1201 1202 /** 1203 * Returns the AppCompat attr resource reference with the given name. 1204 */ 1205 @NonNull createAppCompatAttrReference(@onNull String name)1206 public ResourceReference createAppCompatAttrReference(@NonNull String name) { 1207 return createAppCompatResourceReference(ResourceType.ATTR, name); 1208 } 1209 1210 /** 1211 * Returns the AppCompat resource reference with the given type and name. 1212 */ 1213 @NonNull createAppCompatResourceReference(@onNull ResourceType type, @NonNull String name)1214 public ResourceReference createAppCompatResourceReference(@NonNull ResourceType type, 1215 @NonNull String name) { 1216 return new ResourceReference(mAppCompatNamespace, type, name); 1217 } 1218 getBinder()1219 public IBinder getBinder() { 1220 if (mBinder == null) { 1221 // create a no-op binder. We only need it be not null. 1222 mBinder = new IBinder() { 1223 @Override 1224 public String getInterfaceDescriptor() throws RemoteException { 1225 return null; 1226 } 1227 1228 @Override 1229 public boolean pingBinder() { 1230 return false; 1231 } 1232 1233 @Override 1234 public boolean isBinderAlive() { 1235 return false; 1236 } 1237 1238 @Override 1239 public IInterface queryLocalInterface(String descriptor) { 1240 return null; 1241 } 1242 1243 @Override 1244 public void dump(FileDescriptor fd, String[] args) throws RemoteException { 1245 1246 } 1247 1248 @Override 1249 public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { 1250 1251 } 1252 1253 @Override 1254 public boolean transact(int code, Parcel data, Parcel reply, int flags) 1255 throws RemoteException { 1256 return false; 1257 } 1258 1259 @Override 1260 public void linkToDeath(DeathRecipient recipient, int flags) 1261 throws RemoteException { 1262 1263 } 1264 1265 @Override 1266 public boolean unlinkToDeath(DeathRecipient recipient, int flags) { 1267 return false; 1268 } 1269 1270 @Override 1271 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1272 String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) { 1273 } 1274 }; 1275 } 1276 return mBinder; 1277 } 1278 1279 //------------ NOT OVERRIDEN -------------------- 1280 1281 @Override bindService(Intent arg0, ServiceConnection arg1, int arg2)1282 public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { 1283 // pass 1284 return false; 1285 } 1286 1287 @Override bindService(Intent arg0, int arg1, Executor arg2, ServiceConnection arg3)1288 public boolean bindService(Intent arg0, int arg1, Executor arg2, ServiceConnection arg3) { 1289 return false; 1290 } 1291 1292 @Override bindIsolatedService(Intent arg0, int arg1, String arg2, Executor arg3, ServiceConnection arg4)1293 public boolean bindIsolatedService(Intent arg0, 1294 int arg1, String arg2, Executor arg3, ServiceConnection arg4) { 1295 return false; 1296 } 1297 1298 @Override checkCallingOrSelfPermission(String arg0)1299 public int checkCallingOrSelfPermission(String arg0) { 1300 // pass 1301 return 0; 1302 } 1303 1304 @Override checkCallingOrSelfUriPermission(Uri arg0, int arg1)1305 public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { 1306 // pass 1307 return 0; 1308 } 1309 1310 @Override checkCallingPermission(String arg0)1311 public int checkCallingPermission(String arg0) { 1312 // pass 1313 return 0; 1314 } 1315 1316 @Override checkCallingUriPermission(Uri arg0, int arg1)1317 public int checkCallingUriPermission(Uri arg0, int arg1) { 1318 // pass 1319 return 0; 1320 } 1321 1322 @Override checkPermission(String arg0, int arg1, int arg2)1323 public int checkPermission(String arg0, int arg1, int arg2) { 1324 // pass 1325 return 0; 1326 } 1327 1328 @Override checkSelfPermission(String arg0)1329 public int checkSelfPermission(String arg0) { 1330 // pass 1331 return 0; 1332 } 1333 1334 @Override checkPermission(String arg0, int arg1, int arg2, IBinder arg3)1335 public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) { 1336 // pass 1337 return 0; 1338 } 1339 1340 @Override checkUriPermission(Uri arg0, int arg1, int arg2, int arg3)1341 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { 1342 // pass 1343 return 0; 1344 } 1345 1346 @Override checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4)1347 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) { 1348 // pass 1349 return 0; 1350 } 1351 1352 @Override checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5)1353 public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, 1354 int arg4, int arg5) { 1355 // pass 1356 return 0; 1357 } 1358 1359 @Override clearWallpaper()1360 public void clearWallpaper() { 1361 // pass 1362 1363 } 1364 1365 @Override createPackageContext(String arg0, int arg1)1366 public Context createPackageContext(String arg0, int arg1) { 1367 // pass 1368 return null; 1369 } 1370 1371 @Override createPackageContextAsUser(String arg0, int arg1, UserHandle user)1372 public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { 1373 // pass 1374 return null; 1375 } 1376 1377 @Override createConfigurationContext(Configuration overrideConfiguration)1378 public Context createConfigurationContext(Configuration overrideConfiguration) { 1379 // pass 1380 return null; 1381 } 1382 1383 @Override createDisplayContext(Display display)1384 public Context createDisplayContext(Display display) { 1385 // pass 1386 return null; 1387 } 1388 1389 @Override createContextForSplit(String splitName)1390 public Context createContextForSplit(String splitName) { 1391 // pass 1392 return null; 1393 } 1394 1395 @Override databaseList()1396 public String[] databaseList() { 1397 // pass 1398 return null; 1399 } 1400 1401 @Override createApplicationContext(ApplicationInfo application, int flags)1402 public Context createApplicationContext(ApplicationInfo application, int flags) 1403 throws PackageManager.NameNotFoundException { 1404 return null; 1405 } 1406 1407 @Override moveDatabaseFrom(Context sourceContext, String name)1408 public boolean moveDatabaseFrom(Context sourceContext, String name) { 1409 // pass 1410 return false; 1411 } 1412 1413 @Override deleteDatabase(String arg0)1414 public boolean deleteDatabase(String arg0) { 1415 // pass 1416 return false; 1417 } 1418 1419 @Override deleteFile(String arg0)1420 public boolean deleteFile(String arg0) { 1421 // pass 1422 return false; 1423 } 1424 1425 @Override enforceCallingOrSelfPermission(String arg0, String arg1)1426 public void enforceCallingOrSelfPermission(String arg0, String arg1) { 1427 // pass 1428 1429 } 1430 1431 @Override enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2)1432 public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, 1433 String arg2) { 1434 // pass 1435 1436 } 1437 1438 @Override enforceCallingPermission(String arg0, String arg1)1439 public void enforceCallingPermission(String arg0, String arg1) { 1440 // pass 1441 1442 } 1443 1444 @Override enforceCallingUriPermission(Uri arg0, int arg1, String arg2)1445 public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { 1446 // pass 1447 1448 } 1449 1450 @Override enforcePermission(String arg0, int arg1, int arg2, String arg3)1451 public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { 1452 // pass 1453 1454 } 1455 1456 @Override enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4)1457 public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, 1458 String arg4) { 1459 // pass 1460 1461 } 1462 1463 @Override enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6)1464 public void enforceUriPermission(Uri arg0, String arg1, String arg2, 1465 int arg3, int arg4, int arg5, String arg6) { 1466 // pass 1467 1468 } 1469 1470 @Override fileList()1471 public String[] fileList() { 1472 // pass 1473 return null; 1474 } 1475 1476 @Override getAssets()1477 public BridgeAssetManager getAssets() { 1478 return mAssets; 1479 } 1480 1481 @Override getCacheDir()1482 public File getCacheDir() { 1483 // pass 1484 return null; 1485 } 1486 1487 @Override getCodeCacheDir()1488 public File getCodeCacheDir() { 1489 // pass 1490 return null; 1491 } 1492 1493 @Override getExternalCacheDir()1494 public File getExternalCacheDir() { 1495 // pass 1496 return null; 1497 } 1498 1499 @Override getPreloadsFileCache()1500 public File getPreloadsFileCache() { 1501 // pass 1502 return null; 1503 } 1504 1505 @Override getContentResolver()1506 public ContentResolver getContentResolver() { 1507 if (mContentResolver == null) { 1508 mContentResolver = new BridgeContentResolver(this); 1509 } 1510 return mContentResolver; 1511 } 1512 1513 @Override getDatabasePath(String arg0)1514 public File getDatabasePath(String arg0) { 1515 // pass 1516 return null; 1517 } 1518 1519 @Override getDir(String arg0, int arg1)1520 public File getDir(String arg0, int arg1) { 1521 // pass 1522 return null; 1523 } 1524 1525 @Override getFileStreamPath(String arg0)1526 public File getFileStreamPath(String arg0) { 1527 // pass 1528 return null; 1529 } 1530 1531 @Override getSharedPreferencesPath(String name)1532 public File getSharedPreferencesPath(String name) { 1533 // pass 1534 return null; 1535 } 1536 1537 @Override getDataDir()1538 public File getDataDir() { 1539 // pass 1540 return null; 1541 } 1542 1543 @Override getFilesDir()1544 public File getFilesDir() { 1545 // pass 1546 return null; 1547 } 1548 1549 @Override getNoBackupFilesDir()1550 public File getNoBackupFilesDir() { 1551 // pass 1552 return null; 1553 } 1554 1555 @Override getExternalFilesDir(String type)1556 public File getExternalFilesDir(String type) { 1557 // pass 1558 return null; 1559 } 1560 1561 @Override getPackageCodePath()1562 public String getPackageCodePath() { 1563 // pass 1564 return null; 1565 } 1566 1567 @Override getBasePackageName()1568 public String getBasePackageName() { 1569 // pass 1570 return null; 1571 } 1572 1573 @Override getOpPackageName()1574 public String getOpPackageName() { 1575 // pass 1576 return null; 1577 } 1578 1579 @Override getApplicationInfo()1580 public ApplicationInfo getApplicationInfo() { 1581 return mApplicationInfo; 1582 } 1583 1584 @Override getPackageResourcePath()1585 public String getPackageResourcePath() { 1586 // pass 1587 return null; 1588 } 1589 1590 @Override getSharedPreferences(String arg0, int arg1)1591 public SharedPreferences getSharedPreferences(String arg0, int arg1) { 1592 if (mSharedPreferences == null) { 1593 mSharedPreferences = new BridgeSharedPreferences(); 1594 } 1595 return mSharedPreferences; 1596 } 1597 1598 @Override getSharedPreferences(File arg0, int arg1)1599 public SharedPreferences getSharedPreferences(File arg0, int arg1) { 1600 if (mSharedPreferences == null) { 1601 mSharedPreferences = new BridgeSharedPreferences(); 1602 } 1603 return mSharedPreferences; 1604 } 1605 1606 @Override reloadSharedPreferences()1607 public void reloadSharedPreferences() { 1608 // intentional noop 1609 } 1610 1611 @Override moveSharedPreferencesFrom(Context sourceContext, String name)1612 public boolean moveSharedPreferencesFrom(Context sourceContext, String name) { 1613 // pass 1614 return false; 1615 } 1616 1617 @Override deleteSharedPreferences(String name)1618 public boolean deleteSharedPreferences(String name) { 1619 // pass 1620 return false; 1621 } 1622 1623 @Override getWallpaper()1624 public Drawable getWallpaper() { 1625 // pass 1626 return null; 1627 } 1628 1629 @Override getWallpaperDesiredMinimumWidth()1630 public int getWallpaperDesiredMinimumWidth() { 1631 return -1; 1632 } 1633 1634 @Override getWallpaperDesiredMinimumHeight()1635 public int getWallpaperDesiredMinimumHeight() { 1636 return -1; 1637 } 1638 1639 @Override grantUriPermission(String arg0, Uri arg1, int arg2)1640 public void grantUriPermission(String arg0, Uri arg1, int arg2) { 1641 // pass 1642 1643 } 1644 1645 @Override openFileInput(String arg0)1646 public FileInputStream openFileInput(String arg0) throws FileNotFoundException { 1647 // pass 1648 return null; 1649 } 1650 1651 @Override openFileOutput(String arg0, int arg1)1652 public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { 1653 // pass 1654 return null; 1655 } 1656 1657 @Override openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2)1658 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { 1659 // pass 1660 return null; 1661 } 1662 1663 @Override openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2, DatabaseErrorHandler arg3)1664 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, 1665 CursorFactory arg2, DatabaseErrorHandler arg3) { 1666 // pass 1667 return null; 1668 } 1669 1670 @Override peekWallpaper()1671 public Drawable peekWallpaper() { 1672 // pass 1673 return null; 1674 } 1675 1676 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1)1677 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { 1678 // pass 1679 return null; 1680 } 1681 1682 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2)1683 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2) { 1684 // pass 1685 return null; 1686 } 1687 1688 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3)1689 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1690 String arg2, Handler arg3) { 1691 // pass 1692 return null; 1693 } 1694 1695 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3, int arg4)1696 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1697 String arg2, Handler arg3, int arg4) { 1698 // pass 1699 return null; 1700 } 1701 1702 @Override registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3)1703 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1704 IntentFilter arg1, String arg2, Handler arg3) { 1705 // pass 1706 return null; 1707 } 1708 1709 @Override registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3, int arg4)1710 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1711 IntentFilter arg1, String arg2, Handler arg3, int arg4) { 1712 // pass 1713 return null; 1714 } 1715 1716 @Override removeStickyBroadcast(Intent arg0)1717 public void removeStickyBroadcast(Intent arg0) { 1718 // pass 1719 1720 } 1721 1722 @Override revokeUriPermission(Uri arg0, int arg1)1723 public void revokeUriPermission(Uri arg0, int arg1) { 1724 // pass 1725 1726 } 1727 1728 @Override revokeUriPermission(String arg0, Uri arg1, int arg2)1729 public void revokeUriPermission(String arg0, Uri arg1, int arg2) { 1730 // pass 1731 1732 } 1733 1734 @Override sendBroadcast(Intent arg0)1735 public void sendBroadcast(Intent arg0) { 1736 // pass 1737 1738 } 1739 1740 @Override sendBroadcast(Intent arg0, String arg1)1741 public void sendBroadcast(Intent arg0, String arg1) { 1742 // pass 1743 1744 } 1745 1746 @Override sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)1747 public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { 1748 // pass 1749 1750 } 1751 1752 @Override sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions)1753 public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, 1754 String[] receiverPermissions) { 1755 // pass 1756 1757 } 1758 1759 @Override sendBroadcast(Intent arg0, String arg1, Bundle arg2)1760 public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) { 1761 // pass 1762 1763 } 1764 1765 @Override sendBroadcast(Intent intent, String receiverPermission, int appOp)1766 public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { 1767 // pass 1768 } 1769 1770 @Override sendOrderedBroadcast(Intent arg0, String arg1)1771 public void sendOrderedBroadcast(Intent arg0, String arg1) { 1772 // pass 1773 1774 } 1775 1776 @Override sendOrderedBroadcast(Intent arg0, String arg1, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1777 public void sendOrderedBroadcast(Intent arg0, String arg1, 1778 BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1779 Bundle arg6) { 1780 // pass 1781 1782 } 1783 1784 @Override sendOrderedBroadcast(Intent arg0, String arg1, Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1785 public void sendOrderedBroadcast(Intent arg0, String arg1, 1786 Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1787 Bundle arg6) { 1788 // pass 1789 1790 } 1791 1792 @Override sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1793 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 1794 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 1795 String initialData, Bundle initialExtras) { 1796 // pass 1797 } 1798 1799 @Override sendBroadcastAsUser(Intent intent, UserHandle user)1800 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1801 // pass 1802 } 1803 1804 @Override sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)1805 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1806 String receiverPermission) { 1807 // pass 1808 } 1809 1810 @Override sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options)1811 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1812 String receiverPermission, Bundle options) { 1813 // pass 1814 } 1815 sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp)1816 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1817 String receiverPermission, int appOp) { 1818 // pass 1819 } 1820 1821 @Override sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1822 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1823 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 1824 int initialCode, String initialData, Bundle initialExtras) { 1825 // pass 1826 } 1827 1828 @Override sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1829 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1830 String receiverPermission, int appOp, BroadcastReceiver resultReceiver, 1831 Handler scheduler, 1832 int initialCode, String initialData, Bundle initialExtras) { 1833 // pass 1834 } 1835 1836 @Override sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1837 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1838 String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, 1839 Handler scheduler, 1840 int initialCode, String initialData, Bundle initialExtras) { 1841 // pass 1842 } 1843 1844 @Override sendStickyBroadcast(Intent arg0)1845 public void sendStickyBroadcast(Intent arg0) { 1846 // pass 1847 1848 } 1849 1850 @Override sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1851 public void sendStickyOrderedBroadcast(Intent intent, 1852 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, 1853 Bundle initialExtras) { 1854 // pass 1855 } 1856 1857 @Override sendStickyBroadcastAsUser(Intent intent, UserHandle user)1858 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 1859 // pass 1860 } 1861 1862 @Override sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options)1863 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) { 1864 // pass 1865 } 1866 1867 @Override sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1868 public void sendStickyOrderedBroadcastAsUser(Intent intent, 1869 UserHandle user, BroadcastReceiver resultReceiver, 1870 Handler scheduler, int initialCode, String initialData, 1871 Bundle initialExtras) { 1872 // pass 1873 } 1874 1875 @Override removeStickyBroadcastAsUser(Intent intent, UserHandle user)1876 public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { 1877 // pass 1878 } 1879 1880 @Override setTheme(int arg0)1881 public void setTheme(int arg0) { 1882 // pass 1883 1884 } 1885 1886 @Override setWallpaper(Bitmap arg0)1887 public void setWallpaper(Bitmap arg0) throws IOException { 1888 // pass 1889 1890 } 1891 1892 @Override setWallpaper(InputStream arg0)1893 public void setWallpaper(InputStream arg0) throws IOException { 1894 // pass 1895 1896 } 1897 1898 @Override startActivity(Intent arg0)1899 public void startActivity(Intent arg0) { 1900 // pass 1901 } 1902 1903 @Override startActivity(Intent arg0, Bundle arg1)1904 public void startActivity(Intent arg0, Bundle arg1) { 1905 // pass 1906 } 1907 1908 @Override startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)1909 public void startIntentSender(IntentSender intent, 1910 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 1911 throws IntentSender.SendIntentException { 1912 // pass 1913 } 1914 1915 @Override startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)1916 public void startIntentSender(IntentSender intent, 1917 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1918 Bundle options) throws IntentSender.SendIntentException { 1919 // pass 1920 } 1921 1922 @Override startInstrumentation(ComponentName arg0, String arg1, Bundle arg2)1923 public boolean startInstrumentation(ComponentName arg0, String arg1, 1924 Bundle arg2) { 1925 // pass 1926 return false; 1927 } 1928 1929 @Override startService(Intent arg0)1930 public ComponentName startService(Intent arg0) { 1931 // pass 1932 return null; 1933 } 1934 1935 @Override startForegroundService(Intent service)1936 public ComponentName startForegroundService(Intent service) { 1937 // pass 1938 return null; 1939 } 1940 1941 @Override startForegroundServiceAsUser(Intent service, UserHandle user)1942 public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) { 1943 // pass 1944 return null; 1945 } 1946 1947 @Override stopService(Intent arg0)1948 public boolean stopService(Intent arg0) { 1949 // pass 1950 return false; 1951 } 1952 1953 @Override startServiceAsUser(Intent arg0, UserHandle arg1)1954 public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { 1955 // pass 1956 return null; 1957 } 1958 1959 @Override stopServiceAsUser(Intent arg0, UserHandle arg1)1960 public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { 1961 // pass 1962 return false; 1963 } 1964 1965 @Override updateServiceGroup(@onNull ServiceConnection conn, int group, int importance)1966 public void updateServiceGroup(@NonNull ServiceConnection conn, int group, 1967 int importance) { 1968 // pass 1969 } 1970 1971 @Override unbindService(ServiceConnection arg0)1972 public void unbindService(ServiceConnection arg0) { 1973 // pass 1974 1975 } 1976 1977 @Override unregisterReceiver(BroadcastReceiver arg0)1978 public void unregisterReceiver(BroadcastReceiver arg0) { 1979 // pass 1980 1981 } 1982 1983 @Override getApplicationContext()1984 public Context getApplicationContext() { 1985 return this; 1986 } 1987 1988 @Override startActivities(Intent[] arg0)1989 public void startActivities(Intent[] arg0) { 1990 // pass 1991 1992 } 1993 1994 @Override startActivities(Intent[] arg0, Bundle arg1)1995 public void startActivities(Intent[] arg0, Bundle arg1) { 1996 // pass 1997 1998 } 1999 2000 @Override isRestricted()2001 public boolean isRestricted() { 2002 return false; 2003 } 2004 2005 @Override getObbDir()2006 public File getObbDir() { 2007 Bridge.getLog().error(ILayoutLog.TAG_UNSUPPORTED, "OBB not supported", null, null); 2008 return null; 2009 } 2010 2011 @Override getDisplayAdjustments(int displayId)2012 public DisplayAdjustments getDisplayAdjustments(int displayId) { 2013 // pass 2014 return null; 2015 } 2016 2017 @Override getDisplay()2018 public Display getDisplay() { 2019 // pass 2020 return null; 2021 } 2022 2023 @Override getDisplayId()2024 public int getDisplayId() { 2025 // pass 2026 return 0; 2027 } 2028 2029 @Override updateDisplay(int displayId)2030 public void updateDisplay(int displayId) { 2031 // pass 2032 } 2033 2034 @Override getUserId()2035 public int getUserId() { 2036 return 0; // not used 2037 } 2038 2039 @Override getExternalFilesDirs(String type)2040 public File[] getExternalFilesDirs(String type) { 2041 // pass 2042 return new File[0]; 2043 } 2044 2045 @Override getObbDirs()2046 public File[] getObbDirs() { 2047 // pass 2048 return new File[0]; 2049 } 2050 2051 @Override getExternalCacheDirs()2052 public File[] getExternalCacheDirs() { 2053 // pass 2054 return new File[0]; 2055 } 2056 2057 @Override getExternalMediaDirs()2058 public File[] getExternalMediaDirs() { 2059 // pass 2060 return new File[0]; 2061 } 2062 setScrollYPos(@onNull View view, int scrollPos)2063 public void setScrollYPos(@NonNull View view, int scrollPos) { 2064 mScrollYPos.put(view, scrollPos); 2065 } 2066 getScrollYPos(@onNull View view)2067 public int getScrollYPos(@NonNull View view) { 2068 Integer pos = mScrollYPos.get(view); 2069 return pos != null ? pos : 0; 2070 } 2071 setScrollXPos(@onNull View view, int scrollPos)2072 public void setScrollXPos(@NonNull View view, int scrollPos) { 2073 mScrollXPos.put(view, scrollPos); 2074 } 2075 getScrollXPos(@onNull View view)2076 public int getScrollXPos(@NonNull View view) { 2077 Integer pos = mScrollXPos.get(view); 2078 return pos != null ? pos : 0; 2079 } 2080 2081 @Override createDeviceProtectedStorageContext()2082 public Context createDeviceProtectedStorageContext() { 2083 // pass 2084 return null; 2085 } 2086 2087 @Override createCredentialProtectedStorageContext()2088 public Context createCredentialProtectedStorageContext() { 2089 // pass 2090 return null; 2091 } 2092 2093 @Override isDeviceProtectedStorage()2094 public boolean isDeviceProtectedStorage() { 2095 return false; 2096 } 2097 2098 @Override isCredentialProtectedStorage()2099 public boolean isCredentialProtectedStorage() { 2100 return false; 2101 } 2102 2103 @Override canLoadUnsafeResources()2104 public boolean canLoadUnsafeResources() { 2105 return true; 2106 } 2107 2108 @Override isUiContext()2109 public boolean isUiContext() { 2110 return true; 2111 } 2112 putUserData(@onNull Key<T> key, @Nullable T data)2113 public <T> void putUserData(@NonNull Key<T> key, @Nullable T data) { 2114 mUserData.put(key, data); 2115 } 2116 2117 @SuppressWarnings("unchecked") 2118 @Nullable getUserData(@onNull Key<T> key)2119 public <T> T getUserData(@NonNull Key<T> key) { 2120 return (T) mUserData.get(key); 2121 } 2122 2123 /** Logs an error message to the error log of the host application. */ error(@onNull String message, @NonNull String... details)2124 public void error(@NonNull String message, @NonNull String... details) { 2125 mLayoutlibCallback.error(message, details); 2126 } 2127 2128 /** Logs an error message to the error log of the host application. */ error(@onNull String message, @Nullable Throwable t)2129 public void error(@NonNull String message, @Nullable Throwable t) { 2130 mLayoutlibCallback.error(message, t); 2131 } 2132 2133 /** Logs an error message to the error log of the host application. */ error(@onNull Throwable t)2134 public void error(@NonNull Throwable t) { 2135 mLayoutlibCallback.error(t); 2136 } 2137 2138 /** Logs a warning to the log of the host application. */ warn(@onNull String message, @Nullable Throwable t)2139 public void warn(@NonNull String message, @Nullable Throwable t) { 2140 mLayoutlibCallback.warn(message, t); 2141 } 2142 2143 /** Logs a warning to the log of the host application. */ warn(@onNull Throwable t)2144 public void warn(@NonNull Throwable t) { 2145 mLayoutlibCallback.warn(t); 2146 } 2147 2148 /** 2149 * No two Key instances are considered equal. 2150 * 2151 * @param <T> the type of values associated with the key 2152 */ 2153 public static final class Key<T> { 2154 private final String name; 2155 2156 @NonNull create(@onNull String name)2157 public static <T> Key<T> create(@NonNull String name) { 2158 return new Key<T>(name); 2159 } 2160 Key(@onNull String name)2161 private Key(@NonNull String name) { 2162 this.name = name; 2163 } 2164 2165 /** For debugging only. */ 2166 @Override toString()2167 public String toString() { 2168 return name; 2169 } 2170 } 2171 2172 private class AttributeHolder { 2173 private final int resourceId; 2174 @NonNull private final ResourceReference reference; 2175 AttributeHolder(int resourceId, @NonNull ResourceReference reference)2176 private AttributeHolder(int resourceId, @NonNull ResourceReference reference) { 2177 this.resourceId = resourceId; 2178 this.reference = reference; 2179 } 2180 2181 @NonNull asReference()2182 private ResourceReference asReference() { 2183 return reference; 2184 } 2185 getResourceId()2186 private int getResourceId() { 2187 return resourceId; 2188 } 2189 2190 @NonNull getName()2191 private String getName() { 2192 return reference.getName(); 2193 } 2194 2195 @NonNull getNamespace()2196 private ResourceNamespace getNamespace() { 2197 return reference.getNamespace(); 2198 } 2199 } 2200 2201 /** 2202 * The cached value depends on 2203 * <ol> 2204 * <li>{@code int[]}: the attributes for which TypedArray is created </li> 2205 * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of 2206 * creation of the TypedArray</li> 2207 * <li>{@code Integer}: the default style used at the time of creation</li> 2208 * </ol> 2209 * 2210 * The class is created by using nested maps resolving one dependency at a time. 2211 * <p/> 2212 * The final value of the nested maps is a pair of the typed array and a map of properties 2213 * that should be added to {@link #mDefaultPropMaps}, if needed. 2214 */ 2215 private static class TypedArrayCache { 2216 2217 private Map<int[], 2218 Map<List<StyleResourceValue>, 2219 Map<Integer, Pair<BridgeTypedArray, 2220 Map<ResourceReference, ResourceValue>>>>> mCache; 2221 TypedArrayCache()2222 private TypedArrayCache() { 2223 mCache = new IdentityHashMap<>(); 2224 } 2225 get(int[] attrs, List<StyleResourceValue> themes, int resId)2226 public Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> get(int[] attrs, 2227 List<StyleResourceValue> themes, int resId) { 2228 Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, 2229 ResourceValue>>>> 2230 cacheFromThemes = mCache.get(attrs); 2231 if (cacheFromThemes != null) { 2232 Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>>> cacheFromResId = 2233 cacheFromThemes.get(themes); 2234 if (cacheFromResId != null) { 2235 return cacheFromResId.get(resId); 2236 } 2237 } 2238 return null; 2239 } 2240 put(int[] attrs, List<StyleResourceValue> themes, int resId, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> value)2241 public void put(int[] attrs, List<StyleResourceValue> themes, int resId, 2242 Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> value) { 2243 Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, 2244 ResourceValue>>>> 2245 cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>()); 2246 Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>>> cacheFromResId = 2247 cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>()); 2248 cacheFromResId.put(resId, value); 2249 } 2250 2251 } 2252 2253 @NotNull getSessionInteractiveData()2254 public SessionInteractiveData getSessionInteractiveData() { 2255 return mSessionInteractiveData; 2256 } 2257 } 2258