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