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