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