BridgeContext.java revision 6a6cdafaec56fcd793214678c7fcc52f0b860cfc
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 17package com.android.layoutlib.bridge.android; 18 19import com.android.SdkConstants; 20import com.android.ide.common.rendering.api.AssetRepository; 21import com.android.ide.common.rendering.api.ILayoutPullParser; 22import com.android.ide.common.rendering.api.LayoutLog; 23import com.android.ide.common.rendering.api.LayoutlibCallback; 24import com.android.ide.common.rendering.api.RenderResources; 25import com.android.ide.common.rendering.api.ResourceReference; 26import com.android.ide.common.rendering.api.ResourceValue; 27import com.android.ide.common.rendering.api.StyleResourceValue; 28import com.android.layoutlib.bridge.Bridge; 29import com.android.layoutlib.bridge.BridgeConstants; 30import com.android.layoutlib.bridge.android.view.WindowManagerImpl; 31import com.android.layoutlib.bridge.impl.ParserFactory; 32import com.android.layoutlib.bridge.impl.Stack; 33import com.android.resources.ResourceType; 34import com.android.util.Pair; 35 36import org.xmlpull.v1.XmlPullParser; 37import org.xmlpull.v1.XmlPullParserException; 38 39import android.annotation.NonNull; 40import android.annotation.Nullable; 41import android.content.BroadcastReceiver; 42import android.content.ComponentName; 43import android.content.ContentResolver; 44import android.content.Context; 45import android.content.ContextWrapper; 46import android.content.Intent; 47import android.content.IntentFilter; 48import android.content.IntentSender; 49import android.content.ServiceConnection; 50import android.content.SharedPreferences; 51import android.content.pm.ApplicationInfo; 52import android.content.pm.PackageManager; 53import android.content.res.AssetManager; 54import android.content.res.BridgeAssetManager; 55import android.content.res.BridgeResources; 56import android.content.res.BridgeTypedArray; 57import android.content.res.Configuration; 58import android.content.res.Resources; 59import android.content.res.Resources.Theme; 60import android.database.DatabaseErrorHandler; 61import android.database.sqlite.SQLiteDatabase; 62import android.database.sqlite.SQLiteDatabase.CursorFactory; 63import android.graphics.Bitmap; 64import android.graphics.drawable.Drawable; 65import android.hardware.display.DisplayManager; 66import android.net.Uri; 67import android.os.Build.VERSION_CODES; 68import android.os.Bundle; 69import android.os.Handler; 70import android.os.IBinder; 71import android.os.IInterface; 72import android.os.Looper; 73import android.os.Parcel; 74import android.os.PowerManager; 75import android.os.RemoteException; 76import android.os.ResultReceiver; 77import android.os.UserHandle; 78import android.util.AttributeSet; 79import android.util.DisplayMetrics; 80import android.util.TypedValue; 81import android.view.BridgeInflater; 82import android.view.Display; 83import android.view.DisplayAdjustments; 84import android.view.LayoutInflater; 85import android.view.View; 86import android.view.ViewGroup; 87import android.view.WindowManager; 88import android.view.accessibility.AccessibilityManager; 89import android.view.textservice.TextServicesManager; 90 91import java.io.File; 92import java.io.FileDescriptor; 93import java.io.FileInputStream; 94import java.io.FileNotFoundException; 95import java.io.FileOutputStream; 96import java.io.IOException; 97import java.io.InputStream; 98import java.util.ArrayList; 99import java.util.HashMap; 100import java.util.IdentityHashMap; 101import java.util.List; 102import java.util.Map; 103 104import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; 105 106/** 107 * Custom implementation of Context/Activity to handle non compiled resources. 108 */ 109@SuppressWarnings("deprecation") // For use of Pair. 110public final class BridgeContext extends Context { 111 112 /** The map adds cookies to each view so that IDE can link xml tags to views. */ 113 private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>(); 114 /** 115 * In some cases, when inflating an xml, some objects are created. Then later, the objects are 116 * converted to views. This map stores the mapping from objects to cookies which can then be 117 * used to populate the mViewKeyMap. 118 */ 119 private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>(); 120 private final BridgeAssetManager mAssets; 121 private Resources mSystemResources; 122 private final Object mProjectKey; 123 private final DisplayMetrics mMetrics; 124 private final RenderResources mRenderResources; 125 private final Configuration mConfig; 126 private final ApplicationInfo mApplicationInfo; 127 private final LayoutlibCallback mLayoutlibCallback; 128 private final WindowManager mWindowManager; 129 private final DisplayManager mDisplayManager; 130 private final HashMap<View, Integer> mScrollYPos = new HashMap<View, Integer>(); 131 132 private Resources.Theme mTheme; 133 134 private final Map<Object, Map<String, String>> mDefaultPropMaps = 135 new IdentityHashMap<Object, Map<String,String>>(); 136 137 // maps for dynamically generated id representing style objects (StyleResourceValue) 138 @Nullable 139 private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; 140 private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; 141 private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace 142 143 // cache for TypedArray generated from StyleResourceValue object 144 private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>> 145 mTypedArrayCache; 146 private BridgeInflater mBridgeInflater; 147 148 private BridgeContentResolver mContentResolver; 149 150 private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); 151 private SharedPreferences mSharedPreferences; 152 private ClassLoader mClassLoader; 153 private IBinder mBinder; 154 private PackageManager mPackageManager; 155 156 157 /** 158 * Some applications that target both pre API 17 and post API 17, set the newer attrs to 159 * reference the older ones. For example, android:paddingStart will resolve to 160 * android:paddingLeft. This way the apps need to only define paddingLeft at any other place. 161 * This a map from value to attribute name. Warning for missing references shouldn't be logged 162 * if value and attr name pair is the same as an entry in this map. 163 */ 164 private static Map<String, String> RTL_ATTRS = new HashMap<String, String>(10); 165 166 static { 167 RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart"); 168 RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd"); 169 RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart"); 170 RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd"); 171 RTL_ATTRS.put("?android:attr/layout_toLeft", "layout_toStartOf"); 172 RTL_ATTRS.put("?android:attr/layout_toRight", "layout_toEndOf"); 173 RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart"); 174 RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd"); 175 RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart"); 176 RTL_ATTRS.put("?android:attr/drawableRight", "drawableEnd"); 177 } 178 179 /** 180 * @param projectKey An Object identifying the project. This is used for the cache mechanism. 181 * @param metrics the {@link DisplayMetrics}. 182 * @param renderResources the configured resources (both framework and projects) for this 183 * render. 184 * @param config the Configuration object for this render. 185 * @param targetSdkVersion the targetSdkVersion of the application. 186 */ 187 public BridgeContext(Object projectKey, DisplayMetrics metrics, 188 RenderResources renderResources, 189 AssetRepository assets, 190 LayoutlibCallback layoutlibCallback, 191 Configuration config, 192 int targetSdkVersion, 193 boolean hasRtlSupport) { 194 mProjectKey = projectKey; 195 mMetrics = metrics; 196 mLayoutlibCallback = layoutlibCallback; 197 198 mRenderResources = renderResources; 199 mConfig = config; 200 mAssets = new BridgeAssetManager(); 201 mAssets.setAssetRepository(assets); 202 203 mApplicationInfo = new ApplicationInfo(); 204 mApplicationInfo.targetSdkVersion = targetSdkVersion; 205 if (hasRtlSupport) { 206 mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL; 207 } 208 209 mWindowManager = new WindowManagerImpl(mMetrics); 210 mDisplayManager = new DisplayManager(this); 211 } 212 213 /** 214 * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its 215 * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}. 216 * 217 * @see #disposeResources() 218 */ 219 public void initResources() { 220 AssetManager assetManager = AssetManager.getSystem(); 221 222 mSystemResources = BridgeResources.initSystem( 223 this, 224 assetManager, 225 mMetrics, 226 mConfig, 227 mLayoutlibCallback); 228 mTheme = mSystemResources.newTheme(); 229 } 230 231 /** 232 * Disposes the {@link Resources} singleton. 233 */ 234 public void disposeResources() { 235 BridgeResources.disposeSystem(); 236 } 237 238 public void setBridgeInflater(BridgeInflater inflater) { 239 mBridgeInflater = inflater; 240 } 241 242 public void addViewKey(View view, Object viewKey) { 243 mViewKeyMap.put(view, viewKey); 244 } 245 246 public Object getViewKey(View view) { 247 return mViewKeyMap.get(view); 248 } 249 250 public void addCookie(Object o, Object cookie) { 251 mViewKeyHelpMap.put(o, cookie); 252 } 253 254 public Object getCookie(Object o) { 255 return mViewKeyHelpMap.get(o); 256 } 257 258 public Object getProjectKey() { 259 return mProjectKey; 260 } 261 262 public DisplayMetrics getMetrics() { 263 return mMetrics; 264 } 265 266 public LayoutlibCallback getLayoutlibCallback() { 267 return mLayoutlibCallback; 268 } 269 270 public RenderResources getRenderResources() { 271 return mRenderResources; 272 } 273 274 public Map<String, String> getDefaultPropMap(Object key) { 275 return mDefaultPropMaps.get(key); 276 } 277 278 public Configuration getConfiguration() { 279 return mConfig; 280 } 281 282 /** 283 * Adds a parser to the stack. 284 * @param parser the parser to add. 285 */ 286 public void pushParser(BridgeXmlBlockParser parser) { 287 if (ParserFactory.LOG_PARSER) { 288 System.out.println("PUSH " + parser.getParser().toString()); 289 } 290 mParserStack.push(parser); 291 } 292 293 /** 294 * Removes the parser at the top of the stack 295 */ 296 public void popParser() { 297 BridgeXmlBlockParser parser = mParserStack.pop(); 298 if (ParserFactory.LOG_PARSER) { 299 System.out.println("POPD " + parser.getParser().toString()); 300 } 301 } 302 303 /** 304 * Returns the current parser at the top the of the stack. 305 * @return a parser or null. 306 */ 307 public BridgeXmlBlockParser getCurrentParser() { 308 return mParserStack.peek(); 309 } 310 311 /** 312 * Returns the previous parser. 313 * @return a parser or null if there isn't any previous parser 314 */ 315 public BridgeXmlBlockParser getPreviousParser() { 316 if (mParserStack.size() < 2) { 317 return null; 318 } 319 return mParserStack.get(mParserStack.size() - 2); 320 } 321 322 public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { 323 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); 324 boolean isFrameworkRes = true; 325 if (resourceInfo == null) { 326 resourceInfo = mLayoutlibCallback.resolveResourceId(resid); 327 isFrameworkRes = false; 328 } 329 330 if (resourceInfo == null) { 331 return false; 332 } 333 334 ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), 335 isFrameworkRes); 336 if (resolveRefs) { 337 value = mRenderResources.resolveResValue(value); 338 } 339 340 if (value == null) { 341 // unable to find the attribute. 342 return false; 343 } 344 345 // check if this is a style resource 346 if (value instanceof StyleResourceValue) { 347 // get the id that will represent this style. 348 outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value); 349 return true; 350 } 351 352 int a; 353 // if this is a framework value. 354 if (value.isFramework()) { 355 // look for idName in the android R classes. 356 // use 0 a default res value as it's not a valid id value. 357 a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 358 } else { 359 // look for idName in the project R class. 360 // use 0 a default res value as it's not a valid id value. 361 a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 362 } 363 364 if (a != 0) { 365 outValue.resourceId = a; 366 return true; 367 } 368 369 return false; 370 } 371 372 373 public ResourceReference resolveId(int id) { 374 // first get the String related to this id in the framework 375 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); 376 377 if (resourceInfo != null) { 378 return new ResourceReference(resourceInfo.getSecond(), true); 379 } 380 381 // didn't find a match in the framework? look in the project. 382 if (mLayoutlibCallback != null) { 383 resourceInfo = mLayoutlibCallback.resolveResourceId(id); 384 385 if (resourceInfo != null) { 386 return new ResourceReference(resourceInfo.getSecond(), false); 387 } 388 } 389 390 // The base value for R.style is 0x01030000 and the custom style is 0x02030000. 391 // So, if the second byte is 03, it's probably a style. 392 if ((id >> 16 & 0xFF) == 0x03) { 393 return getStyleByDynamicId(id); 394 } 395 return null; 396 } 397 398 public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, 399 boolean attachToRoot, boolean skipCallbackParser) { 400 boolean isPlatformLayout = resource.isFramework(); 401 402 if (!isPlatformLayout && !skipCallbackParser) { 403 // check if the project callback can provide us with a custom parser. 404 ILayoutPullParser parser = getParser(resource); 405 406 if (parser != null) { 407 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 408 this, resource.isFramework()); 409 try { 410 pushParser(blockParser); 411 return Pair.of( 412 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 413 Boolean.TRUE); 414 } finally { 415 popParser(); 416 } 417 } 418 } 419 420 ResourceValue resValue; 421 if (resource instanceof ResourceValue) { 422 resValue = (ResourceValue) resource; 423 } else { 424 if (isPlatformLayout) { 425 resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT, 426 resource.getName()); 427 } else { 428 resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT, 429 resource.getName()); 430 } 431 } 432 433 if (resValue != null) { 434 435 File xml = new File(resValue.getValue()); 436 if (xml.isFile()) { 437 // we need to create a pull parser around the layout XML file, and then 438 // give that to our XmlBlockParser 439 try { 440 XmlPullParser parser = ParserFactory.create(xml, true); 441 442 // set the resource ref to have correct view cookies 443 mBridgeInflater.setResourceReference(resource); 444 445 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 446 this, resource.isFramework()); 447 try { 448 pushParser(blockParser); 449 return Pair.of( 450 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 451 Boolean.FALSE); 452 } finally { 453 popParser(); 454 } 455 } catch (XmlPullParserException e) { 456 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 457 "Failed to configure parser for " + xml, e, null /*data*/); 458 // we'll return null below. 459 } catch (FileNotFoundException e) { 460 // this shouldn't happen since we check above. 461 } finally { 462 mBridgeInflater.setResourceReference(null); 463 } 464 } else { 465 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 466 String.format("File %s is missing!", xml), null); 467 } 468 } else { 469 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 470 String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", 471 resource.getName()), null); 472 } 473 474 return Pair.of(null, Boolean.FALSE); 475 } 476 477 @SuppressWarnings("deprecation") 478 private ILayoutPullParser getParser(ResourceReference resource) { 479 ILayoutPullParser parser; 480 if (resource instanceof ResourceValue) { 481 parser = mLayoutlibCallback.getParser((ResourceValue) resource); 482 } else { 483 parser = mLayoutlibCallback.getParser(resource.getName()); 484 } 485 return parser; 486 } 487 488 // ------------ Context methods 489 490 @Override 491 public Resources getResources() { 492 return mSystemResources; 493 } 494 495 @Override 496 public Theme getTheme() { 497 return mTheme; 498 } 499 500 @Override 501 public ClassLoader getClassLoader() { 502 // The documentation for this method states that it should return a class loader one can 503 // use to retrieve classes in this package. However, when called by LayoutInflater, we do 504 // not want the class loader to return app's custom views. 505 // This is so that the IDE can instantiate the custom views and also generate proper error 506 // messages in case of failure. This also enables the IDE to fallback to MockView in case 507 // there's an exception thrown when trying to inflate the custom view. 508 // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to 509 // replace invocations of this method to a new method: getFrameworkClassLoader(). Also, 510 // the method is injected into Context. The implementation of getFrameworkClassLoader() is: 511 // "return getClass().getClassLoader();". This means that when LayoutInflater asks for 512 // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have 513 // access to the apps's custom views. 514 // This method can now return the right ClassLoader, which CustomViews can use to do the 515 // right thing. 516 if (mClassLoader == null) { 517 mClassLoader = new ClassLoader(getClass().getClassLoader()) { 518 @Override 519 protected Class<?> findClass(String name) throws ClassNotFoundException { 520 for (String prefix : BridgeInflater.getClassPrefixList()) { 521 if (name.startsWith(prefix)) { 522 // These are framework classes and should not be loaded from the app. 523 throw new ClassNotFoundException(name + " not found"); 524 } 525 } 526 return BridgeContext.this.mLayoutlibCallback.findClass(name); 527 } 528 }; 529 } 530 return mClassLoader; 531 } 532 533 @Override 534 public Object getSystemService(String service) { 535 if (LAYOUT_INFLATER_SERVICE.equals(service)) { 536 return mBridgeInflater; 537 } 538 539 if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) { 540 // we need to return a valid service to avoid NPE 541 return TextServicesManager.getInstance(); 542 } 543 544 if (WINDOW_SERVICE.equals(service)) { 545 return mWindowManager; 546 } 547 548 // needed by SearchView 549 if (INPUT_METHOD_SERVICE.equals(service)) { 550 return null; 551 } 552 553 if (POWER_SERVICE.equals(service)) { 554 return new PowerManager(this, new BridgePowerManager(), new Handler()); 555 } 556 557 if (DISPLAY_SERVICE.equals(service)) { 558 return mDisplayManager; 559 } 560 561 if (ACCESSIBILITY_SERVICE.equals(service)) { 562 return AccessibilityManager.getInstance(this); 563 } 564 565 throw new UnsupportedOperationException("Unsupported Service: " + service); 566 } 567 568 @Override 569 public String getSystemServiceName(Class<?> serviceClass) { 570 if (serviceClass.equals(LayoutInflater.class)) { 571 return LAYOUT_INFLATER_SERVICE; 572 } 573 574 if (serviceClass.equals(TextServicesManager.class)) { 575 return TEXT_SERVICES_MANAGER_SERVICE; 576 } 577 578 if (serviceClass.equals(WindowManager.class)) { 579 return WINDOW_SERVICE; 580 } 581 582 if (serviceClass.equals(PowerManager.class)) { 583 return POWER_SERVICE; 584 } 585 586 if (serviceClass.equals(DisplayManager.class)) { 587 return DISPLAY_SERVICE; 588 } 589 590 if (serviceClass.equals(AccessibilityManager.class)) { 591 return ACCESSIBILITY_SERVICE; 592 } 593 594 throw new UnsupportedOperationException("Unsupported Service: " + serviceClass); 595 } 596 597 @Override 598 public final BridgeTypedArray obtainStyledAttributes(int[] attrs) { 599 // No style is specified here, so create the typed array based on the default theme 600 // and the styles already applied to it. A null value of style indicates that the default 601 // theme should be used. 602 return createStyleBasedTypedArray(null, attrs); 603 } 604 605 @Override 606 public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs) 607 throws Resources.NotFoundException { 608 StyleResourceValue style = null; 609 // get the StyleResourceValue based on the resId; 610 if (resid != 0) { 611 style = getStyleByDynamicId(resid); 612 613 if (style == null) { 614 // In some cases, style may not be a dynamic id, so we do a full search. 615 ResourceReference ref = resolveId(resid); 616 if (ref != null) { 617 style = mRenderResources.getStyle(ref.getName(), ref.isFramework()); 618 } 619 } 620 621 if (style == null) { 622 throw new Resources.NotFoundException(); 623 } 624 } 625 626 // The map is from 627 // attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array. 628 if (mTypedArrayCache == null) { 629 mTypedArrayCache = new IdentityHashMap<int[], 630 Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>(); 631 } 632 633 // get the 2nd map 634 Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 = 635 mTypedArrayCache.get(attrs); 636 if (map2 == null) { 637 map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>(); 638 mTypedArrayCache.put(attrs, map2); 639 } 640 641 // get the 3rd map 642 List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes(); 643 Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes); 644 if (map3 == null) { 645 map3 = new HashMap<Integer, BridgeTypedArray>(); 646 // Create a copy of the list before adding it to the map. This allows reusing the 647 // existing list. 648 currentThemes = new ArrayList<StyleResourceValue>(currentThemes); 649 map2.put(currentThemes, map3); 650 } 651 652 // get the array from the 3rd map 653 BridgeTypedArray ta = map3.get(resid); 654 655 if (ta == null) { 656 ta = createStyleBasedTypedArray(style, attrs); 657 map3.put(resid, ta); 658 } 659 660 return ta; 661 } 662 663 @Override 664 public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { 665 return obtainStyledAttributes(set, attrs, 0, 0); 666 } 667 668 @Override 669 public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, 670 int defStyleAttr, int defStyleRes) { 671 672 Map<String, String> defaultPropMap = null; 673 boolean isPlatformFile = true; 674 675 // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java 676 if (set instanceof BridgeXmlBlockParser) { 677 BridgeXmlBlockParser parser; 678 parser = (BridgeXmlBlockParser)set; 679 680 isPlatformFile = parser.isPlatformFile(); 681 682 Object key = parser.getViewCookie(); 683 if (key != null) { 684 defaultPropMap = mDefaultPropMaps.get(key); 685 if (defaultPropMap == null) { 686 defaultPropMap = new HashMap<String, String>(); 687 mDefaultPropMaps.put(key, defaultPropMap); 688 } 689 } 690 691 } else if (set instanceof BridgeLayoutParamsMapAttributes) { 692 // this is only for temp layout params generated dynamically, so this is never 693 // platform content. 694 isPlatformFile = false; 695 } else if (set != null) { // null parser is ok 696 // really this should not be happening since its instantiated in Bridge 697 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 698 "Parser is not a BridgeXmlBlockParser!", null); 699 return null; 700 } 701 702 List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); 703 704 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 705 isPlatformFile); 706 707 // look for a custom style. 708 String customStyle = null; 709 if (set != null) { 710 customStyle = set.getAttributeValue(null, "style"); 711 } 712 713 StyleResourceValue customStyleValues = null; 714 if (customStyle != null) { 715 ResourceValue item = mRenderResources.findResValue(customStyle, 716 isPlatformFile /*forceFrameworkOnly*/); 717 718 // resolve it in case it links to something else 719 item = mRenderResources.resolveResValue(item); 720 721 if (item instanceof StyleResourceValue) { 722 customStyleValues = (StyleResourceValue)item; 723 } 724 } 725 726 // resolve the defStyleAttr value into a IStyleResourceValue 727 StyleResourceValue defStyleValues = null; 728 729 if (defStyleAttr != 0) { 730 // get the name from the int. 731 Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); 732 733 if (defStyleAttribute == null) { 734 // This should be rare. Happens trying to map R.style.foo to @style/foo fails. 735 // This will happen if the user explicitly used a non existing int value for 736 // defStyleAttr or there's something wrong with the project structure/build. 737 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, 738 "Failed to find the style corresponding to the id " + defStyleAttr, null); 739 } else { 740 if (defaultPropMap != null) { 741 String defStyleName = defStyleAttribute.getFirst(); 742 if (defStyleAttribute.getSecond()) { 743 defStyleName = "android:" + defStyleName; 744 } 745 defaultPropMap.put("style", defStyleName); 746 } 747 748 // look for the style in the current theme, and its parent: 749 ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(), 750 defStyleAttribute.getSecond()); 751 752 if (item != null) { 753 // item is a reference to a style entry. Search for it. 754 item = mRenderResources.findResValue(item.getValue(), item.isFramework()); 755 item = mRenderResources.resolveResValue(item); 756 if (item instanceof StyleResourceValue) { 757 defStyleValues = (StyleResourceValue) item; 758 } 759 } else { 760 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 761 String.format( 762 "Failed to find style '%s' in current theme", 763 defStyleAttribute.getFirst()), 764 null); 765 } 766 } 767 } else if (defStyleRes != 0) { 768 StyleResourceValue item = getStyleByDynamicId(defStyleRes); 769 if (item != null) { 770 defStyleValues = item; 771 } else { 772 boolean isFrameworkRes = true; 773 Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); 774 if (value == null) { 775 value = mLayoutlibCallback.resolveResourceId(defStyleRes); 776 isFrameworkRes = false; 777 } 778 779 if (value != null) { 780 if ((value.getFirst() == ResourceType.STYLE)) { 781 // look for the style in all resources: 782 item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes); 783 if (item != null) { 784 if (defaultPropMap != null) { 785 defaultPropMap.put("style", item.getName()); 786 } 787 788 defStyleValues = item; 789 } else { 790 Bridge.getLog().error(null, 791 String.format( 792 "Style with id 0x%x (resolved to '%s') does not exist.", 793 defStyleRes, value.getSecond()), 794 null); 795 } 796 } else { 797 Bridge.getLog().error(null, 798 String.format( 799 "Resource id 0x%x is not of type STYLE (instead %s)", 800 defStyleRes, value.getFirst().toString()), 801 null); 802 } 803 } else { 804 Bridge.getLog().error(null, 805 String.format( 806 "Failed to find style with id 0x%x in current theme", 807 defStyleRes), 808 null); 809 } 810 } 811 } 812 813 String appNamespace = mLayoutlibCallback.getNamespace(); 814 815 if (attributeList != null) { 816 for (int index = 0 ; index < attributeList.size() ; index++) { 817 Pair<String, Boolean> attribute = attributeList.get(index); 818 819 if (attribute == null) { 820 continue; 821 } 822 823 String attrName = attribute.getFirst(); 824 boolean frameworkAttr = attribute.getSecond(); 825 String value = null; 826 if (set != null) { 827 value = set.getAttributeValue( 828 frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, 829 attrName); 830 831 // if this is an app attribute, and the first get fails, try with the 832 // new res-auto namespace as well 833 if (!frameworkAttr && value == null) { 834 value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); 835 } 836 } 837 838 // if there's no direct value for this attribute in the XML, we look for default 839 // values in the widget defStyle, and then in the theme. 840 if (value == null) { 841 ResourceValue resValue = null; 842 843 // look for the value in the custom style first (and its parent if needed) 844 if (customStyleValues != null) { 845 resValue = mRenderResources.findItemInStyle(customStyleValues, 846 attrName, frameworkAttr); 847 } 848 849 // then look for the value in the default Style (and its parent if needed) 850 if (resValue == null && defStyleValues != null) { 851 resValue = mRenderResources.findItemInStyle(defStyleValues, 852 attrName, frameworkAttr); 853 } 854 855 // if the item is not present in the defStyle, we look in the main theme (and 856 // its parent themes) 857 if (resValue == null) { 858 resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); 859 } 860 861 // if we found a value, we make sure this doesn't reference another value. 862 // So we resolve it. 863 if (resValue != null) { 864 // put the first default value, before the resolution. 865 if (defaultPropMap != null) { 866 defaultPropMap.put(attrName, resValue.getValue()); 867 } 868 869 resValue = mRenderResources.resolveResValue(resValue); 870 871 // If the value is a reference to another theme attribute that doesn't 872 // exist, we should log a warning and omit it. 873 String val = resValue.getValue(); 874 if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) { 875 if (!attrName.equals(RTL_ATTRS.get(val)) || 876 getApplicationInfo().targetSdkVersion < 877 VERSION_CODES.JELLY_BEAN_MR1) { 878 // Only log a warning if the referenced value isn't one of the RTL 879 // attributes, or the app targets old API. 880 Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 881 String.format("Failed to find '%s' in current theme.", val), 882 val); 883 } 884 resValue = null; 885 } 886 } 887 888 ta.bridgeSetValue(index, attrName, frameworkAttr, resValue); 889 } else { 890 // there is a value in the XML, but we need to resolve it in case it's 891 // referencing another resource or a theme value. 892 ta.bridgeSetValue(index, attrName, frameworkAttr, 893 mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); 894 } 895 } 896 } 897 898 ta.sealArray(); 899 900 return ta; 901 } 902 903 @Override 904 public Looper getMainLooper() { 905 return Looper.myLooper(); 906 } 907 908 909 @Override 910 public String getPackageName() { 911 if (mApplicationInfo.packageName == null) { 912 mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE); 913 } 914 return mApplicationInfo.packageName; 915 } 916 917 @Override 918 public PackageManager getPackageManager() { 919 if (mPackageManager == null) { 920 mPackageManager = new BridgePackageManager(); 921 } 922 return mPackageManager; 923 } 924 925 // ------------- private new methods 926 927 /** 928 * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the 929 * values found in the given style. If no style is specified, the default theme, along with the 930 * styles applied to it are used. 931 * 932 * @see #obtainStyledAttributes(int, int[]) 933 */ 934 private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style, 935 int[] attrs) throws Resources.NotFoundException { 936 937 List<Pair<String, Boolean>> attributes = searchAttrs(attrs); 938 939 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 940 false); 941 942 // for each attribute, get its name so that we can search it in the style 943 for (int i = 0 ; i < attrs.length ; i++) { 944 Pair<String, Boolean> attribute = attributes.get(i); 945 946 if (attribute != null) { 947 // look for the value in the given style 948 ResourceValue resValue; 949 if (style != null) { 950 resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(), 951 attribute.getSecond()); 952 } else { 953 resValue = mRenderResources.findItemInTheme(attribute.getFirst(), 954 attribute.getSecond()); 955 } 956 957 if (resValue != null) { 958 // resolve it to make sure there are no references left. 959 ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), 960 mRenderResources.resolveResValue(resValue)); 961 } 962 } 963 } 964 965 ta.sealArray(); 966 967 return ta; 968 } 969 970 /** 971 * The input int[] attrs is a list of attributes. The returns a list of information about 972 * each attributes. The information is (name, isFramework) 973 * <p/> 974 * 975 * @param attrs An attribute array reference given to obtainStyledAttributes. 976 * @return List of attribute information. 977 */ 978 private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { 979 List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); 980 981 // for each attribute, get its name so that we can search it in the style 982 for (int attr : attrs) { 983 Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr); 984 boolean isFramework = false; 985 if (resolvedResource != null) { 986 isFramework = true; 987 } else { 988 resolvedResource = mLayoutlibCallback.resolveResourceId(attr); 989 } 990 991 if (resolvedResource != null) { 992 results.add(Pair.of(resolvedResource.getSecond(), isFramework)); 993 } else { 994 results.add(null); 995 } 996 } 997 998 return results; 999 } 1000 1001 /** 1002 * Searches for the attribute referenced by its internal id. 1003 * 1004 * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. 1005 * @return A (name, isFramework) pair describing the attribute if found. Returns null 1006 * if nothing is found. 1007 */ 1008 public Pair<String, Boolean> searchAttr(int attr) { 1009 Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); 1010 if (info != null) { 1011 return Pair.of(info.getSecond(), Boolean.TRUE); 1012 } 1013 1014 info = mLayoutlibCallback.resolveResourceId(attr); 1015 if (info != null) { 1016 return Pair.of(info.getSecond(), Boolean.FALSE); 1017 } 1018 1019 return null; 1020 } 1021 1022 public int getDynamicIdByStyle(StyleResourceValue resValue) { 1023 if (mDynamicIdToStyleMap == null) { 1024 // create the maps. 1025 mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>(); 1026 mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>(); 1027 } 1028 1029 // look for an existing id 1030 Integer id = mStyleToDynamicIdMap.get(resValue); 1031 1032 if (id == null) { 1033 // generate a new id 1034 id = ++mDynamicIdGenerator; 1035 1036 // and add it to the maps. 1037 mDynamicIdToStyleMap.put(id, resValue); 1038 mStyleToDynamicIdMap.put(resValue, id); 1039 } 1040 1041 return id; 1042 } 1043 1044 private StyleResourceValue getStyleByDynamicId(int i) { 1045 if (mDynamicIdToStyleMap != null) { 1046 return mDynamicIdToStyleMap.get(i); 1047 } 1048 1049 return null; 1050 } 1051 1052 public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) { 1053 if (getRenderResources().getFrameworkResource(resType, resName) != null) { 1054 // Bridge.getResourceId creates a new resource id if an existing one isn't found. So, 1055 // we check for the existence of the resource before calling it. 1056 return Bridge.getResourceId(resType, resName); 1057 } 1058 1059 return defValue; 1060 } 1061 1062 public int getProjectResourceValue(ResourceType resType, String resName, int defValue) { 1063 // getResourceId creates a new resource id if an existing resource id isn't found. So, we 1064 // check for the existence of the resource before calling it. 1065 if (getRenderResources().getProjectResource(resType, resName) != null) { 1066 if (mLayoutlibCallback != null) { 1067 Integer value = mLayoutlibCallback.getResourceId(resType, resName); 1068 if (value != null) { 1069 return value; 1070 } 1071 } 1072 } 1073 1074 return defValue; 1075 } 1076 1077 public static Context getBaseContext(Context context) { 1078 while (context instanceof ContextWrapper) { 1079 context = ((ContextWrapper) context).getBaseContext(); 1080 } 1081 return context; 1082 } 1083 1084 public IBinder getBinder() { 1085 if (mBinder == null) { 1086 // create a dummy binder. We only need it be not null. 1087 mBinder = new IBinder() { 1088 @Override 1089 public String getInterfaceDescriptor() throws RemoteException { 1090 return null; 1091 } 1092 1093 @Override 1094 public boolean pingBinder() { 1095 return false; 1096 } 1097 1098 @Override 1099 public boolean isBinderAlive() { 1100 return false; 1101 } 1102 1103 @Override 1104 public IInterface queryLocalInterface(String descriptor) { 1105 return null; 1106 } 1107 1108 @Override 1109 public void dump(FileDescriptor fd, String[] args) throws RemoteException { 1110 1111 } 1112 1113 @Override 1114 public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { 1115 1116 } 1117 1118 @Override 1119 public boolean transact(int code, Parcel data, Parcel reply, int flags) 1120 throws RemoteException { 1121 return false; 1122 } 1123 1124 @Override 1125 public void linkToDeath(DeathRecipient recipient, int flags) 1126 throws RemoteException { 1127 1128 } 1129 1130 @Override 1131 public boolean unlinkToDeath(DeathRecipient recipient, int flags) { 1132 return false; 1133 } 1134 1135 @Override 1136 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1137 String[] args, ResultReceiver resultReceiver) { 1138 } 1139 }; 1140 } 1141 return mBinder; 1142 } 1143 1144 //------------ NOT OVERRIDEN -------------------- 1145 1146 @Override 1147 public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { 1148 // pass 1149 return false; 1150 } 1151 1152 @Override 1153 public int checkCallingOrSelfPermission(String arg0) { 1154 // pass 1155 return 0; 1156 } 1157 1158 @Override 1159 public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { 1160 // pass 1161 return 0; 1162 } 1163 1164 @Override 1165 public int checkCallingPermission(String arg0) { 1166 // pass 1167 return 0; 1168 } 1169 1170 @Override 1171 public int checkCallingUriPermission(Uri arg0, int arg1) { 1172 // pass 1173 return 0; 1174 } 1175 1176 @Override 1177 public int checkPermission(String arg0, int arg1, int arg2) { 1178 // pass 1179 return 0; 1180 } 1181 1182 @Override 1183 public int checkSelfPermission(String arg0) { 1184 // pass 1185 return 0; 1186 } 1187 1188 @Override 1189 public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) { 1190 // pass 1191 return 0; 1192 } 1193 1194 @Override 1195 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { 1196 // pass 1197 return 0; 1198 } 1199 1200 @Override 1201 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) { 1202 // pass 1203 return 0; 1204 } 1205 1206 @Override 1207 public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, 1208 int arg4, int arg5) { 1209 // pass 1210 return 0; 1211 } 1212 1213 @Override 1214 public void clearWallpaper() { 1215 // pass 1216 1217 } 1218 1219 @Override 1220 public Context createPackageContext(String arg0, int arg1) { 1221 // pass 1222 return null; 1223 } 1224 1225 @Override 1226 public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { 1227 // pass 1228 return null; 1229 } 1230 1231 @Override 1232 public Context createConfigurationContext(Configuration overrideConfiguration) { 1233 // pass 1234 return null; 1235 } 1236 1237 @Override 1238 public Context createDisplayContext(Display display) { 1239 // pass 1240 return null; 1241 } 1242 1243 @Override 1244 public String[] databaseList() { 1245 // pass 1246 return null; 1247 } 1248 1249 @Override 1250 public Context createApplicationContext(ApplicationInfo application, int flags) 1251 throws PackageManager.NameNotFoundException { 1252 return null; 1253 } 1254 1255 @Override 1256 public boolean deleteDatabase(String arg0) { 1257 // pass 1258 return false; 1259 } 1260 1261 @Override 1262 public boolean deleteFile(String arg0) { 1263 // pass 1264 return false; 1265 } 1266 1267 @Override 1268 public void enforceCallingOrSelfPermission(String arg0, String arg1) { 1269 // pass 1270 1271 } 1272 1273 @Override 1274 public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, 1275 String arg2) { 1276 // pass 1277 1278 } 1279 1280 @Override 1281 public void enforceCallingPermission(String arg0, String arg1) { 1282 // pass 1283 1284 } 1285 1286 @Override 1287 public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { 1288 // pass 1289 1290 } 1291 1292 @Override 1293 public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { 1294 // pass 1295 1296 } 1297 1298 @Override 1299 public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, 1300 String arg4) { 1301 // pass 1302 1303 } 1304 1305 @Override 1306 public void enforceUriPermission(Uri arg0, String arg1, String arg2, 1307 int arg3, int arg4, int arg5, String arg6) { 1308 // pass 1309 1310 } 1311 1312 @Override 1313 public String[] fileList() { 1314 // pass 1315 return null; 1316 } 1317 1318 @Override 1319 public BridgeAssetManager getAssets() { 1320 return mAssets; 1321 } 1322 1323 @Override 1324 public File getCacheDir() { 1325 // pass 1326 return null; 1327 } 1328 1329 @Override 1330 public File getCodeCacheDir() { 1331 // pass 1332 return null; 1333 } 1334 1335 @Override 1336 public File getExternalCacheDir() { 1337 // pass 1338 return null; 1339 } 1340 1341 @Override 1342 public ContentResolver getContentResolver() { 1343 if (mContentResolver == null) { 1344 mContentResolver = new BridgeContentResolver(this); 1345 } 1346 return mContentResolver; 1347 } 1348 1349 @Override 1350 public File getDatabasePath(String arg0) { 1351 // pass 1352 return null; 1353 } 1354 1355 @Override 1356 public File getDir(String arg0, int arg1) { 1357 // pass 1358 return null; 1359 } 1360 1361 @Override 1362 public File getFileStreamPath(String arg0) { 1363 // pass 1364 return null; 1365 } 1366 1367 @Override 1368 public File getSharedPreferencesPath(String name) { 1369 // pass 1370 return null; 1371 } 1372 1373 @Override 1374 public File getFilesDir() { 1375 // pass 1376 return null; 1377 } 1378 1379 @Override 1380 public File getDeviceEncryptedFilesDir() { 1381 // pass 1382 return null; 1383 } 1384 1385 @Override 1386 public File getCredentialEncryptedFilesDir() { 1387 // pass 1388 return null; 1389 } 1390 1391 @Override 1392 public File getNoBackupFilesDir() { 1393 // pass 1394 return null; 1395 } 1396 1397 @Override 1398 public File getExternalFilesDir(String type) { 1399 // pass 1400 return null; 1401 } 1402 1403 @Override 1404 public String getPackageCodePath() { 1405 // pass 1406 return null; 1407 } 1408 1409 @Override 1410 public String getBasePackageName() { 1411 // pass 1412 return null; 1413 } 1414 1415 @Override 1416 public String getOpPackageName() { 1417 // pass 1418 return null; 1419 } 1420 1421 @Override 1422 public ApplicationInfo getApplicationInfo() { 1423 return mApplicationInfo; 1424 } 1425 1426 @Override 1427 public String getPackageResourcePath() { 1428 // pass 1429 return null; 1430 } 1431 1432 @Override 1433 public SharedPreferences getSharedPreferences(String arg0, int arg1) { 1434 if (mSharedPreferences == null) { 1435 mSharedPreferences = new BridgeSharedPreferences(); 1436 } 1437 return mSharedPreferences; 1438 } 1439 1440 @Override 1441 public SharedPreferences getSharedPreferences(File arg0, int arg1) { 1442 if (mSharedPreferences == null) { 1443 mSharedPreferences = new BridgeSharedPreferences(); 1444 } 1445 return mSharedPreferences; 1446 } 1447 1448 @Override 1449 public Drawable getWallpaper() { 1450 // pass 1451 return null; 1452 } 1453 1454 @Override 1455 public int getWallpaperDesiredMinimumWidth() { 1456 return -1; 1457 } 1458 1459 @Override 1460 public int getWallpaperDesiredMinimumHeight() { 1461 return -1; 1462 } 1463 1464 @Override 1465 public void grantUriPermission(String arg0, Uri arg1, int arg2) { 1466 // pass 1467 1468 } 1469 1470 @Override 1471 public FileInputStream openFileInput(String arg0) throws FileNotFoundException { 1472 // pass 1473 return null; 1474 } 1475 1476 @Override 1477 public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { 1478 // pass 1479 return null; 1480 } 1481 1482 @Override 1483 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { 1484 // pass 1485 return null; 1486 } 1487 1488 @Override 1489 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, 1490 CursorFactory arg2, DatabaseErrorHandler arg3) { 1491 // pass 1492 return null; 1493 } 1494 1495 @Override 1496 public Drawable peekWallpaper() { 1497 // pass 1498 return null; 1499 } 1500 1501 @Override 1502 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { 1503 // pass 1504 return null; 1505 } 1506 1507 @Override 1508 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1509 String arg2, Handler arg3) { 1510 // pass 1511 return null; 1512 } 1513 1514 @Override 1515 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1516 IntentFilter arg1, String arg2, Handler arg3) { 1517 // pass 1518 return null; 1519 } 1520 1521 @Override 1522 public void removeStickyBroadcast(Intent arg0) { 1523 // pass 1524 1525 } 1526 1527 @Override 1528 public void revokeUriPermission(Uri arg0, int arg1) { 1529 // pass 1530 1531 } 1532 1533 @Override 1534 public void sendBroadcast(Intent arg0) { 1535 // pass 1536 1537 } 1538 1539 @Override 1540 public void sendBroadcast(Intent arg0, String arg1) { 1541 // pass 1542 1543 } 1544 1545 @Override 1546 public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { 1547 // pass 1548 1549 } 1550 1551 @Override 1552 public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) { 1553 // pass 1554 1555 } 1556 1557 @Override 1558 public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { 1559 // pass 1560 } 1561 1562 @Override 1563 public void sendOrderedBroadcast(Intent arg0, String arg1) { 1564 // pass 1565 1566 } 1567 1568 @Override 1569 public void sendOrderedBroadcast(Intent arg0, String arg1, 1570 BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1571 Bundle arg6) { 1572 // pass 1573 1574 } 1575 1576 @Override 1577 public void sendOrderedBroadcast(Intent arg0, String arg1, 1578 Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1579 Bundle arg6) { 1580 // pass 1581 1582 } 1583 1584 @Override 1585 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 1586 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 1587 String initialData, Bundle initialExtras) { 1588 // pass 1589 } 1590 1591 @Override 1592 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1593 // pass 1594 } 1595 1596 @Override 1597 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1598 String receiverPermission) { 1599 // pass 1600 } 1601 1602 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1603 String receiverPermission, int appOp) { 1604 // pass 1605 } 1606 1607 @Override 1608 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1609 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 1610 int initialCode, String initialData, Bundle initialExtras) { 1611 // pass 1612 } 1613 1614 @Override 1615 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1616 String receiverPermission, int appOp, BroadcastReceiver resultReceiver, 1617 Handler scheduler, 1618 int initialCode, String initialData, Bundle initialExtras) { 1619 // pass 1620 } 1621 1622 @Override 1623 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1624 String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, 1625 Handler scheduler, 1626 int initialCode, String initialData, Bundle initialExtras) { 1627 // pass 1628 } 1629 1630 @Override 1631 public void sendStickyBroadcast(Intent arg0) { 1632 // pass 1633 1634 } 1635 1636 @Override 1637 public void sendStickyOrderedBroadcast(Intent intent, 1638 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, 1639 Bundle initialExtras) { 1640 // pass 1641 } 1642 1643 @Override 1644 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 1645 // pass 1646 } 1647 1648 @Override 1649 public void sendStickyOrderedBroadcastAsUser(Intent intent, 1650 UserHandle user, BroadcastReceiver resultReceiver, 1651 Handler scheduler, int initialCode, String initialData, 1652 Bundle initialExtras) { 1653 // pass 1654 } 1655 1656 @Override 1657 public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { 1658 // pass 1659 } 1660 1661 @Override 1662 public void setTheme(int arg0) { 1663 // pass 1664 1665 } 1666 1667 @Override 1668 public void setWallpaper(Bitmap arg0) throws IOException { 1669 // pass 1670 1671 } 1672 1673 @Override 1674 public void setWallpaper(InputStream arg0) throws IOException { 1675 // pass 1676 1677 } 1678 1679 @Override 1680 public void startActivity(Intent arg0) { 1681 // pass 1682 } 1683 1684 @Override 1685 public void startActivity(Intent arg0, Bundle arg1) { 1686 // pass 1687 } 1688 1689 @Override 1690 public void startIntentSender(IntentSender intent, 1691 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 1692 throws IntentSender.SendIntentException { 1693 // pass 1694 } 1695 1696 @Override 1697 public void startIntentSender(IntentSender intent, 1698 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1699 Bundle options) throws IntentSender.SendIntentException { 1700 // pass 1701 } 1702 1703 @Override 1704 public boolean startInstrumentation(ComponentName arg0, String arg1, 1705 Bundle arg2) { 1706 // pass 1707 return false; 1708 } 1709 1710 @Override 1711 public ComponentName startService(Intent arg0) { 1712 // pass 1713 return null; 1714 } 1715 1716 @Override 1717 public boolean stopService(Intent arg0) { 1718 // pass 1719 return false; 1720 } 1721 1722 @Override 1723 public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { 1724 // pass 1725 return null; 1726 } 1727 1728 @Override 1729 public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { 1730 // pass 1731 return false; 1732 } 1733 1734 @Override 1735 public void unbindService(ServiceConnection arg0) { 1736 // pass 1737 1738 } 1739 1740 @Override 1741 public void unregisterReceiver(BroadcastReceiver arg0) { 1742 // pass 1743 1744 } 1745 1746 @Override 1747 public Context getApplicationContext() { 1748 return this; 1749 } 1750 1751 @Override 1752 public void startActivities(Intent[] arg0) { 1753 // pass 1754 1755 } 1756 1757 @Override 1758 public void startActivities(Intent[] arg0, Bundle arg1) { 1759 // pass 1760 1761 } 1762 1763 @Override 1764 public boolean isRestricted() { 1765 return false; 1766 } 1767 1768 @Override 1769 public File getObbDir() { 1770 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null); 1771 return null; 1772 } 1773 1774 @Override 1775 public DisplayAdjustments getDisplayAdjustments(int displayId) { 1776 // pass 1777 return null; 1778 } 1779 1780 @Override 1781 public int getUserId() { 1782 return 0; // not used 1783 } 1784 1785 @Override 1786 public File[] getExternalFilesDirs(String type) { 1787 // pass 1788 return new File[0]; 1789 } 1790 1791 @Override 1792 public File[] getObbDirs() { 1793 // pass 1794 return new File[0]; 1795 } 1796 1797 @Override 1798 public File[] getExternalCacheDirs() { 1799 // pass 1800 return new File[0]; 1801 } 1802 1803 @Override 1804 public File[] getExternalMediaDirs() { 1805 // pass 1806 return new File[0]; 1807 } 1808 1809 public void setScrollYPos(@NonNull View view, int scrollPos) { 1810 mScrollYPos.put(view, scrollPos); 1811 } 1812 1813 public int getScrollYPos(@NonNull View view) { 1814 Integer pos = mScrollYPos.get(view); 1815 return pos != null ? pos : 0; 1816 } 1817} 1818