summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt55
-rw-r--r--api/system-current.txt56
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/ActivityManager.java22
-rw-r--r--core/java/android/app/AppOpsManager.java3
-rw-r--r--core/java/android/app/ExitTransitionCoordinator.java2
-rw-r--r--core/java/android/app/IntentService.java2
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java3
-rw-r--r--core/java/android/bluetooth/BluetoothHealthCallback.java3
-rw-r--r--core/java/android/bluetooth/BluetoothSap.java59
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java10
-rw-r--r--core/java/android/bluetooth/le/ScanCallback.java6
-rw-r--r--core/java/android/bluetooth/le/ScanSettings.java11
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/net/ConnectivityManager.java4
-rw-r--r--core/java/android/os/AsyncTask.java13
-rw-r--r--core/java/android/os/Bundle.java8
-rw-r--r--core/java/android/provider/ContactsContract.java10
-rw-r--r--core/java/android/service/carrier/CarrierMessagingService.java77
-rw-r--r--core/java/android/service/carrier/ICarrierMessagingService.aidl9
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java13
-rw-r--r--core/java/android/transition/Transition.java3
-rw-r--r--core/java/android/transition/Visibility.java117
-rw-r--r--core/java/android/view/View.java8
-rw-r--r--core/java/android/view/ViewGroup.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java28
-rw-r--r--core/java/android/widget/AbsListView.java8
-rw-r--r--core/java/android/widget/CursorAdapter.java2
-rw-r--r--core/java/android/widget/Editor.java5
-rw-r--r--core/java/android/widget/HorizontalScrollView.java14
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java10
-rw-r--r--core/java/android/widget/ScrollView.java13
-rw-r--r--core/java/com/android/internal/widget/ViewPager.java6
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp592
-rw-r--r--core/jni/android/graphics/Bitmap.h114
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp52
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp24
-rw-r--r--core/jni/android/graphics/Graphics.cpp120
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h73
-rw-r--r--core/jni/android_view_SurfaceControl.cpp22
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/res/res/values-gu-rIN/strings.xml22
-rw-r--r--core/res/res/values-mcc310-mnc260-sq-rAL/strings.xml2
-rwxr-xr-xcore/res/res/values-mcc311-mnc480/config.xml5
-rw-r--r--core/res/res/values-pa-rIN/strings.xml22
-rw-r--r--core/res/res/values-sq-rAL/strings.xml40
-rw-r--r--core/res/res/values/ids.xml12
-rw-r--r--core/res/res/values/public.xml4
-rw-r--r--docs/html/about/dashboards/index.jd48
-rw-r--r--docs/html/auto/index.jd5
-rw-r--r--docs/html/design/building-blocks/buttons.jd28
-rw-r--r--docs/html/design/building-blocks/dialogs.jd26
-rw-r--r--docs/html/design/building-blocks/grid-lists.jd18
-rw-r--r--docs/html/design/building-blocks/lists.jd6
-rw-r--r--docs/html/design/building-blocks/pickers.jd6
-rw-r--r--docs/html/design/building-blocks/progress.jd18
-rw-r--r--docs/html/design/building-blocks/seek-bars.jd12
-rw-r--r--docs/html/design/building-blocks/spinners.jd6
-rw-r--r--docs/html/design/building-blocks/tabs.jd6
-rw-r--r--docs/html/design/building-blocks/text-fields.jd16
-rw-r--r--docs/html/design/devices.jd3
-rw-r--r--docs/html/design/downloads/index.jd98
-rw-r--r--docs/html/design/get-started/creative-vision.jd9
-rw-r--r--docs/html/design/get-started/principles.jd102
-rw-r--r--docs/html/design/handhelds/index.jd20
-rw-r--r--docs/html/design/index.jd100
-rw-r--r--docs/html/design/material/index.jd4
-rw-r--r--docs/html/design/media/hero-material-design.pngbin0 -> 170844 bytes
-rw-r--r--docs/html/design/patterns/accessibility.jd8
-rw-r--r--docs/html/design/patterns/actionbar.jd28
-rw-r--r--docs/html/design/patterns/app-structure.jd48
-rw-r--r--docs/html/design/patterns/buttons.jd10
-rw-r--r--docs/html/design/patterns/compatibility.jd18
-rw-r--r--docs/html/design/patterns/confirming-acknowledging.jd24
-rw-r--r--docs/html/design/patterns/fullscreen.jd10
-rw-r--r--docs/html/design/patterns/gestures.jd22
-rw-r--r--docs/html/design/patterns/help.jd28
-rw-r--r--docs/html/design/patterns/multi-pane-layouts.jd24
-rw-r--r--docs/html/design/patterns/navigation-drawer.jd30
-rw-r--r--docs/html/design/patterns/new.jd49
-rw-r--r--docs/html/design/patterns/notifications_k.jd40
-rw-r--r--docs/html/design/patterns/pure-android.jd37
-rw-r--r--docs/html/design/patterns/selection.jd18
-rw-r--r--docs/html/design/patterns/settings.jd128
-rw-r--r--docs/html/design/patterns/swipe-views.jd6
-rw-r--r--docs/html/design/patterns/widgets.jd20
-rw-r--r--docs/html/design/style/branding.jd24
-rw-r--r--docs/html/design/style/devices-displays.jd8
-rw-r--r--docs/html/design/style/iconography.jd92
-rw-r--r--docs/html/design/style/metrics-grids.jd6
-rw-r--r--docs/html/design/style/themes.jd6
-rw-r--r--docs/html/design/style/touch-feedback.jd18
-rw-r--r--docs/html/design/style/typography.jd12
-rw-r--r--docs/html/design/style/writing.jd36
-rw-r--r--docs/html/design/tv/patterns.jd6
-rw-r--r--docs/html/design/videos/index.jd60
-rw-r--r--docs/html/design/wear/creative-vision.jd20
-rw-r--r--docs/html/design/wear/style.jd12
-rw-r--r--docs/html/design/wear/watchfaces.jd66
-rw-r--r--docs/html/develop/index.jd468
-rw-r--r--docs/html/distribute/analyze/index.jd2
-rw-r--r--docs/html/distribute/engage/deep-linking.jd4
-rw-r--r--docs/html/distribute/engage/easy-signin.jd2
-rw-r--r--docs/html/distribute/googleplay/about.jd4
-rw-r--r--docs/html/distribute/googleplay/developer-console.jd4
-rw-r--r--docs/html/distribute/googleplay/index.jd1
-rw-r--r--docs/html/distribute/images/advertising.jpgbin26362 -> 23239 bytes
-rw-r--r--docs/html/distribute/index.jd80
-rw-r--r--docs/html/distribute/monetize/ads.jd2
-rw-r--r--docs/html/distribute/tools/promote/device-art-resources/nexus_6/port_back.pngbin705724 -> 692418 bytes
-rw-r--r--docs/html/distribute/tools/promote/device-art.jd12
-rw-r--r--docs/html/distribute/users/promote-with-ads.jd4
-rw-r--r--docs/html/google/index.jd2
-rw-r--r--docs/html/google/play-services/index.jd14
-rw-r--r--docs/html/google/play-services/location.jd6
-rw-r--r--docs/html/google/play/dist.jd14
-rw-r--r--docs/html/images/cards/adwords_2x.jpgbin0 -> 31526 bytes
-rw-r--r--docs/html/images/cards/analytics-mobile_2x.jpgbin0 -> 40375 bytes
-rw-r--r--docs/html/images/cards/android-auto_2x.pngbin0 -> 12762 bytes
-rw-r--r--docs/html/images/cards/android-devices_2x.jpgbin0 -> 43007 bytes
-rw-r--r--docs/html/images/cards/android-studio_2x.pngbin0 -> 28824 bytes
-rw-r--r--docs/html/images/cards/android-tv_2x.pngbin0 -> 2567 bytes
-rw-r--r--docs/html/images/cards/android-wear-apps_2x.jpgbin0 -> 33577 bytes
-rw-r--r--docs/html/images/cards/android-wear-materials_2x.jpgbin0 -> 23220 bytes
-rw-r--r--docs/html/images/cards/android-wear_2x.pngbin0 -> 12883 bytes
-rw-r--r--docs/html/images/cards/cloud-platform_2x.pngbin0 -> 14894 bytes
-rw-r--r--docs/html/images/cards/design-creative-vision_2x.jpgbin0 -> 42208 bytes
-rw-r--r--docs/html/images/cards/design-material-for-android_2x.jpgbin0 -> 15448 bytes
-rw-r--r--docs/html/images/cards/design-new-in-android_2x.jpgbin0 -> 36691 bytes
-rw-r--r--docs/html/images/cards/design-pure-android_2x.pngbin0 -> 27109 bytes
-rw-r--r--docs/html/images/cards/dev-console_2x.jpgbin0 -> 36425 bytes
-rw-r--r--docs/html/images/cards/google-play_2x.pngbin0 -> 10368 bytes
-rw-r--r--docs/html/images/cards/google-search_2x.pngbin0 -> 3097 bytes
-rw-r--r--docs/html/images/cards/google-sign-in_2x.pngbin0 -> 6236 bytes
-rw-r--r--docs/html/images/cards/material-animation_2x.pngbin0 -> 10935 bytes
-rw-r--r--docs/html/images/cards/material-color-palette_2x.jpgbin0 -> 26202 bytes
-rw-r--r--docs/html/images/cards/material-components_2x.jpgbin0 -> 24555 bytes
-rw-r--r--docs/html/images/cards/material-layout-template_2x.jpgbin0 -> 22336 bytes
-rw-r--r--docs/html/images/cards/material-layout_2x.pngbin0 -> 11400 bytes
-rw-r--r--docs/html/images/cards/material-patterns_2x.pngbin0 -> 8462 bytes
-rw-r--r--docs/html/images/cards/material-sticker-sheet_2x.jpgbin0 -> 21453 bytes
-rw-r--r--docs/html/images/cards/material-style_2x.jpgbin0 -> 29130 bytes
-rw-r--r--docs/html/images/cards/material-typography_2x.jpgbin0 -> 30729 bytes
-rw-r--r--docs/html/images/cards/material-usability_2x.pngbin0 -> 2798 bytes
-rw-r--r--docs/html/images/cards/material_2x.pngbin0 -> 9002 bytes
-rw-r--r--docs/html/images/cards/program-edu_2x.jpgbin0 -> 53708 bytes
-rw-r--r--docs/html/images/cards/samples-new_2x.pngbin0 -> 4940 bytes
-rw-r--r--docs/html/images/develop/hero-android-studio-on-device.pngbin0 -> 200898 bytes
-rw-r--r--docs/html/images/distribute/google-play-bg.jpgbin0 -> 30811 bytes
-rw-r--r--docs/html/images/distribute/hero-family.jpgbin0 -> 282862 bytes
-rw-r--r--docs/html/images/distribute/hero-g-play-guidebooks_2x.pngbin0 -> 24250 bytes
-rw-r--r--docs/html/images/distribute/hero-ginlemon.jpgbin0 -> 311355 bytes
-rw-r--r--docs/html/images/distribute/hero-haystack.jpgbin0 -> 222047 bytes
-rw-r--r--docs/html/images/distribute/hero-jelly-button.jpgbin0 -> 265394 bytes
-rw-r--r--docs/html/images/distribute/hero-outfit7.jpgbin0 -> 120060 bytes
-rw-r--r--docs/html/images/home/hero-lollipop_2x.pngbin0 -> 1035400 bytes
-rw-r--r--docs/html/index.jd129
-rw-r--r--docs/html/jd_collections.js152
-rw-r--r--docs/html/jd_extras.js352
-rw-r--r--docs/html/preview/api-overview.jd120
-rw-r--r--docs/html/preview/images/bugs.pngbin0 -> 2359 bytes
-rw-r--r--docs/html/preview/images/dev-prev.pngbin0 -> 706073 bytes
-rw-r--r--docs/html/preview/images/updates.pngbin0 -> 2398 bytes
-rw-r--r--docs/html/preview/index.html689
-rw-r--r--docs/html/preview/license.jd143
-rw-r--r--docs/html/preview/preview_toc.cs37
-rw-r--r--docs/html/preview/reference.jd15
-rw-r--r--docs/html/preview/samples.jd37
-rw-r--r--docs/html/preview/setup-sdk.jd361
-rw-r--r--docs/html/preview/support.jd67
-rw-r--r--docs/html/samples/new/index.jd1
-rw-r--r--docs/html/sdk/index.jd53
-rw-r--r--docs/html/sdk/installing/migrate.jd32
-rw-r--r--docs/html/tools/sdk/tools-notes.jd27
-rw-r--r--docs/html/tools/support-library/index.jd1
-rw-r--r--docs/html/training/building-wearables.jd4
-rw-r--r--docs/html/training/material/index.jd4
-rw-r--r--docs/html/training/swipe/add-swipe-interface.jd135
-rw-r--r--docs/html/training/swipe/images/swipe.mp4bin0 -> 411879 bytes
-rw-r--r--docs/html/training/swipe/images/swipe_original.mp4bin0 -> 743388 bytes
-rw-r--r--docs/html/training/swipe/index.jd91
-rw-r--r--docs/html/training/swipe/respond-refresh-request.jd158
-rw-r--r--docs/html/training/sync-adapters/creating-stub-provider.jd6
-rw-r--r--docs/html/training/training_toc.cs19
-rw-r--r--docs/html/training/tv/start/start.jd2
-rw-r--r--docs/html/tv/index.jd2
-rw-r--r--docs/html/wear/index.jd4
-rw-r--r--graphics/java/android/graphics/Bitmap.java88
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java7
-rw-r--r--libs/androidfw/Android.mk2
-rw-r--r--location/java/android/location/LocationManager.java31
-rw-r--r--media/java/android/media/AudioManager.java76
-rw-r--r--media/java/android/media/MediaPlayer.java52
-rw-r--r--media/java/android/media/MediaSync.java22
-rw-r--r--media/java/android/media/tv/TvContentRating.java87
-rw-r--r--media/jni/android_media_MediaSync.cpp30
-rw-r--r--media/jni/android_media_MediaSync.h4
-rw-r--r--packages/DocumentsUI/res/values-gu-rIN/strings.xml8
-rw-r--r--packages/DocumentsUI/res/values-pa-rIN/strings.xml8
-rw-r--r--packages/DocumentsUI/res/values-sq-rAL/strings.xml8
-rw-r--r--packages/Keyguard/res/values-sq-rAL/strings.xml2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/EmergencyButton.java7
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java1
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java23
-rw-r--r--packages/PrintSpooler/res/values-sq-rAL/strings.xml4
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java25
-rw-r--r--packages/SettingsProvider/res/values-sq-rAL/defaults.xml24
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml21
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java73
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java8
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java27
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java17
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java26
-rw-r--r--services/core/java/com/android/server/net/DelayedDiskWrite.java12
-rw-r--r--services/core/java/com/android/server/notification/CalendarTracker.java38
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java64
-rw-r--r--services/core/java/com/android/server/pm/Settings.java8
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java11
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java9
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--telecomm/java/android/telecom/Connection.java12
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java8
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java15
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java17
-rw-r--r--telecomm/java/android/telecom/ParcelableConference.java3
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java7
-rw-r--r--telecomm/java/android/telecom/VideoProfile.java36
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl2
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java14
-rw-r--r--telephony/java/com/android/internal/telephony/ISms.aidl224
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl1
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneConstants.java4
-rw-r--r--tools/aapt/Android.mk3
-rw-r--r--tools/aapt2/Android.mk5
-rw-r--r--tools/aapt2/BinaryResourceParser.cpp80
-rw-r--r--tools/aapt2/BinaryResourceParser.h5
-rw-r--r--tools/aapt2/BinaryXmlPullParser.cpp73
-rw-r--r--tools/aapt2/BinaryXmlPullParser.h31
-rw-r--r--tools/aapt2/BindingXmlPullParser.cpp5
-rw-r--r--tools/aapt2/BindingXmlPullParser.h2
-rw-r--r--tools/aapt2/Flag.cpp2
-rw-r--r--tools/aapt2/JavaClassGenerator.cpp15
-rw-r--r--tools/aapt2/JavaClassGenerator_test.cpp37
-rw-r--r--tools/aapt2/Linker.cpp54
-rw-r--r--tools/aapt2/Linker.h7
-rw-r--r--tools/aapt2/Linker_test.cpp4
-rw-r--r--tools/aapt2/Main.cpp98
-rw-r--r--tools/aapt2/ManifestValidator.cpp32
-rw-r--r--tools/aapt2/Maybe.h92
-rw-r--r--tools/aapt2/Maybe_test.cpp60
-rw-r--r--tools/aapt2/MockResolver.h93
-rw-r--r--tools/aapt2/Resolver.h54
-rw-r--r--tools/aapt2/Resource.h7
-rw-r--r--tools/aapt2/ResourceParser.cpp64
-rw-r--r--tools/aapt2/ResourceParser.h12
-rw-r--r--tools/aapt2/ResourceParser_test.cpp151
-rw-r--r--tools/aapt2/ResourceTable.cpp39
-rw-r--r--tools/aapt2/ResourceTable.h1
-rw-r--r--tools/aapt2/ResourceTableResolver.cpp (renamed from tools/aapt2/Resolver.cpp)31
-rw-r--r--tools/aapt2/ResourceTableResolver.h76
-rw-r--r--tools/aapt2/ResourceTypeExtensions.h41
-rw-r--r--tools/aapt2/ResourceValues.cpp19
-rw-r--r--tools/aapt2/ResourceValues.h20
-rw-r--r--tools/aapt2/ScopedXmlPullParser.cpp5
-rw-r--r--tools/aapt2/ScopedXmlPullParser.h30
-rw-r--r--tools/aapt2/SourceXmlPullParser.cpp37
-rw-r--r--tools/aapt2/SourceXmlPullParser.h36
-rw-r--r--tools/aapt2/StringPool.cpp71
-rw-r--r--tools/aapt2/StringPool.h4
-rw-r--r--tools/aapt2/TableFlattener.cpp61
-rw-r--r--tools/aapt2/Util.cpp15
-rw-r--r--tools/aapt2/Util.h10
-rw-r--r--tools/aapt2/XliffXmlPullParser.cpp5
-rw-r--r--tools/aapt2/XliffXmlPullParser.h30
-rw-r--r--tools/aapt2/XmlFlattener.cpp153
-rw-r--r--tools/aapt2/XmlFlattener.h12
-rw-r--r--tools/aapt2/XmlFlattener_test.cpp151
-rw-r--r--tools/aapt2/XmlPullParser.h23
-rw-r--r--tools/aapt2/data/lib/Makefile2
-rw-r--r--tools/aapt2/data/lib/res/values/styles.xml2
-rw-r--r--tools/aapt2/data/res/layout/main.xml3
-rw-r--r--tools/aapt2/data/res/values/styles.xml3
-rw-r--r--tools/split-select/Android.mk3
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl3
-rw-r--r--wifi/java/android/net/wifi/RttManager.java2
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java13
289 files changed, 6149 insertions, 3347 deletions
diff --git a/api/current.txt b/api/current.txt
index c8069e1..e3bb0b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1686,9 +1686,13 @@ package android {
public static final class R.id {
ctor public R.id();
+ field public static final int accessibilityActionScrollDown = 16908345; // 0x1020039
+ field public static final int accessibilityActionScrollLeft = 16908344; // 0x1020038
+ field public static final int accessibilityActionScrollRight = 16908346; // 0x102003a
field public static final int accessibilityActionScrollToPosition = 16908342; // 0x1020036
+ field public static final int accessibilityActionScrollUp = 16908343; // 0x1020037
field public static final int accessibilityActionShowOnScreen = 16908341; // 0x1020035
- field public static final int accessibilityActionStylusButtonPress = 16908344; // 0x1020038
+ field public static final int accessibilityActionStylusButtonPress = 16908348; // 0x102003c
field public static final int addToDictionary = 16908330; // 0x102002a
field public static final int background = 16908288; // 0x1020000
field public static final int button1 = 16908313; // 0x1020019
@@ -1728,7 +1732,7 @@ package android {
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
field public static final int selectedIcon = 16908302; // 0x102000e
- field public static final int shareText = 16908343; // 0x1020037
+ field public static final int shareText = 16908347; // 0x102003b
field public static final int startSelectingText = 16908328; // 0x1020028
field public static final int statusBarBackground = 16908335; // 0x102002f
field public static final int stopSelectingText = 16908329; // 0x1020029
@@ -7005,25 +7009,6 @@ package android.bluetooth {
method public abstract void onServiceDisconnected(int);
}
- public final class BluetoothSap implements android.bluetooth.BluetoothProfile {
- method public synchronized void close();
- method public boolean connect(android.bluetooth.BluetoothDevice);
- method public boolean disconnect(android.bluetooth.BluetoothDevice);
- method public android.bluetooth.BluetoothDevice getClient();
- method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(android.bluetooth.BluetoothDevice);
- method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method public int getPriority(android.bluetooth.BluetoothDevice);
- method public int getState();
- method public boolean isConnected(android.bluetooth.BluetoothDevice);
- method public boolean setPriority(android.bluetooth.BluetoothDevice, int);
- field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
- field public static final int RESULT_CANCELED = 2; // 0x2
- field public static final int RESULT_FAILURE = 0; // 0x0
- field public static final int RESULT_SUCCESS = 1; // 0x1
- field public static final int STATE_ERROR = -1; // 0xffffffff
- }
-
public final class BluetoothServerSocket implements java.io.Closeable {
method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
@@ -7192,7 +7177,14 @@ package android.bluetooth.le {
method public int getScanResultType();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1
+ field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
+ field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanSettings> CREATOR;
+ field public static final int MATCH_MODE_AGGRESSIVE = 1; // 0x1
+ field public static final int MATCH_MODE_STICKY = 2; // 0x2
+ field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
+ field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
+ field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -7202,6 +7194,8 @@ package android.bluetooth.le {
public static final class ScanSettings.Builder {
ctor public ScanSettings.Builder();
method public android.bluetooth.le.ScanSettings build();
+ method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
+ method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
}
@@ -18373,6 +18367,7 @@ package android.net {
method public deprecated void reportBadNetwork(android.net.Network);
method public void reportCaptivePortalDismissed(android.net.Network, java.lang.String);
method public void reportNetworkConnectivity(android.net.Network, boolean);
+ method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated void setNetworkPreference(int);
@@ -28846,13 +28841,17 @@ package android.service.carrier {
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
- method public void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
- method public void onSendMultipartTextSms(java.util.List<java.lang.String>, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMultipartSmsResult>);
- method public void onSendTextSms(java.lang.String, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public deprecated void onSendMultipartTextSms(java.util.List<java.lang.String>, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMultipartSmsResult>);
+ method public void onSendMultipartTextSms(java.util.List<java.lang.String>, int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMultipartSmsResult>);
+ method public deprecated void onSendTextSms(java.lang.String, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public void onSendTextSms(java.lang.String, int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
field public static final int SEND_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
@@ -30782,6 +30781,7 @@ package android.telecom {
method public static boolean isPaused(int);
method public static boolean isReceptionEnabled(int);
method public static boolean isTransmissionEnabled(int);
+ method public static java.lang.String videoStateToString(int);
field public static final int AUDIO_ONLY = 0; // 0x0
field public static final int BIDIRECTIONAL = 3; // 0x3
field public static final int PAUSED = 4; // 0x4
@@ -31202,7 +31202,8 @@ package android.telephony {
public class SmsMessage {
method public static int[] calculateLength(java.lang.CharSequence, boolean);
method public static int[] calculateLength(java.lang.String, boolean);
- method public static android.telephony.SmsMessage createFromPdu(byte[]);
+ method public static deprecated android.telephony.SmsMessage createFromPdu(byte[]);
+ method public static android.telephony.SmsMessage createFromPdu(byte[], java.lang.String);
method public java.lang.String getDisplayMessageBody();
method public java.lang.String getDisplayOriginatingAddress();
method public java.lang.String getEmailBody();
@@ -37865,8 +37866,12 @@ package android.view.accessibility {
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_BACKWARD;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_DOWN;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_FORWARD;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_LEFT;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_RIGHT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_TO_POSITION;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_UP;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SELECT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
diff --git a/api/system-current.txt b/api/system-current.txt
index 0fd49a7..535bfc7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -110,6 +110,7 @@ package android {
field public static final java.lang.String INTERNET = "android.permission.INTERNET";
field public static final java.lang.String INVOKE_CARRIER_SETUP = "android.permission.INVOKE_CARRIER_SETUP";
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
+ field public static final java.lang.String KILL_UID = "android.permission.KILL_UID";
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
@@ -1761,9 +1762,13 @@ package android {
public static final class R.id {
ctor public R.id();
+ field public static final int accessibilityActionScrollDown = 16908345; // 0x1020039
+ field public static final int accessibilityActionScrollLeft = 16908344; // 0x1020038
+ field public static final int accessibilityActionScrollRight = 16908346; // 0x102003a
field public static final int accessibilityActionScrollToPosition = 16908342; // 0x1020036
+ field public static final int accessibilityActionScrollUp = 16908343; // 0x1020037
field public static final int accessibilityActionShowOnScreen = 16908341; // 0x1020035
- field public static final int accessibilityActionStylusButtonPress = 16908344; // 0x1020038
+ field public static final int accessibilityActionStylusButtonPress = 16908348; // 0x102003c
field public static final int addToDictionary = 16908330; // 0x102002a
field public static final int background = 16908288; // 0x1020000
field public static final int button1 = 16908313; // 0x1020019
@@ -1803,7 +1808,7 @@ package android {
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
field public static final int selectedIcon = 16908302; // 0x102000e
- field public static final int shareText = 16908343; // 0x1020037
+ field public static final int shareText = 16908347; // 0x102003b
field public static final int startSelectingText = 16908328; // 0x1020028
field public static final int statusBarBackground = 16908335; // 0x102002f
field public static final int stopSelectingText = 16908329; // 0x1020029
@@ -3666,6 +3671,7 @@ package android.app {
method public static boolean isRunningInTestHarness();
method public static boolean isUserAMonkey();
method public void killBackgroundProcesses(java.lang.String);
+ method public void killUid(int, java.lang.String);
method public void moveTaskToFront(int, int);
method public void moveTaskToFront(int, int, android.os.Bundle);
method public deprecated void restartPackage(java.lang.String);
@@ -7196,25 +7202,6 @@ package android.bluetooth {
method public abstract void onServiceDisconnected(int);
}
- public final class BluetoothSap implements android.bluetooth.BluetoothProfile {
- method public synchronized void close();
- method public boolean connect(android.bluetooth.BluetoothDevice);
- method public boolean disconnect(android.bluetooth.BluetoothDevice);
- method public android.bluetooth.BluetoothDevice getClient();
- method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(android.bluetooth.BluetoothDevice);
- method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method public int getPriority(android.bluetooth.BluetoothDevice);
- method public int getState();
- method public boolean isConnected(android.bluetooth.BluetoothDevice);
- method public boolean setPriority(android.bluetooth.BluetoothDevice, int);
- field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
- field public static final int RESULT_CANCELED = 2; // 0x2
- field public static final int RESULT_FAILURE = 0; // 0x0
- field public static final int RESULT_SUCCESS = 1; // 0x1
- field public static final int STATE_ERROR = -1; // 0xffffffff
- }
-
public final class BluetoothServerSocket implements java.io.Closeable {
method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
@@ -7397,6 +7384,11 @@ package android.bluetooth.le {
field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanSettings> CREATOR;
+ field public static final int MATCH_MODE_AGGRESSIVE = 1; // 0x1
+ field public static final int MATCH_MODE_STICKY = 2; // 0x2
+ field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
+ field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
+ field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -7409,6 +7401,8 @@ package android.bluetooth.le {
ctor public ScanSettings.Builder();
method public android.bluetooth.le.ScanSettings build();
method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
+ method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
+ method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int);
@@ -19841,6 +19835,7 @@ package android.net {
method public deprecated void reportBadNetwork(android.net.Network);
method public void reportCaptivePortalDismissed(android.net.Network, java.lang.String);
method public void reportNetworkConnectivity(android.net.Network, boolean);
+ method public boolean requestBandwidthUpdate(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
method public deprecated void setNetworkPreference(int);
@@ -20847,6 +20842,7 @@ package android.net.wifi {
field public static final int REASON_INVALID_LISTENER = -3; // 0xfffffffd
field public static final int REASON_INVALID_REQUEST = -4; // 0xfffffffc
field public static final int REASON_NOT_AVAILABLE = -2; // 0xfffffffe
+ field public static final int REASON_PERMISSION_DENIED = -5; // 0xfffffffb
field public static final int REASON_UNSPECIFIED = -1; // 0xffffffff
field public static final int RTT_BW_10_SUPPORT = 2; // 0x2
field public static final int RTT_BW_160_SUPPORT = 32; // 0x20
@@ -30859,13 +30855,17 @@ package android.service.carrier {
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
- method public void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
- method public void onSendMultipartTextSms(java.util.List<java.lang.String>, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMultipartSmsResult>);
- method public void onSendTextSms(java.lang.String, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public deprecated void onSendMultipartTextSms(java.util.List<java.lang.String>, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMultipartSmsResult>);
+ method public void onSendMultipartTextSms(java.util.List<java.lang.String>, int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMultipartSmsResult>);
+ method public deprecated void onSendTextSms(java.lang.String, int, java.lang.String, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
+ method public void onSendTextSms(java.lang.String, int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
field public static final int SEND_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
@@ -32944,6 +32944,7 @@ package android.telecom {
method public static boolean isPaused(int);
method public static boolean isReceptionEnabled(int);
method public static boolean isTransmissionEnabled(int);
+ method public static java.lang.String videoStateToString(int);
field public static final int AUDIO_ONLY = 0; // 0x0
field public static final int BIDIRECTIONAL = 3; // 0x3
field public static final int PAUSED = 4; // 0x4
@@ -33366,7 +33367,8 @@ package android.telephony {
public class SmsMessage {
method public static int[] calculateLength(java.lang.CharSequence, boolean);
method public static int[] calculateLength(java.lang.String, boolean);
- method public static android.telephony.SmsMessage createFromPdu(byte[]);
+ method public static deprecated android.telephony.SmsMessage createFromPdu(byte[]);
+ method public static android.telephony.SmsMessage createFromPdu(byte[], java.lang.String);
method public java.lang.String getDisplayMessageBody();
method public java.lang.String getDisplayOriginatingAddress();
method public java.lang.String getEmailBody();
@@ -40078,8 +40080,12 @@ package android.view.accessibility {
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_BACKWARD;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_DOWN;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_FORWARD;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_LEFT;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_RIGHT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_TO_POSITION;
+ field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_UP;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SELECT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5fd9615..7260d10 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -21,6 +21,7 @@ import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.LayoutRes;
+import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
@@ -891,6 +892,7 @@ public class Activity extends ContextThemeWrapper
* @see #onRestoreInstanceState
* @see #onPostCreate
*/
+ @MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 576a046..9bbb4be 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,8 +16,10 @@
package android.app;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -26,6 +28,7 @@ import android.os.BatteryStats;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.util.Log;
import com.android.internal.app.ProcessStats;
import com.android.internal.os.TransferPipe;
import com.android.internal.util.FastPrintWriter;
@@ -2396,7 +2399,24 @@ public class ActivityManager {
} catch (RemoteException e) {
}
}
-
+
+ /**
+ * Kills the specified UID.
+ * @param uid The UID to kill.
+ * @param reason The reason for the kill.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.KILL_UID)
+ public void killUid(int uid, String reason) {
+ try {
+ ActivityManagerNative.getDefault().killUid(uid, reason);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't kill uid:" + uid, e);
+ }
+ }
+
/**
* Have the system perform a force stop of everything associated with
* the given application package. All processes that share its uid
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6bbbf9e..5aa399b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -941,7 +941,8 @@ public class AppOpsManager {
* @hide
*/
public static int permissionToOpCode(String permission) {
- return sPermToOp.get(permission);
+ Integer boxedOpCode = sPermToOp.get(permission);
+ return boxedOpCode != null ? boxedOpCode : OP_NONE;
}
/**
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 169952a..0f286fb 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -239,7 +239,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK));
}
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this,
- mAllSharedElementNames, resultCode, data);
+ mSharedElementNames, resultCode, data);
mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() {
@Override
public void onTranslucentConversionComplete(boolean drawComplete) {
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 96767ae..3cda973 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.WorkerThread;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
@@ -158,5 +159,6 @@ public abstract class IntentService extends Service {
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
*/
+ @WorkerThread
protected abstract void onHandleIntent(Intent intent);
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9b4dcc6..0a77868 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1692,7 +1692,8 @@ public final class BluetoothAdapter {
* @param context Context of the application
* @param listener The service Listener for connection callbacks.
* @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH},
- * {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}.
+ * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
+ * {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}.
* @return true on success, false on error
*/
public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java
index baf2ade..128376f 100644
--- a/core/java/android/bluetooth/BluetoothHealthCallback.java
+++ b/core/java/android/bluetooth/BluetoothHealthCallback.java
@@ -17,6 +17,7 @@
package android.bluetooth;
+import android.annotation.BinderThread;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -39,6 +40,7 @@ public abstract class BluetoothHealthCallback {
* {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS} or
* {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE}
*/
+ @BinderThread
public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
int status) {
Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status);
@@ -58,6 +60,7 @@ public abstract class BluetoothHealthCallback {
* @param channelId The id associated with the channel. This id will be used
* in future calls like when disconnecting the channel.
*/
+ @BinderThread
public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd,
int channelId) {
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 7b4c6f9..014cb22 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -28,13 +28,41 @@ import android.os.IBinder;
import android.os.ServiceManager;
import android.util.Log;
-
+/**
+ * This class provides the APIs to control the Bluetooth SIM
+ * Access Profile (SAP).
+ *
+ * <p>BluetoothSap is a proxy object for controlling the Bluetooth
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothSap proxy object.
+ *
+ * <p>Each method is protected with its appropriate permission.
+ * @hide
+ */
public final class BluetoothSap implements BluetoothProfile {
private static final String TAG = "BluetoothSap";
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ /**
+ * Intent used to broadcast the change in connection state of the profile.
+ *
+ * <p>This intent will have 4 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ * @hide
+ */
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
@@ -43,12 +71,22 @@ public final class BluetoothSap implements BluetoothProfile {
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- /** There was an error trying to obtain the state */
- public static final int STATE_ERROR = -1;
+ /**
+ * There was an error trying to obtain the state.
+ * @hide
+ */
+ public static final int STATE_ERROR = -1;
- public static final int RESULT_FAILURE = 0;
+ /**
+ * Connection state change succceeded.
+ * @hide
+ */
public static final int RESULT_SUCCESS = 1;
- /** Connection canceled before completion. */
+
+ /**
+ * Connection canceled before completion.
+ * @hide
+ */
public static final int RESULT_CANCELED = 2;
final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -124,6 +162,7 @@ public final class BluetoothSap implements BluetoothProfile {
* Other public functions of BluetoothSap will return default error
* results once close() has been called. Multiple invocations of close()
* are ok.
+ * @hide
*/
public synchronized void close() {
IBluetoothManager mgr = mAdapter.getBluetoothManager();
@@ -152,6 +191,7 @@ public final class BluetoothSap implements BluetoothProfile {
* Get the current state of the BluetoothSap service.
* @return One of the STATE_ return codes, or STATE_ERROR if this proxy
* object is currently not connected to the Sap service.
+ * @hide
*/
public int getState() {
if (VDBG) log("getState()");
@@ -171,6 +211,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return The remote Bluetooth device, or null if not in connected or
* connecting state, or if this proxy object is not connected to
* the Sap service.
+ * @hide
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
@@ -189,6 +230,7 @@ public final class BluetoothSap implements BluetoothProfile {
* Returns true if the specified Bluetooth device is connected.
* Returns false if not connected, or if this proxy object is not
* currently connected to the Sap service.
+ * @hide
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
@@ -206,6 +248,7 @@ public final class BluetoothSap implements BluetoothProfile {
/**
* Initiate connection. Initiation of outgoing connections is not
* supported for SAP server.
+ * @hide
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")" + "not supported for SAPS");
@@ -218,6 +261,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @param device Remote Bluetooth Device
* @return false on error,
* true otherwise
+ * @hide
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -238,6 +282,7 @@ public final class BluetoothSap implements BluetoothProfile {
* Get the list of connected devices. Currently at most one.
*
* @return list of connected devices
+ * @hide
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
@@ -257,6 +302,7 @@ public final class BluetoothSap implements BluetoothProfile {
* Get the list of devices matching specified states. Currently at most one.
*
* @return list of matching devices
+ * @hide
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
@@ -276,6 +322,7 @@ public final class BluetoothSap implements BluetoothProfile {
* Get connection state of device
*
* @return device connection state
+ * @hide
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
@@ -300,6 +347,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
+ * @hide
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
@@ -325,6 +373,7 @@ public final class BluetoothSap implements BluetoothProfile {
*
* @param device Bluetooth device
* @return priority of the device
+ * @hide
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 5702d11..5cf2300 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -91,9 +91,13 @@ public final class BluetoothSocket implements Closeable {
public static final int MAX_RFCOMM_CHANNEL = 30;
/*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF;
- /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */
+ /** RFCOMM socket */
public static final int TYPE_RFCOMM = 1;
+
+ /** SCO socket */
public static final int TYPE_SCO = 2;
+
+ /** L2CAP socket */
public static final int TYPE_L2CAP = 3;
/*package*/ static final int EBADFD = 77;
@@ -578,8 +582,8 @@ public final class BluetoothSocket implements Closeable {
}
/**
- * Get the type of the underlying connection
- * @return one of TYPE_
+ * Get the type of the underlying connection.
+ * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
*/
public int getConnectionType() {
return mType;
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
index 27b96bd..61b2e78 100644
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ b/core/java/android/bluetooth/le/ScanCallback.java
@@ -53,8 +53,10 @@ public abstract class ScanCallback {
/**
* Callback when a BLE advertisement has been found.
*
- * @param callbackType Determines how this callback was triggered. Could be of
- * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}
+ * @param callbackType Determines how this callback was triggered. Could be one of
+ * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES},
+ * {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or
+ * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST}
* @param result A Bluetooth LE scan result.
*/
public void onScanResult(int callbackType, ScanResult result) {
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index dad486d..4eeb577 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -59,17 +59,13 @@ public final class ScanSettings implements Parcelable {
/**
* A result callback is only triggered for the first advertisement packet received that matches
* the filter criteria.
- * @hide
*/
- @SystemApi
public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
/**
* Receive a callback when advertisements are no longer received from a device that has been
* previously reported by a first match callback.
- * @hide
*/
- @SystemApi
public static final int CALLBACK_TYPE_MATCH_LOST = 4;
@@ -78,21 +74,18 @@ public final class ScanSettings implements Parcelable {
*/
/**
* Match one advertisement per filter
- * @hide
*/
public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
/**
* Match few advertisement per filter, depends on current capability and availibility of
* the resources in hw
- * @hide
*/
public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
/**
* Match as many advertisement per filter as hw could allow, depends on current
* capability and availibility of the resources in hw
- * @hide
*/
public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
@@ -100,14 +93,12 @@ public final class ScanSettings implements Parcelable {
/**
* In Aggressive mode, hw will determine a match sooner even with feeble signal strength
* and few number of sightings/match in a duration.
- * @hide
*/
public static final int MATCH_MODE_AGGRESSIVE = 1;
/**
* For sticky mode, higher threshold of signal strength and sightings is required
* before reporting by hw
- * @hide
*/
public static final int MATCH_MODE_STICKY = 2;
@@ -324,7 +315,6 @@ public final class ScanSettings implements Parcelable {
* {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or
* {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
* @throws IllegalArgumentException If the {@code matchMode} is invalid.
- * @hide
*/
public Builder setNumOfMatches(int numOfMatches) {
if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
@@ -342,7 +332,6 @@ public final class ScanSettings implements Parcelable {
* {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or
* {@link ScanSettings#MATCH_MODE_STICKY}
* @throws IllegalArgumentException If the {@code matchMode} is invalid.
- * @hide
*/
public Builder setMatchMode(int matchMode) {
if (matchMode < MATCH_MODE_AGGRESSIVE
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 0b24594..94b0223 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -96,9 +96,9 @@ interface IPackageManager {
void removePermission(String name);
- boolean grantPermission(String packageName, String permissionName, int userId);
+ void grantPermission(String packageName, String permissionName, int userId);
- boolean revokePermission(String packageName, String permissionName, int userId);
+ void revokePermission(String packageName, String permissionName, int userId);
boolean isProtectedBroadcast(String actionName);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2d63e3f..d8c3361 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2571,10 +2571,8 @@ public class ConnectivityManager {
* method assumes that the caller has previously called {@link #registerNetworkCallback} to
* listen for network changes.
*
- * @param network{@link Network} specifying which network you're interested.
+ * @param network {@link Network} specifying which network you're interested.
* @return {@code true} on success, {@code false} if the {@link Network} is no longer valid.
- *
- * @hide
*/
public boolean requestBandwidthUpdate(Network network) {
try {
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 47e8e69..243ddf7 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -16,6 +16,9 @@
package android.os;
+import android.annotation.MainThread;
+import android.annotation.WorkerThread;
+
import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
@@ -350,6 +353,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #onPostExecute
* @see #publishProgress
*/
+ @WorkerThread
protected abstract Result doInBackground(Params... params);
/**
@@ -358,6 +362,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #onPostExecute
* @see #doInBackground
*/
+ @MainThread
protected void onPreExecute() {
}
@@ -374,6 +379,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #onCancelled(Object)
*/
@SuppressWarnings({"UnusedDeclaration"})
+ @MainThread
protected void onPostExecute(Result result) {
}
@@ -387,6 +393,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #doInBackground
*/
@SuppressWarnings({"UnusedDeclaration"})
+ @MainThread
protected void onProgressUpdate(Progress... values) {
}
@@ -405,6 +412,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #isCancelled()
*/
@SuppressWarnings({"UnusedParameters"})
+ @MainThread
protected void onCancelled(Result result) {
onCancelled();
}
@@ -421,6 +429,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #cancel(boolean)
* @see #isCancelled()
*/
+ @MainThread
protected void onCancelled() {
}
@@ -535,6 +544,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
* @see #execute(Runnable)
*/
+ @MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@@ -572,6 +582,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
*
* @see #execute(Object[])
*/
+ @MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
@@ -604,6 +615,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #execute(Object[])
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
*/
+ @MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
@@ -622,6 +634,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* @see #onProgressUpdate
* @see #doInBackground
*/
+ @WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 5e9b8c1..74699fd 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -211,8 +211,9 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
} else if (obj instanceof Parcelable[]) {
Parcelable[] array = (Parcelable[]) obj;
for (int n = array.length - 1; n >= 0; n--) {
- if ((array[n].describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+ Parcelable p = array[n];
+ if (p != null && ((p.describeContents()
+ & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
fdFound = true;
break;
}
@@ -221,7 +222,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
SparseArray<? extends Parcelable> array =
(SparseArray<? extends Parcelable>) obj;
for (int n = array.size() - 1; n >= 0; n--) {
- if ((array.valueAt(n).describeContents()
+ Parcelable p = array.valueAt(n);
+ if (p != null && (p.describeContents()
& Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
fdFound = true;
break;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 396cf19..e07e846 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -9062,5 +9062,15 @@ public final class ContactsContract {
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI,
"metadata_sync");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
}
}
diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java
index 0592a84..d7bf10c 100644
--- a/core/java/android/service/carrier/CarrierMessagingService.java
+++ b/core/java/android/service/carrier/CarrierMessagingService.java
@@ -80,6 +80,11 @@ public abstract class CarrierMessagingService extends Service {
*/
public static final int DOWNLOAD_STATUS_ERROR = 2;
+ /**
+ * Flag to request SMS delivery status report.
+ */
+ public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1;
+
private final ICarrierMessagingWrapper mWrapper = new ICarrierMessagingWrapper();
/**
@@ -103,12 +108,14 @@ public abstract class CarrierMessagingService extends Service {
/**
* Override this method to intercept text SMSs sent from the device.
+ * @deprecated Override {@link #onSendTextSms} below instead.
*
* @param text the text to send
* @param subId SMS subscription ID of the SIM
* @param destAddress phone number of the recipient of the message
* @param callback result callback. Call with a {@link SendSmsResult}.
*/
+ @Deprecated
public void onSendTextSms(
@NonNull String text, int subId, @NonNull String destAddress,
@NonNull ResultCallback<SendSmsResult> callback) {
@@ -120,7 +127,25 @@ public abstract class CarrierMessagingService extends Service {
}
/**
+ * Override this method to intercept text SMSs sent from the device.
+ *
+ * @param text the text to send
+ * @param subId SMS subscription ID of the SIM
+ * @param destAddress phone number of the recipient of the message
+ * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
+ * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
+ * @param callback result callback. Call with a {@link SendSmsResult}.
+ */
+ public void onSendTextSms(
+ @NonNull String text, int subId, @NonNull String destAddress,
+ int sendSmsFlag, @NonNull ResultCallback<SendSmsResult> callback) {
+ // optional
+ onSendTextSms(text, subId, destAddress, callback);
+ }
+
+ /**
* Override this method to intercept binary SMSs sent from the device.
+ * @deprecated Override {@link #onSendDataSms} below instead.
*
* @param data the binary content
* @param subId SMS subscription ID of the SIM
@@ -128,6 +153,7 @@ public abstract class CarrierMessagingService extends Service {
* @param destPort the destination port
* @param callback result callback. Call with a {@link SendSmsResult}.
*/
+ @Deprecated
public void onSendDataSms(@NonNull byte[] data, int subId,
@NonNull String destAddress, int destPort,
@NonNull ResultCallback<SendSmsResult> callback) {
@@ -139,13 +165,33 @@ public abstract class CarrierMessagingService extends Service {
}
/**
+ * Override this method to intercept binary SMSs sent from the device.
+ *
+ * @param data the binary content
+ * @param subId SMS subscription ID of the SIM
+ * @param destAddress phone number of the recipient of the message
+ * @param destPort the destination port
+ * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
+ * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
+ * @param callback result callback. Call with a {@link SendSmsResult}.
+ */
+ public void onSendDataSms(@NonNull byte[] data, int subId,
+ @NonNull String destAddress, int destPort, int sendSmsFlag,
+ @NonNull ResultCallback<SendSmsResult> callback) {
+ // optional
+ onSendDataSms(data, subId, destAddress, destPort, callback);
+ }
+
+ /**
* Override this method to intercept long SMSs sent from the device.
+ * @deprecated Override {@link #onSendMultipartTextSms} below instead.
*
* @param parts a {@link List} of the message parts
* @param subId SMS subscription ID of the SIM
* @param destAddress phone number of the recipient of the message
* @param callback result callback. Call with a {@link SendMultipartSmsResult}.
*/
+ @Deprecated
public void onSendMultipartTextSms(@NonNull List<String> parts,
int subId, @NonNull String destAddress,
@NonNull ResultCallback<SendMultipartSmsResult> callback) {
@@ -158,6 +204,23 @@ public abstract class CarrierMessagingService extends Service {
}
/**
+ * Override this method to intercept long SMSs sent from the device.
+ *
+ * @param parts a {@link List} of the message parts
+ * @param subId SMS subscription ID of the SIM
+ * @param destAddress phone number of the recipient of the message
+ * @param sendSmsFlag Flag for sending SMS. Acceptable values are 0 and
+ * {@link #SEND_FLAG_REQUEST_DELIVERY_STATUS}.
+ * @param callback result callback. Call with a {@link SendMultipartSmsResult}.
+ */
+ public void onSendMultipartTextSms(@NonNull List<String> parts,
+ int subId, @NonNull String destAddress, int sendSmsFlag,
+ @NonNull ResultCallback<SendMultipartSmsResult> callback) {
+ // optional
+ onSendMultipartTextSms(parts, subId, destAddress, callback);
+ }
+
+ /**
* Override this method to intercept MMSs sent from the device.
*
* @param pduUri the content provider URI of the PDU to send
@@ -355,8 +418,9 @@ public abstract class CarrierMessagingService extends Service {
@Override
public void sendTextSms(String text, int subId, String destAddress,
- final ICarrierMessagingCallback callback) {
- onSendTextSms(text, subId, destAddress, new ResultCallback<SendSmsResult>() {
+ int sendSmsFlag, final ICarrierMessagingCallback callback) {
+ onSendTextSms(text, subId, destAddress, sendSmsFlag,
+ new ResultCallback<SendSmsResult>() {
@Override
public void onReceiveResult(final SendSmsResult result) throws RemoteException {
callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
@@ -366,8 +430,9 @@ public abstract class CarrierMessagingService extends Service {
@Override
public void sendDataSms(byte[] data, int subId, String destAddress, int destPort,
- final ICarrierMessagingCallback callback) {
- onSendDataSms(data, subId, destAddress, destPort, new ResultCallback<SendSmsResult>() {
+ int sendSmsFlag, final ICarrierMessagingCallback callback) {
+ onSendDataSms(data, subId, destAddress, destPort, sendSmsFlag,
+ new ResultCallback<SendSmsResult>() {
@Override
public void onReceiveResult(final SendSmsResult result) throws RemoteException {
callback.onSendSmsComplete(result.getSendStatus(), result.getMessageRef());
@@ -377,8 +442,8 @@ public abstract class CarrierMessagingService extends Service {
@Override
public void sendMultipartTextSms(List<String> parts, int subId, String destAddress,
- final ICarrierMessagingCallback callback) {
- onSendMultipartTextSms(parts, subId, destAddress,
+ int sendSmsFlag, final ICarrierMessagingCallback callback) {
+ onSendMultipartTextSms(parts, subId, destAddress, sendSmsFlag,
new ResultCallback<SendMultipartSmsResult>() {
@Override
public void onReceiveResult(final SendMultipartSmsResult result)
diff --git a/core/java/android/service/carrier/ICarrierMessagingService.aidl b/core/java/android/service/carrier/ICarrierMessagingService.aidl
index 40a9047..2d96c3d 100644
--- a/core/java/android/service/carrier/ICarrierMessagingService.aidl
+++ b/core/java/android/service/carrier/ICarrierMessagingService.aidl
@@ -48,9 +48,10 @@ oneway interface ICarrierMessagingService {
* @param text the text to send
* @param subId SMS subscription ID of the SIM
* @param destAddress phone number of the recipient of the message
+ * @param sendSmsFlag flag for sending SMS
* @param callback the callback to notify upon completion
*/
- void sendTextSms(String text, int subId, String destAddress,
+ void sendTextSms(String text, int subId, String destAddress, int sendSmsFlag,
in ICarrierMessagingCallback callback);
/**
@@ -62,10 +63,11 @@ oneway interface ICarrierMessagingService {
* @param subId SMS subscription ID of the SIM
* @param destAddress phone number of the recipient of the message
* @param destPort port number of the recipient of the message
+ * @param sendSmsFlag flag for sending SMS
* @param callback the callback to notify upon completion
*/
void sendDataSms(in byte[] data, int subId, String destAddress, int destPort,
- in ICarrierMessagingCallback callback);
+ int sendSmsFlag, in ICarrierMessagingCallback callback);
/**
* Request sending a new multi-part text SMS from the device.
@@ -75,10 +77,11 @@ oneway interface ICarrierMessagingService {
* @param parts the parts of the multi-part text SMS to send
* @param subId SMS subscription ID of the SIM
* @param destAddress phone number of the recipient of the message
+ * @param sendSmsFlag flag for sending SMS
* @param callback the callback to notify upon completion
*/
void sendMultipartTextSms(in List<String> parts, int subId, String destAddress,
- in ICarrierMessagingCallback callback);
+ int sendSmsFlag, in ICarrierMessagingCallback callback);
/**
* Request sending a new MMS PDU from the device.
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f09f4d2..968cd72 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -692,7 +692,6 @@ public class ZenModeConfig implements Parcelable {
.authority(SYSTEM_AUTHORITY)
.appendPath(EVENT_PATH)
.appendQueryParameter("calendar", Long.toString(event.calendar))
- .appendQueryParameter("attendance", Integer.toString(event.attendance))
.appendQueryParameter("reply", Integer.toString(event.reply))
.build();
}
@@ -710,22 +709,16 @@ public class ZenModeConfig implements Parcelable {
if (!isEvent) return null;
final EventInfo rt = new EventInfo();
rt.calendar = tryParseLong(conditionId.getQueryParameter("calendar"), 0L);
- rt.attendance = tryParseInt(conditionId.getQueryParameter("attendance"), 0);
rt.reply = tryParseInt(conditionId.getQueryParameter("reply"), 0);
return rt;
}
public static class EventInfo {
- public static final int ATTENDANCE_REQUIRED_OR_OPTIONAL = 0;
- public static final int ATTENDANCE_REQUIRED = 1;
- public static final int ATTENDANCE_OPTIONAL = 2;
-
- public static final int REPLY_ANY = 0;
- public static final int REPLY_ANY_EXCEPT_NO = 1;
+ public static final int REPLY_ANY_EXCEPT_NO = 0;
+ public static final int REPLY_YES_OR_MAYBE = 1;
public static final int REPLY_YES = 2;
public long calendar; // CalendarContract.Calendars._ID, or 0 for any
- public int attendance;
public int reply;
@Override
@@ -738,14 +731,12 @@ public class ZenModeConfig implements Parcelable {
if (!(o instanceof EventInfo)) return false;
final EventInfo other = (EventInfo) o;
return calendar == other.calendar
- && attendance == other.attendance
&& reply == other.reply;
}
public EventInfo copy() {
final EventInfo rt = new EventInfo();
rt.calendar = calendar;
- rt.attendance = attendance;
rt.reply = reply;
return rt;
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index c942042..ebc2aac 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -792,6 +792,9 @@ public abstract class Transition implements Cloneable {
* views are ignored and only the ids are used).
*/
boolean isValidTarget(View target) {
+ if (target == null) {
+ return false;
+ }
int targetId = target.getId();
if (mTargetIdExcludes != null && mTargetIdExcludes.contains(targetId)) {
return false;
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index cd68fd1..ed7fd86 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -19,12 +19,17 @@ package android.transition;
import com.android.internal.R;
import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.Animator.AnimatorPauseListener;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+
/**
* This transition tracks changes to the visibility of target views in the
* start and end scenes. Visibility is determined not just by the
@@ -286,6 +291,12 @@ public abstract class Visibility extends Transition {
return null;
}
}
+ final boolean isForcedVisibility = mForcedStartVisibility != -1 ||
+ mForcedEndVisibility != -1;
+ if (isForcedVisibility) {
+ // Make sure that we reverse the effect of onDisappear's setTransitionAlpha(0)
+ endValues.view.setTransitionAlpha(1);
+ }
return onAppear(sceneRoot, endValues.view, startValues, endValues);
}
@@ -418,9 +429,9 @@ public abstract class Visibility extends Transition {
sceneRoot.getOverlay().remove(overlayView);
} else {
final View finalOverlayView = overlayView;
- animator.addListener(new AnimatorListenerAdapter() {
+ addListener(new TransitionListenerAdapter() {
@Override
- public void onAnimationEnd(Animator animation) {
+ public void onTransitionEnd(Transition transition) {
finalSceneRoot.getOverlay().remove(finalOverlayView);
}
});
@@ -438,40 +449,10 @@ public abstract class Visibility extends Transition {
}
Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
if (animator != null) {
- final View finalViewToKeep = viewToKeep;
- animator.addListener(new AnimatorListenerAdapter() {
- boolean mCanceled = false;
-
- @Override
- public void onAnimationPause(Animator animation) {
- if (!mCanceled && !isForcedVisibility) {
- finalViewToKeep.setVisibility(finalVisibility);
- }
- }
-
- @Override
- public void onAnimationResume(Animator animation) {
- if (!mCanceled && !isForcedVisibility) {
- finalViewToKeep.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCanceled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mCanceled) {
- if (isForcedVisibility) {
- finalViewToKeep.setTransitionAlpha(0);
- } else {
- finalViewToKeep.setVisibility(finalVisibility);
- }
- }
- }
- });
+ DisappearListener disappearListener = new DisappearListener(viewToKeep,
+ finalVisibility, isForcedVisibility);
+ animator.addListener(disappearListener);
+ addListener(disappearListener);
} else if (!isForcedVisibility) {
viewToKeep.setVisibility(originalVisibility);
}
@@ -517,4 +498,68 @@ public abstract class Visibility extends Transition {
TransitionValues endValues) {
return null;
}
+
+ private static class DisappearListener
+ extends TransitionListenerAdapter implements AnimatorListener, AnimatorPauseListener {
+ private final boolean mIsForcedVisibility;
+ private final View mView;
+ private final int mFinalVisibility;
+
+ boolean mCanceled = false;
+
+ public DisappearListener(View view, int finalVisibility, boolean isForcedVisibility) {
+ this.mView = view;
+ this.mIsForcedVisibility = isForcedVisibility;
+ this.mFinalVisibility = finalVisibility;
+ }
+
+ @Override
+ public void onAnimationPause(Animator animation) {
+ if (!mCanceled && !mIsForcedVisibility) {
+ mView.setVisibility(mFinalVisibility);
+ }
+ }
+
+ @Override
+ public void onAnimationResume(Animator animation) {
+ if (!mCanceled && !mIsForcedVisibility) {
+ mView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ hideViewWhenNotCanceled();
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ hideViewWhenNotCanceled();
+ }
+
+ private void hideViewWhenNotCanceled() {
+ if (!mCanceled) {
+ if (mIsForcedVisibility) {
+ mView.setTransitionAlpha(0);
+ } else {
+ mView.setVisibility(mFinalVisibility);
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 963b7a6..75dc0a2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28,6 +28,7 @@ import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
+import android.annotation.UiThread;
import android.content.ClipData;
import android.content.Context;
import android.content.ContextWrapper;
@@ -700,6 +701,7 @@ import java.util.concurrent.atomic.AtomicInteger;
*
* @see android.view.ViewGroup
*/
+@UiThread
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
private static final boolean DBG = false;
@@ -8595,7 +8597,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
if (isNestedScrollingEnabled()
&& (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
- || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
+ || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
+ || action == R.id.accessibilityActionScrollUp
+ || action == R.id.accessibilityActionScrollLeft
+ || action == R.id.accessibilityActionScrollDown
+ || action == R.id.accessibilityActionScrollRight)) {
if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
return true;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index ef57dc3..f240fd6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -18,6 +18,7 @@ package android.view;
import android.animation.LayoutTransition;
import android.annotation.IdRes;
+import android.annotation.UiThread;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -105,6 +106,7 @@ import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
* @attr ref android.R.styleable#ViewGroup_splitMotionEvents
* @attr ref android.R.styleable#ViewGroup_layoutMode
*/
+@UiThread
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
private static final String TAG = "ViewGroup";
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index bf4b7ae..c785149 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3500,6 +3500,30 @@ public class AccessibilityNodeInfo implements Parcelable {
new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
/**
+ * Action to scroll the node content up.
+ */
+ public static final AccessibilityAction ACTION_SCROLL_UP =
+ new AccessibilityAction(R.id.accessibilityActionScrollUp, null);
+
+ /**
+ * Action to scroll the node content left.
+ */
+ public static final AccessibilityAction ACTION_SCROLL_LEFT =
+ new AccessibilityAction(R.id.accessibilityActionScrollLeft, null);
+
+ /**
+ * Action to scroll the node content down.
+ */
+ public static final AccessibilityAction ACTION_SCROLL_DOWN =
+ new AccessibilityAction(R.id.accessibilityActionScrollDown, null);
+
+ /**
+ * Action to scroll the node content right.
+ */
+ public static final AccessibilityAction ACTION_SCROLL_RIGHT =
+ new AccessibilityAction(R.id.accessibilityActionScrollRight, null);
+
+ /**
* Action that stylus button presses the node.
*/
public static final AccessibilityAction ACTION_STYLUS_BUTTON_PRESS =
@@ -3531,6 +3555,10 @@ public class AccessibilityNodeInfo implements Parcelable {
sStandardActions.add(ACTION_SET_TEXT);
sStandardActions.add(ACTION_SHOW_ON_SCREEN);
sStandardActions.add(ACTION_SCROLL_TO_POSITION);
+ sStandardActions.add(ACTION_SCROLL_UP);
+ sStandardActions.add(ACTION_SCROLL_LEFT);
+ sStandardActions.add(ACTION_SCROLL_DOWN);
+ sStandardActions.add(ACTION_SCROLL_RIGHT);
sStandardActions.add(ACTION_STYLUS_BUTTON_PRESS);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1df43d0..c57a53a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1506,10 +1506,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (isEnabled()) {
if (canScrollUp()) {
info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_UP);
info.setScrollable(true);
}
if (canScrollDown()) {
info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_DOWN);
info.setScrollable(true);
}
}
@@ -1537,14 +1539,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
return true;
}
switch (action) {
- case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ case R.id.accessibilityActionScrollDown: {
if (isEnabled() && getLastVisiblePosition() < getCount() - 1) {
final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION);
return true;
}
} return false;
- case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ case R.id.accessibilityActionScrollUp: {
if (isEnabled() && mFirstPosition > 0) {
final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION);
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java
index 30c74c0..d8ce60c 100644
--- a/core/java/android/widget/CursorAdapter.java
+++ b/core/java/android/widget/CursorAdapter.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.WorkerThread;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -425,6 +426,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable,
* @see #getFilterQueryProvider()
* @see #setFilterQueryProvider(android.widget.FilterQueryProvider)
*/
+ @WorkerThread
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (mFilterQueryProvider != null) {
return mFilterQueryProvider.runQuery(constraint);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 9b36b84..8d35b83 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -318,6 +318,7 @@ public class Editor {
}
getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
+ resumeBlink();
}
void onDetachedFromWindow() {
@@ -327,9 +328,7 @@ public class Editor {
hideError();
}
- if (mBlink != null) {
- mBlink.removeCallbacks(mBlink);
- }
+ suspendBlink();
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.onDetached();
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 324c2aa..0879c5d 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -40,6 +40,8 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
+import com.android.internal.R;
+
import java.util.List;
/**
@@ -768,7 +770,8 @@ public class HorizontalScrollView extends FrameLayout {
return true;
}
switch (action) {
- case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ case R.id.accessibilityActionScrollRight: {
if (!isEnabled()) {
return false;
}
@@ -779,7 +782,8 @@ public class HorizontalScrollView extends FrameLayout {
return true;
}
} return false;
- case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ case R.id.accessibilityActionScrollLeft: {
if (!isEnabled()) {
return false;
}
@@ -807,10 +811,12 @@ public class HorizontalScrollView extends FrameLayout {
if (scrollRange > 0) {
info.setScrollable(true);
if (isEnabled() && mScrollX > 0) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_LEFT);
}
if (isEnabled() && mScrollX < scrollRange) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_RIGHT);
}
}
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 10e4db3..5953a98 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -618,7 +618,15 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
// remove based on both its position as well as it's current memory usage, as well
// as whether it was directly requested vs. whether it was preloaded by our caching
// mechanism.
- mIndexRemoteViews.remove(getFarthestPositionFrom(pruneFromPosition, visibleWindow));
+ int trimIndex = getFarthestPositionFrom(pruneFromPosition, visibleWindow);
+
+ // Need to check that this is a valid index, to cover the case where you have only
+ // a single view in the cache, but it's larger than the max memory limit
+ if (trimIndex < 0) {
+ break;
+ }
+
+ mIndexRemoteViews.remove(trimIndex);
}
// Update the metadata cache
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 2026169..98d61d3 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -819,7 +819,8 @@ public class ScrollView extends FrameLayout {
return false;
}
switch (action) {
- case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ case R.id.accessibilityActionScrollDown: {
final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop;
final int targetScrollY = Math.min(mScrollY + viewportHeight, getScrollRange());
if (targetScrollY != mScrollY) {
@@ -827,7 +828,8 @@ public class ScrollView extends FrameLayout {
return true;
}
} return false;
- case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ case R.id.accessibilityActionScrollUp: {
final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop;
final int targetScrollY = Math.max(mScrollY - viewportHeight, 0);
if (targetScrollY != mScrollY) {
@@ -853,10 +855,13 @@ public class ScrollView extends FrameLayout {
if (scrollRange > 0) {
info.setScrollable(true);
if (mScrollY > 0) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ info.addAction(
+ AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
}
if (mScrollY < scrollRange) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN);
}
}
}
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 441e640..e76302b 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -47,6 +47,8 @@ import android.view.animation.Interpolator;
import android.widget.EdgeEffect;
import android.widget.Scroller;
+import com.android.internal.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -2720,10 +2722,12 @@ public class ViewPager extends ViewGroup {
if (canScrollHorizontally(1)) {
info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_RIGHT);
}
if (canScrollHorizontally(-1)) {
info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_LEFT);
}
}
@@ -2735,12 +2739,14 @@ public class ViewPager extends ViewGroup {
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ case R.id.accessibilityActionScrollRight:
if (canScrollHorizontally(1)) {
setCurrentItem(mCurItem + 1);
return true;
}
return false;
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ case R.id.accessibilityActionScrollLeft:
if (canScrollHorizontally(-1)) {
setCurrentItem(mCurItem - 1);
return true;
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 5c95f8a..8ae2e3b 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1,3 +1,7 @@
+#define LOG_TAG "Bitmap"
+
+#include "Bitmap.h"
+
#include "Paint.h"
#include "SkBitmap.h"
#include "SkPixelRef.h"
@@ -14,11 +18,322 @@
#include "android_util_Binder.h"
#include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
+#include <Caches.h>
#include "core_jni_helpers.h"
#include <jni.h>
+namespace android {
+
+class WrappedPixelRef : public SkPixelRef {
+public:
+ WrappedPixelRef(Bitmap* wrapper, void* storage,
+ const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
+ : SkPixelRef(info)
+ , mBitmap(*wrapper)
+ , mStorage(storage) {
+ reconfigure(info, rowBytes, ctable);
+ }
+
+ ~WrappedPixelRef() {
+ // Tell SkRefCnt that everything is as it expects by forcing
+ // the refcnt to 1
+ internal_dispose_restore_refcnt_to_1();
+ SkSafeUnref(mColorTable);
+ }
+
+ void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) {
+ if (kIndex_8_SkColorType != info.colorType()) {
+ ctable = nullptr;
+ }
+ mRowBytes = rowBytes;
+ if (mColorTable != ctable) {
+ SkSafeUnref(mColorTable);
+ mColorTable = ctable;
+ SkSafeRef(mColorTable);
+ }
+ // Dirty hack is dirty
+ // TODO: Figure something out here, Skia's current design makes this
+ // really hard to work with. Skia really, really wants immutable objects,
+ // but with the nested-ref-count hackery going on that's just not
+ // feasible without going insane trying to figure it out
+ SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
+ *myInfo = info;
+
+ // Docs say to only call this in the ctor, but we're going to call
+ // it anyway even if this isn't always the ctor.
+ // TODO: Fix this too as part of the above TODO
+ setPreLocked(mStorage, mRowBytes, mColorTable);
+ }
+
+ // Can't mark as override since SkPixelRef::rowBytes isn't virtual
+ // but that's OK since we just want BitmapWrapper to be able to rely
+ // on calling rowBytes() on an unlocked pixelref, which it will be
+ // doing on a WrappedPixelRef type, not a SkPixelRef, so static
+ // dispatching will do what we want.
+ size_t rowBytes() const { return mRowBytes; }
+ SkColorTable* colorTable() const { return mColorTable; }
+
+ bool hasHardwareMipMap() const {
+ return mHasHardwareMipMap;
+ }
+
+ void setHasHardwareMipMap(bool hasMipMap) {
+ mHasHardwareMipMap = hasMipMap;
+ }
+
+protected:
+ virtual bool onNewLockPixels(LockRec* rec) override {
+ rec->fPixels = mStorage;
+ rec->fRowBytes = mRowBytes;
+ rec->fColorTable = mColorTable;
+ return true;
+ }
+
+ virtual void onUnlockPixels() override {
+ // nothing
+ }
+
+ virtual size_t getAllocatedSizeInBytes() const override {
+ return info().getSafeSize(mRowBytes);
+ }
+
+private:
+ Bitmap& mBitmap;
+ void* mStorage;
+ size_t mRowBytes = 0;
+ SkColorTable* mColorTable = nullptr;
+ bool mHasHardwareMipMap = false;
+
+ virtual void internal_dispose() const override {
+ mBitmap.onStrongRefDestroyed();
+ }
+};
+
+Bitmap::Bitmap(JNIEnv* env, jbyteArray storageObj, void* address,
+ const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
+ : mPixelStorageType(PixelStorageType::Java) {
+ env->GetJavaVM(&mPixelStorage.java.jvm);
+ mPixelStorage.java.jweakRef = env->NewWeakGlobalRef(storageObj);
+ mPixelStorage.java.jstrongRef = nullptr;
+ mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
+ // Note: this will trigger a call to onStrongRefDestroyed(), but
+ // we want the pixel ref to have a ref count of 0 at this point
+ mPixelRef->unref();
+}
+
+Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
+ const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
+ : mPixelStorageType(PixelStorageType::External) {
+ mPixelStorage.external.address = address;
+ mPixelStorage.external.context = context;
+ mPixelStorage.external.freeFunc = freeFunc;
+ mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
+ // Note: this will trigger a call to onStrongRefDestroyed(), but
+ // we want the pixel ref to have a ref count of 0 at this point
+ mPixelRef->unref();
+}
+
+Bitmap::~Bitmap() {
+ doFreePixels();
+}
+
+void Bitmap::freePixels() {
+ AutoMutex _lock(mLock);
+ if (mPinnedRefCount == 0) {
+ doFreePixels();
+ mPixelStorageType = PixelStorageType::Invalid;
+ }
+}
+
+void Bitmap::doFreePixels() {
+ switch (mPixelStorageType) {
+ case PixelStorageType::Invalid:
+ // already free'd, nothing to do
+ break;
+ case PixelStorageType::External:
+ mPixelStorage.external.freeFunc(mPixelStorage.external.address,
+ mPixelStorage.external.context);
+ break;
+ case PixelStorageType::Java:
+ JNIEnv* env = jniEnv();
+ LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef,
+ "Deleting a bitmap wrapper while there are outstanding strong "
+ "references! mPinnedRefCount = %d", mPinnedRefCount);
+ env->DeleteWeakGlobalRef(mPixelStorage.java.jweakRef);
+ break;
+ }
+
+ if (android::uirenderer::Caches::hasInstance()) {
+ android::uirenderer::Caches::getInstance().textureCache.releaseTexture(
+ mPixelRef->getStableID());
+ }
+}
+
+bool Bitmap::hasHardwareMipMap() {
+ return mPixelRef->hasHardwareMipMap();
+}
+
+void Bitmap::setHasHardwareMipMap(bool hasMipMap) {
+ mPixelRef->setHasHardwareMipMap(hasMipMap);
+}
+
+const SkImageInfo& Bitmap::info() const {
+ assertValid();
+ return mPixelRef->info();
+}
+
+size_t Bitmap::rowBytes() const {
+ return mPixelRef->rowBytes();
+}
+
+SkPixelRef* Bitmap::pixelRef() const {
+ assertValid();
+ return mPixelRef.get();
+}
+
+void Bitmap::reconfigure(const SkImageInfo& info, size_t rowBytes,
+ SkColorTable* ctable) {
+ mPixelRef->reconfigure(info, rowBytes, ctable);
+}
+
+void Bitmap::reconfigure(const SkImageInfo& info) {
+ mPixelRef->reconfigure(info, mPixelRef->rowBytes(), mPixelRef->colorTable());
+}
+
+void Bitmap::detachFromJava() {
+ bool disposeSelf;
+ {
+ android::AutoMutex _lock(mLock);
+ mAttachedToJava = false;
+ disposeSelf = shouldDisposeSelfLocked();
+ }
+ if (disposeSelf) {
+ delete this;
+ }
+}
+
+bool Bitmap::shouldDisposeSelfLocked() {
+ return mPinnedRefCount == 0 && !mAttachedToJava;
+}
+
+JNIEnv* Bitmap::jniEnv() {
+ JNIEnv* env;
+ auto success = mPixelStorage.java.jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+ LOG_ALWAYS_FATAL_IF(success != JNI_OK,
+ "Failed to get JNIEnv* from JVM: %p", mPixelStorage.java.jvm);
+ return env;
+}
+
+void Bitmap::onStrongRefDestroyed() {
+ bool disposeSelf = false;
+ {
+ android::AutoMutex _lock(mLock);
+ if (mPinnedRefCount > 0) {
+ mPinnedRefCount--;
+ if (mPinnedRefCount == 0) {
+ unpinPixelsLocked();
+ disposeSelf = shouldDisposeSelfLocked();
+ }
+ }
+ }
+ if (disposeSelf) {
+ delete this;
+ }
+}
+
+void Bitmap::pinPixelsLocked() {
+ switch (mPixelStorageType) {
+ case PixelStorageType::Invalid:
+ LOG_ALWAYS_FATAL("Cannot pin invalid pixels!");
+ break;
+ case PixelStorageType::External:
+ // Nothing to do
+ break;
+ case PixelStorageType::Java: {
+ JNIEnv* env = jniEnv();
+ if (!mPixelStorage.java.jstrongRef) {
+ mPixelStorage.java.jstrongRef = reinterpret_cast<jbyteArray>(
+ env->NewGlobalRef(mPixelStorage.java.jweakRef));
+ if (!mPixelStorage.java.jstrongRef) {
+ LOG_ALWAYS_FATAL("Failed to acquire strong reference to pixels");
+ }
+ }
+ break;
+ }
+ }
+}
+
+void Bitmap::unpinPixelsLocked() {
+ switch (mPixelStorageType) {
+ case PixelStorageType::Invalid:
+ LOG_ALWAYS_FATAL("Cannot unpin invalid pixels!");
+ break;
+ case PixelStorageType::External:
+ // Don't need to do anything
+ break;
+ case PixelStorageType::Java: {
+ JNIEnv* env = jniEnv();
+ if (mPixelStorage.java.jstrongRef) {
+ env->DeleteGlobalRef(mPixelStorage.java.jstrongRef);
+ mPixelStorage.java.jstrongRef = nullptr;
+ }
+ break;
+ }
+ }
+}
+
+void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
+ assertValid();
+ android::AutoMutex _lock(mLock);
+ mPixelRef->ref();
+ if (mPixelRef->unique()) {
+ // We just restored this from 0, pin the pixels and inc the strong count
+ // Note that there *might be* an incoming onStrongRefDestroyed from whatever
+ // last unref'd
+ pinPixelsLocked();
+ mPinnedRefCount++;
+ }
+ // Safe because mPixelRef is a WrappedPixelRef type, otherwise rowBytes()
+ // would require locking the pixels first.
+ outBitmap->setInfo(mPixelRef->info(), mPixelRef->rowBytes());
+ outBitmap->setPixelRef(mPixelRef.get())->unref();
+ outBitmap->setHasHardwareMipMap(hasHardwareMipMap());
+}
+
+void Bitmap::assertValid() const {
+ LOG_ALWAYS_FATAL_IF(mPixelStorageType == PixelStorageType::Invalid,
+ "Error, cannot access an invalid/free'd bitmap here!");
+}
+
+} // namespace android
+
+using namespace android;
+
+// Convenience class that does not take a global ref on the pixels, relying
+// on the caller already having a local JNI ref
+class LocalScopedBitmap {
+public:
+ LocalScopedBitmap(jlong bitmapHandle)
+ : mBitmap(reinterpret_cast<Bitmap*>(bitmapHandle)) {}
+
+ Bitmap* operator->() {
+ return mBitmap;
+ }
+
+ void* pixels() {
+ return mBitmap->pixelRef()->pixels();
+ }
+
+ bool valid() {
+ return mBitmap && mBitmap->valid();
+ }
+
+private:
+ Bitmap* mBitmap;
+};
+
///////////////////////////////////////////////////////////////////////////////
// Conversions to/from SkColor, for get/setPixels, and the create method, which
// is basically like setPixels
@@ -328,8 +643,8 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));
- jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
- if (NULL == buff) {
+ Bitmap* nativeBitmap = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
+ if (!nativeBitmap) {
return NULL;
}
@@ -338,39 +653,41 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
0, 0, width, height, bitmap);
}
- return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
- getPremulBitmapCreateFlags(isMutable), NULL, NULL);
+ return GraphicsJNI::createBitmap(env, nativeBitmap,
+ getPremulBitmapCreateFlags(isMutable));
}
static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
jint dstConfigHandle, jboolean isMutable) {
- const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
+ SkBitmap src;
+ reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
SkBitmap result;
JavaPixelAllocator allocator(env);
- if (!src->copyTo(&result, dstCT, &allocator)) {
+ if (!src.copyTo(&result, dstCT, &allocator)) {
return NULL;
}
- return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
- getPremulBitmapCreateFlags(isMutable), NULL, NULL);
+ Bitmap* bitmap = allocator.getStorageObjAndReset();
+ return GraphicsJNI::createBitmap(env, bitmap,
+ getPremulBitmapCreateFlags(isMutable));
}
static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- delete bitmap;
+ LocalScopedBitmap bitmap(bitmapHandle);
+ bitmap->detachFromJava();
}
static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- bitmap->setPixels(NULL, NULL);
+ LocalScopedBitmap bitmap(bitmapHandle);
+ bitmap->freePixels();
return JNI_TRUE;
}
static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
jint width, jint height, jint configHandle, jint allocSize,
jboolean requestPremul) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ LocalScopedBitmap bitmap(bitmapHandle);
SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
// ARGB_4444 is a deprecated format, convert automatically to 8888
@@ -383,11 +700,9 @@ static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
doThrowIAE(env, "Bitmap not large enough to support new configuration");
return;
}
- SkPixelRef* ref = bitmap->pixelRef();
- ref->ref();
SkAlphaType alphaType;
- if (bitmap->colorType() != kRGB_565_SkColorType
- && bitmap->alphaType() == kOpaque_SkAlphaType) {
+ if (bitmap->info().colorType() != kRGB_565_SkColorType
+ && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
// If the original bitmap was set to opaque, keep that setting, unless it
// was 565, which is required to be opaque.
alphaType = kOpaque_SkAlphaType;
@@ -395,22 +710,7 @@ static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
// Otherwise respect the premultiplied request.
alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
}
- bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType));
- // FIXME: Skia thinks of an SkPixelRef as having a constant SkImageInfo (except for
- // its alphatype), so it would make more sense from Skia's perspective to create a
- // new SkPixelRef. That said, libhwui uses the pointer to the SkPixelRef as a key
- // for its cache, so it won't realize this is the same Java Bitmap.
- SkImageInfo& info = const_cast<SkImageInfo&>(ref->info());
- // Use the updated from the SkBitmap, which may have corrected an invalid alphatype.
- // (e.g. 565 non-opaque)
- info = bitmap->info();
- bitmap->setPixelRef(ref);
-
- // notifyPixelsChanged will increment the generation ID even though the actual pixel data
- // hasn't been touched. This signals the renderer that the bitmap (including width, height,
- // colortype and alphatype) has changed.
- ref->notifyPixelsChanged();
- ref->unref();
+ bitmap->reconfigure(SkImageInfo::Make(width, height, colorType, alphaType));
}
// These must match the int values in Bitmap.java
@@ -423,7 +723,8 @@ enum JavaEncodeFormat {
static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
jint format, jint quality,
jobject jstream, jbyteArray jstorage) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+
+ LocalScopedBitmap bitmap(bitmapHandle);
SkImageEncoder::Type fm;
switch (format) {
@@ -440,92 +741,92 @@ static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
return JNI_FALSE;
}
- bool success = false;
- if (NULL != bitmap) {
- SkAutoLockPixels alp(*bitmap);
+ if (!bitmap.valid()) {
+ return JNI_FALSE;
+ }
- if (NULL == bitmap->getPixels()) {
- return JNI_FALSE;
- }
+ bool success = false;
- SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
- if (NULL == strm) {
- return JNI_FALSE;
- }
+ std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
+ if (!strm.get()) {
+ return JNI_FALSE;
+ }
- SkImageEncoder* encoder = SkImageEncoder::Create(fm);
- if (NULL != encoder) {
- success = encoder->encodeStream(strm, *bitmap, quality);
- delete encoder;
- }
- delete strm;
+ std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
+ if (encoder.get()) {
+ SkBitmap skbitmap;
+ bitmap->getSkBitmap(&skbitmap);
+ success = encoder->encodeStream(strm.get(), skbitmap, quality);
}
return success ? JNI_TRUE : JNI_FALSE;
}
static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- bitmap->eraseColor(color);
+ LocalScopedBitmap bitmap(bitmapHandle);
+ SkBitmap skBitmap;
+ bitmap->getSkBitmap(&skBitmap);
+ skBitmap.eraseColor(color);
}
static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ LocalScopedBitmap bitmap(bitmapHandle);
return static_cast<jint>(bitmap->rowBytes());
}
static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->colorType());
+ LocalScopedBitmap bitmap(bitmapHandle);
+ return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
}
static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return static_cast<jint>(bitmap->getGenerationID());
+ LocalScopedBitmap bitmap(bitmapHandle);
+ return static_cast<jint>(bitmap->pixelRef()->getGenerationID());
}
static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- if (bitmap->alphaType() == kPremul_SkAlphaType) {
+ LocalScopedBitmap bitmap(bitmapHandle);
+ if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
return JNI_TRUE;
}
return JNI_FALSE;
}
static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return !bitmap->isOpaque() ? JNI_TRUE : JNI_FALSE;
+ LocalScopedBitmap bitmap(bitmapHandle);
+ return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
}
static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
jboolean hasAlpha, jboolean requestPremul) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ LocalScopedBitmap bitmap(bitmapHandle);
if (hasAlpha) {
- bitmap->setAlphaType(requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
+ bitmap->pixelRef()->changeAlphaType(
+ requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
} else {
- bitmap->setAlphaType(kOpaque_SkAlphaType);
+ bitmap->pixelRef()->changeAlphaType(kOpaque_SkAlphaType);
}
}
static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
jboolean isPremul) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- if (!bitmap->isOpaque()) {
+ LocalScopedBitmap bitmap(bitmapHandle);
+ if (!bitmap->info().isOpaque()) {
if (isPremul) {
- bitmap->setAlphaType(kPremul_SkAlphaType);
+ bitmap->pixelRef()->changeAlphaType(kPremul_SkAlphaType);
} else {
- bitmap->setAlphaType(kUnpremul_SkAlphaType);
+ bitmap->pixelRef()->changeAlphaType(kUnpremul_SkAlphaType);
}
}
}
static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ LocalScopedBitmap bitmap(bitmapHandle);
return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
}
static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
jboolean hasMipMap) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ LocalScopedBitmap bitmap(bitmapHandle);
bitmap->setHasHardwareMipMap(hasMipMap);
}
@@ -580,8 +881,8 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
}
}
- jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap.get(), ctable);
- if (NULL == buffer) {
+ android::Bitmap* nativeBitmap = GraphicsJNI::allocateJavaPixelRef(env, bitmap.get(), ctable);
+ if (!nativeBitmap) {
SkSafeUnref(ctable);
return NULL;
}
@@ -593,6 +894,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
android::Parcel::ReadableBlob blob;
android::status_t status = p->readBlob(size, &blob);
if (status) {
+ nativeBitmap->detachFromJava();
doThrowRE(env, "Could not read bitmap from parcel blob.");
return NULL;
}
@@ -603,7 +905,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
blob.release();
- return GraphicsJNI::createBitmap(env, bitmap.release(), buffer,
+ return GraphicsJNI::createBitmap(env, nativeBitmap,
getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
}
@@ -611,24 +913,25 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
jlong bitmapHandle,
jboolean isMutable, jint density,
jobject parcel) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
if (parcel == NULL) {
SkDebugf("------- writeToParcel null parcel\n");
return JNI_FALSE;
}
android::Parcel* p = android::parcelForJavaObject(env, parcel);
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
p->writeInt32(isMutable);
- p->writeInt32(bitmap->colorType());
- p->writeInt32(bitmap->alphaType());
- p->writeInt32(bitmap->width());
- p->writeInt32(bitmap->height());
- p->writeInt32(bitmap->rowBytes());
+ p->writeInt32(bitmap.colorType());
+ p->writeInt32(bitmap.alphaType());
+ p->writeInt32(bitmap.width());
+ p->writeInt32(bitmap.height());
+ p->writeInt32(bitmap.rowBytes());
p->writeInt32(density);
- if (bitmap->colorType() == kIndex_8_SkColorType) {
- SkColorTable* ctable = bitmap->getColorTable();
+ if (bitmap.colorType() == kIndex_8_SkColorType) {
+ SkColorTable* ctable = bitmap.getColorTable();
if (ctable != NULL) {
int count = ctable->count();
p->writeInt32(count);
@@ -639,7 +942,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
}
}
- size_t size = bitmap->getSize();
+ size_t size = bitmap.getSize();
android::Parcel::WritableBlob blob;
android::status_t status = p->writeBlob(size, &blob);
@@ -648,14 +951,14 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
return JNI_FALSE;
}
- bitmap->lockPixels();
- const void* pSrc = bitmap->getPixels();
+ bitmap.lockPixels();
+ const void* pSrc = bitmap.getPixels();
if (pSrc == NULL) {
memset(blob.data(), 0, size);
} else {
memcpy(blob.data(), pSrc, size);
}
- bitmap->unlockPixels();
+ bitmap.unlockPixels();
blob.release();
return JNI_TRUE;
@@ -664,17 +967,17 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
jlong srcHandle, jlong paintHandle,
jintArray offsetXY) {
- const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
+ SkBitmap src;
+ reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
SkIPoint offset;
- SkBitmap* dst = new SkBitmap;
+ SkBitmap dst;
JavaPixelAllocator allocator(env);
- src->extractAlpha(dst, paint, &allocator, &offset);
+ src.extractAlpha(&dst, paint, &allocator, &offset);
// If Skia can't allocate pixels for destination bitmap, it resets
// it, that is set its pixels buffer to NULL, and zero width and height.
- if (dst->getPixels() == NULL && src->getPixels() != NULL) {
- delete dst;
+ if (dst.getPixels() == NULL && src.getPixels() != NULL) {
doThrowOOME(env, "failed to allocate pixels for alpha");
return NULL;
}
@@ -685,53 +988,55 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
env->ReleaseIntArrayElements(offsetXY, array, 0);
}
- return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),
- getPremulBitmapCreateFlags(true), NULL, NULL);
+ return GraphicsJNI::createBitmap(env, allocator.getStorageObjAndReset(),
+ getPremulBitmapCreateFlags(true));
}
///////////////////////////////////////////////////////////////////////////////
static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
jint x, jint y) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
+ SkAutoLockPixels alp(bitmap);
- ToColorProc proc = ChooseToColorProc(*bitmap);
+ ToColorProc proc = ChooseToColorProc(bitmap);
if (NULL == proc) {
return 0;
}
- const void* src = bitmap->getAddr(x, y);
+ const void* src = bitmap.getAddr(x, y);
if (NULL == src) {
return 0;
}
SkColor dst[1];
- proc(dst, src, 1, bitmap->getColorTable());
+ proc(dst, src, 1, bitmap.getColorTable());
return static_cast<jint>(dst[0]);
}
static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
jintArray pixelArray, jint offset, jint stride,
jint x, jint y, jint width, jint height) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
+ SkAutoLockPixels alp(bitmap);
- ToColorProc proc = ChooseToColorProc(*bitmap);
+ ToColorProc proc = ChooseToColorProc(bitmap);
if (NULL == proc) {
return;
}
- const void* src = bitmap->getAddr(x, y);
+ const void* src = bitmap.getAddr(x, y);
if (NULL == src) {
return;
}
- SkColorTable* ctable = bitmap->getColorTable();
+ SkColorTable* ctable = bitmap.getColorTable();
jint* dst = env->GetIntArrayElements(pixelArray, NULL);
SkColor* d = (SkColor*)dst + offset;
while (--height >= 0) {
proc(d, src, width, ctable);
d += stride;
- src = (void*)((const char*)src + bitmap->rowBytes());
+ src = (void*)((const char*)src + bitmap.rowBytes());
}
env->ReleaseIntArrayElements(pixelArray, dst, 0);
}
@@ -740,79 +1045,85 @@ static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
jint x, jint y, jint colorHandle) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
SkColor color = static_cast<SkColor>(colorHandle);
- SkAutoLockPixels alp(*bitmap);
- if (NULL == bitmap->getPixels()) {
+ SkAutoLockPixels alp(bitmap);
+ if (NULL == bitmap.getPixels()) {
return;
}
- FromColorProc proc = ChooseFromColorProc(*bitmap);
+ FromColorProc proc = ChooseFromColorProc(bitmap);
if (NULL == proc) {
return;
}
- proc(bitmap->getAddr(x, y), &color, 1, x, y);
- bitmap->notifyPixelsChanged();
+ proc(bitmap.getAddr(x, y), &color, 1, x, y);
+ bitmap.notifyPixelsChanged();
}
static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
jintArray pixelArray, jint offset, jint stride,
jint x, jint y, jint width, jint height) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
- x, y, width, height, *bitmap);
+ x, y, width, height, bitmap);
}
static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
jlong bitmapHandle, jobject jbuffer) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
- const void* src = bitmap->getPixels();
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
+ SkAutoLockPixels alp(bitmap);
+ const void* src = bitmap.getPixels();
if (NULL != src) {
android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
// the java side has already checked that buffer is large enough
- memcpy(abp.pointer(), src, bitmap->getSize());
+ memcpy(abp.pointer(), src, bitmap.getSize());
}
}
static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
jlong bitmapHandle, jobject jbuffer) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
- void* dst = bitmap->getPixels();
+ SkBitmap bitmap;
+ reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
+ SkAutoLockPixels alp(bitmap);
+ void* dst = bitmap.getPixels();
if (NULL != dst) {
android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
// the java side has already checked that buffer is large enough
- memcpy(dst, abp.pointer(), bitmap->getSize());
- bitmap->notifyPixelsChanged();
+ memcpy(dst, abp.pointer(), bitmap.getSize());
+ bitmap.notifyPixelsChanged();
}
}
static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
jlong bm1Handle) {
- const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle);
- const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle);
- if (bm0->width() != bm1->width() ||
- bm0->height() != bm1->height() ||
- bm0->colorType() != bm1->colorType()) {
+ SkBitmap bm0;
+ SkBitmap bm1;
+ reinterpret_cast<Bitmap*>(bm0Handle)->getSkBitmap(&bm0);
+ reinterpret_cast<Bitmap*>(bm1Handle)->getSkBitmap(&bm1);
+ if (bm0.width() != bm1.width() ||
+ bm0.height() != bm1.height() ||
+ bm0.colorType() != bm1.colorType()) {
return JNI_FALSE;
}
- SkAutoLockPixels alp0(*bm0);
- SkAutoLockPixels alp1(*bm1);
+ SkAutoLockPixels alp0(bm0);
+ SkAutoLockPixels alp1(bm1);
// if we can't load the pixels, return false
- if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
+ if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
return JNI_FALSE;
}
- if (bm0->colorType() == kIndex_8_SkColorType) {
- SkColorTable* ct0 = bm0->getColorTable();
- SkColorTable* ct1 = bm1->getColorTable();
+ if (bm0.colorType() == kIndex_8_SkColorType) {
+ SkColorTable* ct0 = bm0.getColorTable();
+ SkColorTable* ct1 = bm1.getColorTable();
if (NULL == ct0 || NULL == ct1) {
return JNI_FALSE;
}
@@ -829,16 +1140,16 @@ static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
// now compare each scanline. We can't do the entire buffer at once,
// since we don't care about the pixel values that might extend beyond
// the width (since the scanline might be larger than the logical width)
- const int h = bm0->height();
- const size_t size = bm0->width() * bm0->bytesPerPixel();
+ const int h = bm0.height();
+ const size_t size = bm0.width() * bm0.bytesPerPixel();
for (int y = 0; y < h; y++) {
// SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
// (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
// and bm1 both have pixel data() (have passed NULL == getPixels() check),
// those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
// to warn user those 2 unrecognized config bitmaps may be different.
- void *bm0Addr = bm0->getAddr(0, y);
- void *bm1Addr = bm1->getAddr(0, y);
+ void *bm0Addr = bm0.getAddr(0, y);
+ void *bm1Addr = bm1.getAddr(0, y);
if(bm0Addr == NULL || bm1Addr == NULL) {
return JNI_FALSE;
@@ -851,15 +1162,9 @@ static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
return JNI_TRUE;
}
-static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- bitmap->lockPixels();
- bitmap->unlockPixels();
-}
-
static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkPixelRef* pixelRef = bitmap ? bitmap->pixelRef() : nullptr;
+ LocalScopedBitmap bitmap(bitmapHandle);
+ SkPixelRef* pixelRef = bitmap.valid() ? bitmap->pixelRef() : nullptr;
SkSafeRef(pixelRef);
return reinterpret_cast<jlong>(pixelRef);
}
@@ -902,7 +1207,6 @@ static JNINativeMethod gBitmapMethods[] = {
{ "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
(void*)Bitmap_copyPixelsFromBuffer },
{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
- { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
{ "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef },
};
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
new file mode 100644
index 0000000..d6e5c61
--- /dev/null
+++ b/core/jni/android/graphics/Bitmap.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef BITMAP_H_
+#define BITMAP_H_
+
+#include <jni.h>
+#include <SkBitmap.h>
+#include <SkColorTable.h>
+#include <SkImageInfo.h>
+#include <utils/Mutex.h>
+#include <memory>
+
+namespace android {
+
+enum class PixelStorageType {
+ Invalid,
+ External,
+ Java,
+};
+
+class WrappedPixelRef;
+
+typedef void (*FreeFunc)(void* addr, void* context);
+
+/**
+ * Glue-thingy that deals with managing the interaction between the Java
+ * Bitmap object & SkBitmap along with trying to map a notion of strong/weak
+ * lifecycles onto SkPixelRef which only has strong counts to avoid requiring
+ * two GC passes to free the byte[] that backs a Bitmap.
+ *
+ * Since not all Bitmaps are byte[]-backed it also supports external allocations,
+ * which currently is used by screenshots to wrap a gralloc buffer.
+ */
+class Bitmap {
+public:
+ Bitmap(JNIEnv* env, jbyteArray storageObj, void* address,
+ const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+ Bitmap(void* address, void* context, FreeFunc freeFunc,
+ const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+
+ const SkImageInfo& info() const;
+
+ // Returns nullptr if it is not backed by a jbyteArray
+ jbyteArray javaByteArray() const {
+ return mPixelStorageType == PixelStorageType::Java
+ ? mPixelStorage.java.jstrongRef : nullptr;
+ }
+
+ int width() const { return info().width(); }
+ int height() const { return info().height(); }
+ size_t rowBytes() const;
+ SkPixelRef* pixelRef() const;
+ bool valid() const { return mPixelStorageType != PixelStorageType::Invalid; }
+
+ void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+ void reconfigure(const SkImageInfo& info);
+
+ void getSkBitmap(SkBitmap* outBitmap);
+ void detachFromJava();
+
+ void freePixels();
+
+ bool hasHardwareMipMap();
+ void setHasHardwareMipMap(bool hasMipMap);
+
+private:
+ friend class WrappedPixelRef;
+
+ ~Bitmap();
+ void doFreePixels();
+ void onStrongRefDestroyed();
+
+ void pinPixelsLocked();
+ void unpinPixelsLocked();
+ JNIEnv* jniEnv();
+ bool shouldDisposeSelfLocked();
+ void assertValid() const;
+
+ android::Mutex mLock;
+ int mPinnedRefCount = 0;
+ std::unique_ptr<WrappedPixelRef> mPixelRef;
+ PixelStorageType mPixelStorageType;
+ bool mAttachedToJava = true;
+
+ union {
+ struct {
+ void* address;
+ void* context;
+ FreeFunc freeFunc;
+ } external;
+ struct {
+ JavaVM* jvm;
+ jweak jweakRef;
+ jbyteArray jstrongRef;
+ } java;
+ } mPixelStorage;
+};
+
+} // namespace android
+
+#endif /* BITMAP_H_ */
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index d4069a1..cdd397d 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -156,13 +156,11 @@ private:
class RecyclingPixelAllocator : public SkBitmap::Allocator {
public:
- RecyclingPixelAllocator(SkPixelRef* pixelRef, unsigned int size)
- : mPixelRef(pixelRef), mSize(size) {
- SkSafeRef(mPixelRef);
+ RecyclingPixelAllocator(android::Bitmap* bitmap, unsigned int size)
+ : mBitmap(bitmap), mSize(size) {
}
~RecyclingPixelAllocator() {
- SkSafeUnref(mPixelRef);
}
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
@@ -185,11 +183,9 @@ public:
return false;
}
- // Create a new pixelref with the new ctable that wraps the previous pixelref
- SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef),
- info, bitmap->rowBytes(), ctable);
+ mBitmap->reconfigure(info, bitmap->rowBytes(), ctable);
+ bitmap->setPixelRef(mBitmap->pixelRef());
- bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
// HeapAllocator/JavaPixelAllocator behaves this way too
bitmap->lockPixels();
@@ -197,7 +193,7 @@ public:
}
private:
- SkPixelRef* const mPixelRef;
+ android::Bitmap* const mBitmap;
const unsigned int mSize;
};
@@ -258,27 +254,24 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
decoder->setRequireUnpremultipliedColors(requireUnpremultiplied);
- SkBitmap* outputBitmap = NULL;
+ android::Bitmap* reuseBitmap = nullptr;
unsigned int existingBufferSize = 0;
if (javaBitmap != NULL) {
- outputBitmap = GraphicsJNI::getSkBitmapDeprecated(env, javaBitmap);
- if (outputBitmap->isImmutable()) {
+ reuseBitmap = GraphicsJNI::getBitmap(env, javaBitmap);
+ if (reuseBitmap->pixelRef()->isImmutable()) {
ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
javaBitmap = NULL;
- outputBitmap = NULL;
+ reuseBitmap = nullptr;
} else {
existingBufferSize = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap);
}
}
- SkAutoTDelete<SkBitmap> adb(outputBitmap == NULL ? new SkBitmap : NULL);
- if (outputBitmap == NULL) outputBitmap = adb.get();
-
NinePatchPeeker peeker(decoder);
decoder->setPeeker(&peeker);
JavaPixelAllocator javaAllocator(env);
- RecyclingPixelAllocator recyclingAllocator(outputBitmap->pixelRef(), existingBufferSize);
+ RecyclingPixelAllocator recyclingAllocator(reuseBitmap, existingBufferSize);
ScaleCheckingAllocator scaleCheckingAllocator(scale, existingBufferSize);
SkBitmap::Allocator* outputAllocator = (javaBitmap != NULL) ?
(SkBitmap::Allocator*)&recyclingAllocator : (SkBitmap::Allocator*)&javaAllocator;
@@ -374,6 +367,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
}
+ SkBitmap outputBitmap;
if (willScale) {
// This is weird so let me explain: we could use the scale parameter
// directly, but for historical reasons this is how the corresponding
@@ -388,26 +382,27 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
// FIXME: If the alphaType is kUnpremul and the image has alpha, the
// colors may not be correct, since Skia does not yet support drawing
// to/from unpremultiplied bitmaps.
- outputBitmap->setInfo(SkImageInfo::Make(scaledWidth, scaledHeight,
+ outputBitmap.setInfo(SkImageInfo::Make(scaledWidth, scaledHeight,
colorType, decodingBitmap.alphaType()));
- if (!outputBitmap->tryAllocPixels(outputAllocator, NULL)) {
+ if (!outputBitmap.tryAllocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
}
// If outputBitmap's pixels are newly allocated by Java, there is no need
// to erase to 0, since the pixels were initialized to 0.
if (outputAllocator != &javaAllocator) {
- outputBitmap->eraseColor(0);
+ outputBitmap.eraseColor(0);
}
SkPaint paint;
paint.setFilterQuality(kLow_SkFilterQuality);
- SkCanvas canvas(*outputBitmap);
+ SkCanvas canvas(outputBitmap);
canvas.scale(sx, sy);
+ canvas.drawARGB(0x00, 0x00, 0x00, 0x00);
canvas.drawBitmap(decodingBitmap, 0.0f, 0.0f, &paint);
} else {
- outputBitmap->swap(decodingBitmap);
+ outputBitmap.swap(decodingBitmap);
}
if (padding) {
@@ -422,22 +417,19 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
// if we get here, we're in kDecodePixels_Mode and will therefore
// already have a pixelref installed.
- if (outputBitmap->pixelRef() == NULL) {
+ if (outputBitmap.pixelRef() == NULL) {
return nullObjectReturn("Got null SkPixelRef");
}
if (!isMutable && javaBitmap == NULL) {
// promise we will never change our pixels (great for sharing and pictures)
- outputBitmap->setImmutable();
+ outputBitmap.setImmutable();
}
- // detach bitmap from its autodeleter, since we want to own it now
- adb.detach();
-
if (javaBitmap != NULL) {
bool isPremultiplied = !requireUnpremultiplied;
- GraphicsJNI::reinitBitmap(env, javaBitmap, outputBitmap, isPremultiplied);
- outputBitmap->notifyPixelsChanged();
+ GraphicsJNI::reinitBitmap(env, javaBitmap, outputBitmap.info(), isPremultiplied);
+ outputBitmap.notifyPixelsChanged();
// If a java bitmap was passed in for reuse, pass it back
return javaBitmap;
}
@@ -447,7 +439,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
// now create the java bitmap
- return GraphicsJNI::createBitmap(env, outputBitmap, javaAllocator.getStorageObj(),
+ return GraphicsJNI::createBitmap(env, javaAllocator.getStorageObjAndReset(),
bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
}
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index aeea808..08a3f6f 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -212,26 +212,21 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle,
region.fTop = start_y;
region.fRight = start_x + width;
region.fBottom = start_y + height;
- SkBitmap* bitmap = NULL;
- SkAutoTDelete<SkBitmap> adb;
+ SkBitmap bitmap;
if (tileBitmap != NULL) {
// Re-use bitmap.
- bitmap = GraphicsJNI::getSkBitmapDeprecated(env, tileBitmap);
- }
- if (bitmap == NULL) {
- bitmap = new SkBitmap;
- adb.reset(bitmap);
+ GraphicsJNI::getSkBitmap(env, tileBitmap, &bitmap);
}
- if (!brd->decodeRegion(bitmap, region, prefColorType, sampleSize)) {
+ if (!brd->decodeRegion(&bitmap, region, prefColorType, sampleSize)) {
return nullObjectReturn("decoder->decodeRegion returned false");
}
// update options (if any)
if (NULL != options) {
- env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
- env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
+ env->SetIntField(options, gOptions_widthFieldID, bitmap.width());
+ env->SetIntField(options, gOptions_heightFieldID, bitmap.height());
// TODO: set the mimeType field with the data from the codec.
// but how to reuse a set of strings, rather than allocating new one
// each time?
@@ -240,19 +235,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle,
}
if (tileBitmap != NULL) {
- bitmap->notifyPixelsChanged();
+ bitmap.notifyPixelsChanged();
return tileBitmap;
}
- // detach bitmap from its autodeleter, since we want to own it now
- adb.detach();
-
JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator();
- jbyteArray buff = allocator->getStorageObjAndReset();
int bitmapCreateFlags = 0;
if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
- return GraphicsJNI::createBitmap(env, bitmap, buff, bitmapCreateFlags, NULL, NULL, -1);
+ return GraphicsJNI::createBitmap(env, allocator->getStorageObjAndReset(),
+ bitmapCreateFlags);
}
static jint nativeGetHeight(JNIEnv* env, jobject, jlong brdHandle) {
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index f793df1..0deb8cc 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -154,7 +154,7 @@ static jfieldID gPointF_xFieldID;
static jfieldID gPointF_yFieldID;
static jclass gBitmap_class;
-static jfieldID gBitmap_skBitmapPtr;
+static jfieldID gBitmap_nativePtr;
static jmethodID gBitmap_constructorMethodID;
static jmethodID gBitmap_reinitMethodID;
static jmethodID gBitmap_getAllocationByteCountMethodID;
@@ -338,27 +338,22 @@ SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
}
-SkBitmap* GraphicsJNI::getSkBitmapDeprecated(JNIEnv* env, jobject bitmap) {
+android::Bitmap* GraphicsJNI::getBitmap(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_skBitmapPtr);
- SkBitmap* b = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+ android::Bitmap* b = reinterpret_cast<android::Bitmap*>(bitmapHandle);
SkASSERT(b);
return b;
}
void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
- // TODO: We have to copy from the existing bitmap due to rowBytes not
- // being updated on the SkPixelRef at reconfigure time. This is a short term
- // problem that will be fixed with the specialized wrapper
- *outBitmap = *getSkBitmapDeprecated(env, bitmap);
+ getBitmap(env, bitmap)->getSkBitmap(outBitmap);
}
SkPixelRef* GraphicsJNI::getSkPixelRef(JNIEnv* env, jobject bitmap) {
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_skBitmapPtr);
- SkBitmap* b = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return b->pixelRef();
+ return getBitmap(env, bitmap)->pixelRef();
}
SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) {
@@ -396,47 +391,43 @@ SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
///////////////////////////////////////////////////////////////////////////////////////////
// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
-static void assert_premultiplied(const SkBitmap& bitmap, bool isPremultiplied) {
+static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
// kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
// irrelevant. This just tests to ensure that the SkAlphaType is not
// opposite of isPremultiplied.
if (isPremultiplied) {
- SkASSERT(bitmap.alphaType() != kUnpremul_SkAlphaType);
+ SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
} else {
- SkASSERT(bitmap.alphaType() != kPremul_SkAlphaType);
+ SkASSERT(info.alphaType() != kPremul_SkAlphaType);
}
}
-jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
- int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets, int density)
-{
- SkASSERT(bitmap);
- SkASSERT(bitmap->pixelRef());
- SkASSERT(!env->ExceptionCheck());
+jobject GraphicsJNI::createBitmap(JNIEnv* env, android::Bitmap* bitmap,
+ int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
+ int density) {
bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
-
// The caller needs to have already set the alpha type properly, so the
// native SkBitmap stays in sync with the Java Bitmap.
- assert_premultiplied(*bitmap, isPremultiplied);
+ assert_premultiplied(bitmap->info(), isPremultiplied);
jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
- reinterpret_cast<jlong>(bitmap), buffer,
+ reinterpret_cast<jlong>(bitmap), bitmap->javaByteArray(),
bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied,
ninePatchChunk, ninePatchInsets);
hasException(env); // For the side effect of logging.
return obj;
}
-void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
+void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
bool isPremultiplied)
{
// The caller needs to have already set the alpha type properly, so the
// native SkBitmap stays in sync with the Java Bitmap.
- assert_premultiplied(*bitmap, isPremultiplied);
+ assert_premultiplied(info, isPremultiplied);
env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
- bitmap->width(), bitmap->height(), isPremultiplied);
+ info.width(), info.height(), isPremultiplied);
}
int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
@@ -477,51 +468,6 @@ static JNIEnv* vm2env(JavaVM* vm)
///////////////////////////////////////////////////////////////////////////////
-AndroidPixelRef::AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage,
- size_t rowBytes, jbyteArray storageObj, SkColorTable* ctable) :
- SkMallocPixelRef(info, storage, rowBytes, ctable, (storageObj == NULL)),
- fWrappedPixelRef(NULL) {
- SkASSERT(storage);
- SkASSERT(storageObj);
- SkASSERT(env);
-
- if (env->GetJavaVM(&fVM) != JNI_OK) {
- SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
- sk_throw();
- }
-
- fStorageObj = (jbyteArray) env->NewGlobalRef(storageObj);
-}
-
-AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info,
- size_t rowBytes, SkColorTable* ctable) :
- SkMallocPixelRef(info, wrappedPixelRef.getAddr(), rowBytes, ctable, false),
- fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ?
- wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
-{
- SkASSERT(fWrappedPixelRef);
- SkSafeRef(fWrappedPixelRef);
-
- // don't need to initialize this, as all the relevant logic delegates to the wrapped ref
- fStorageObj = NULL;
-}
-
-AndroidPixelRef::~AndroidPixelRef() {
- if (fWrappedPixelRef) {
- SkSafeUnref(fWrappedPixelRef);
- } else {
- SkASSERT(fStorageObj);
- JNIEnv* env = vm2env(fVM);
- env->DeleteGlobalRef(fStorageObj);
- }
-
- if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().textureCache.releaseTexture(getStableID());
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
int32_t rowBytes32 = SkToS32(bitmap.rowBytes());
int64_t bigSize = (int64_t)bitmap.height() * rowBytes32;
@@ -533,7 +479,7 @@ static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
return true;
}
-jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
+android::Bitmap* GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
SkColorTable* ctable) {
const SkImageInfo& info = bitmap->info();
if (info.fColorType == kUnknown_SkColorType) {
@@ -562,13 +508,14 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
return NULL;
}
SkASSERT(addr);
- SkPixelRef* pr = new AndroidPixelRef(env, info, (void*) addr, rowBytes, arrayObj, ctable);
- bitmap->setPixelRef(pr)->unref();
+ android::Bitmap* wrapper = new android::Bitmap(env, arrayObj, (void*) addr,
+ info, rowBytes, ctable);
+ wrapper->getSkBitmap(bitmap);
// since we're already allocated, we lockPixels right away
// HeapAllocator behaves this way too
bitmap->lockPixels();
- return arrayObj;
+ return wrapper;
}
struct AndroidPixelRefContext {
@@ -627,21 +574,22 @@ bool GraphicsJNI::allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ct
///////////////////////////////////////////////////////////////////////////////
-JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env)
- : fStorageObj(NULL),
- fAllocCount(0) {
- if (env->GetJavaVM(&fVM) != JNI_OK) {
- SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
- sk_throw();
+JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) {
+ LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mJavaVM) != JNI_OK,
+ "env->GetJavaVM failed");
+}
+
+JavaPixelAllocator::~JavaPixelAllocator() {
+ if (mStorage) {
+ mStorage->detachFromJava();
}
}
bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
- JNIEnv* env = vm2env(fVM);
+ JNIEnv* env = vm2env(mJavaVM);
- fStorageObj = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
- fAllocCount += 1;
- return fStorageObj != NULL;
+ mStorage = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
+ return mStorage != nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@@ -687,7 +635,7 @@ int register_android_graphics_Graphics(JNIEnv* env)
gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
- gBitmap_skBitmapPtr = getFieldIDCheck(env, gBitmap_class, "mSkBitmapPtr", "J");
+ gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(J[BIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8eb43f8..e748bac 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -1,6 +1,7 @@
#ifndef _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
#define _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
+#include "Bitmap.h"
#include "SkBitmap.h"
#include "SkDevice.h"
#include "SkPixelRef.h"
@@ -49,7 +50,7 @@ public:
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
- static SkBitmap* getSkBitmapDeprecated(JNIEnv*, jobject bitmap);
+ static android::Bitmap* getBitmap(JNIEnv*, jobject bitmap);
static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
static SkPixelRef* getSkPixelRef(JNIEnv*, jobject bitmap);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
@@ -71,22 +72,18 @@ public:
*/
static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig);
- /** Create a java Bitmap object given the native bitmap (required) and optional
- storage array (may be null).
- bitmap's SkAlphaType must already be in sync with bitmapCreateFlags.
+ /*
+ * Create a java Bitmap object given the native bitmap
+ * bitmap's SkAlphaType must already be in sync with bitmapCreateFlags.
*/
- static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
- int bitmapCreateFlags, jbyteArray ninePatch, jobject ninePatchInsets, int density = -1);
-
- static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
- jbyteArray ninePatch, int density = -1) {
- return createBitmap(env, bitmap, NULL, bitmapCreateFlags, ninePatch, NULL, density);
- }
+ static jobject createBitmap(JNIEnv* env, android::Bitmap* bitmap,
+ int bitmapCreateFlags, jbyteArray ninePatchChunk = NULL,
+ jobject ninePatchInsets = NULL, int density = -1);
/** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
sync with isPremultiplied
*/
- static void reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
+ static void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
bool isPremultiplied);
static int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap);
@@ -95,7 +92,7 @@ public:
static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
- static jbyteArray allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
+ static android::Bitmap* allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
SkColorTable* ctable);
/**
@@ -113,30 +110,6 @@ public:
static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
int srcStride, int x, int y, int width, int height,
const SkBitmap& dstBitmap);
-
- static jbyteArray getBitmapStorageObj(SkPixelRef *pixref);
-};
-
-class AndroidPixelRef : public SkMallocPixelRef {
-public:
- AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage, size_t rowBytes,
- jbyteArray storageObj, SkColorTable* ctable);
-
- /**
- * Creates an AndroidPixelRef that wraps (and refs) another to reuse/share
- * the same storage and java byte array refcounting, yet have a different
- * color table.
- */
- AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info,
- size_t rowBytes, SkColorTable* ctable);
-
- virtual ~AndroidPixelRef();
-
-private:
- AndroidPixelRef* const fWrappedPixelRef; // if set, delegate memory management calls to this
-
- JavaVM* fVM;
- jbyteArray fStorageObj; // The Java byte[] object used as the bitmap backing store
};
/** Allocator which allocates the backing buffer in the Java heap.
@@ -147,30 +120,22 @@ private:
class JavaPixelAllocator : public SkBitmap::Allocator {
public:
JavaPixelAllocator(JNIEnv* env);
- // overrides
- virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
+ ~JavaPixelAllocator();
- /** Return the Java array object created for the last allocation.
- * This returns a local JNI reference which the caller is responsible
- * for storing appropriately (usually by passing it to the Bitmap
- * constructor).
- */
- jbyteArray getStorageObj() { return fStorageObj; }
+ virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) override;
- /** Same as getStorageObj(), but also resets the allocator so that it
- * can allocate again.
+ /**
+ * Fetches the backing allocation object. Must be called!
*/
- jbyteArray getStorageObjAndReset() {
- jbyteArray result = fStorageObj;
- fStorageObj = NULL;
- fAllocCount = 0;
+ android::Bitmap* getStorageObjAndReset() {
+ android::Bitmap* result = mStorage;
+ mStorage = NULL;
return result;
};
private:
- JavaVM* fVM;
- jbyteArray fStorageObj;
- int fAllocCount;
+ JavaVM* mJavaVM;
+ android::Bitmap* mStorage = nullptr;
};
enum JNIAccess {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a8355c2..1965cd3 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -23,6 +23,7 @@
#include "android_os_Parcel.h"
#include "android_util_Binder.h"
+#include "android/graphics/Bitmap.h"
#include "android/graphics/GraphicsJNI.h"
#include "android/graphics/Region.h"
@@ -168,22 +169,19 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
}
}
- const ssize_t rowBytes =
+ const size_t rowBytes =
screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
- SkBitmap* bitmap = new SkBitmap();
- bitmap->setInfo(screenshotInfo, (size_t)rowBytes);
- if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
- // takes ownership of ScreenshotClient
- SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
- (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
- (void*) (screenshot.get()));
- screenshot.detach();
- pixels->setImmutable();
- bitmap->setPixelRef(pixels)->unref();
- bitmap->lockPixels();
+ if (!screenshotInfo.fWidth || !screenshotInfo.fHeight) {
+ return NULL;
}
+ Bitmap* bitmap = new Bitmap(
+ (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
+ screenshotInfo, rowBytes, nullptr);
+ screenshot.detach();
+ bitmap->pixelRef()->setImmutable();
+
return GraphicsJNI::createBitmap(env, bitmap,
GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 942e6a6..a162b4a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2433,6 +2433,12 @@
<permission android:name="android.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows applications to kill UIDs.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.KILL_UID"
+ android:protectionLevel="signature" />
+
<!-- The system process is explicitly the only one allowed to launch the
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 2a3df74..5e9e6be 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -274,10 +274,8 @@
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"એપ્લિકેશનને WAP સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આ પરવાનગીમાં તમને દર્શાવ્યા વિના તમને મોકલેલ સંદેશાઓનું નિરીક્ષણ કરવાની અને કાઢી નાખવાની ક્ષમતાનો સમાવેશ થાય છે."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"ચાલુ એપ્લિકેશન્સ પુનઃપ્રાપ્ત કરો"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"એપ્લિકેશનને વર્તમાનમાં અને તાજેતરમાં ચાલી રહેલ કાર્યો વિશેની વિગતવાર માહિતી પુનઃપ્રાપ્ત કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને ઉપકરણ પર કઈ એપ્લિકેશન્સનો ઉપયોગ થાય છે તેના વિશેની માહિતી શોધવાની મંજૂરી આપી શકે છે."</string>
- <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) -->
- <skip />
- <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) -->
- <skip />
+ <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"પ્રોફાઇલ અને ઉપકરણ માલિકોને સંચાલિત કરો"</string>
+ <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"એપ્લિકેશન્સને પ્રોફાઇલ માલિકો અને ઉપકરણ માલિકો સેટ કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"ચાલુ એપ્લિકેશન્સને ફરી ગોઠવો"</string>
<string name="permdesc_reorderTasks" msgid="7734217754877439351">"એપ્લિકેશનને અગ્રભૂમિ અને પૃષ્ટભૂમિમાં કાર્યો ખસેડવાની મંજૂરી આપે છે. તમારા ઇનપુટ વિના એપ્લિકેશન આ કરી શકે છે."</string>
<string name="permlab_enableCarMode" msgid="5684504058192921098">"કાર મોડ સક્ષમ કરો"</string>
@@ -1080,6 +1078,22 @@
<string name="ext_media_init_action" msgid="8317198948634872507">"સેટઅપ"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"બહાર કાઢો"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"અન્વેષણ કરો"</string>
+ <!-- no translation found for ext_media_missing_title (620980315821543904) -->
+ <skip />
+ <!-- no translation found for ext_media_missing_message (5761133583368750174) -->
+ <skip />
+ <!-- no translation found for ext_media_move_specific_title (1471100343872375842) -->
+ <skip />
+ <!-- no translation found for ext_media_move_title (1022809140035962662) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_title (8575300932957954671) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_message (4199002148206265426) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_title (7613189040358789908) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_message (1978096440816403360) -->
+ <skip />
<string name="activity_list_empty" msgid="1675388330786841066">"કોઈ મેળ ખાતી પ્રવૃત્તિઓ મળી નથી."</string>
<string name="permlab_route_media_output" msgid="1642024455750414694">"મીડિયા આઉટપુટ રૂટ કરો"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"એપ્લિકેશનને અન્ય બાહ્ય ઉપકરણો પર મીડિયા આઉટપુટને રૂટ કરવની મંજૂરી આપે છે."</string>
diff --git a/core/res/res/values-mcc310-mnc260-sq-rAL/strings.xml b/core/res/res/values-mcc310-mnc260-sq-rAL/strings.xml
index 42eb1ca..84ac153 100644
--- a/core/res/res/values-mcc310-mnc260-sq-rAL/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-sq-rAL/strings.xml
@@ -23,7 +23,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="7239039348648848288">"Për të bërë telefonata dhe për të dërguar mesazhe me Wi-Fi, në fillim kërkoji operatorit celular të konfigurojë këtë shërbim. Më pas aktivizo përsëri telefonatat me Wi-Fi nga Parametrat."</item>
+ <item msgid="7239039348648848288">"Për të bërë telefonata dhe për të dërguar mesazhe me Wi-Fi, në fillim kërkoji operatorit celular ta konfigurojë këtë shërbim. Më pas aktivizo përsëri telefonatat me Wi-Fi, nga Cilësimet."</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="483847327467331298">"Regjistrohu me operatorin tënd celular"</item>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 56f8aa2..39ea2bf 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -43,6 +43,11 @@
provisioning, availability etc -->
<bool name="config_carrier_volte_available">true</bool>
+ <!-- Flag specifying whether VT should be available for carrier: independent of
+ carrier provisioning. If false: hard disabled. If true: then depends on carrier
+ provisioning, availability etc -->
+ <bool name="config_carrier_vt_available">true</bool>
+
<!-- Flag specifying whether VoLTE availability is based on provisioning -->
<bool name="config_carrier_volte_provisioned">true</bool>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index af4a068..0e9658b 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -274,10 +274,8 @@
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"ਐਪ ਨੂੰ WAP ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਅਨੁਮਤੀ ਵਿੱਚ ਸ਼ਾਮਲ ਹੈ ਐਪ ਦੀ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰਨ ਅਤੇ ਮਿਟਾਉਣ ਦੀ ਸਮਰੱਥਾ।"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"ਚੱਲ ਰਹੇ ਐਪਸ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"ਐਪ ਨੂੰ ਵਰਤਮਾਨ ਵਿੱਚ ਅਤੇ ਹੁਣੇ ਜਿਹੇ ਚੱਲ ਰਹੇ ਕੰਮਾਂ ਬਾਰੇ ਵਿਸਤ੍ਰਿਤ ਜਾਣਕਾਰੀ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਇਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਖੋਜਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ ਕਿ ਡਿਵਾਈਸ ਤੇ ਕਿਹੜੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵਰਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ।"</string>
- <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) -->
- <skip />
- <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) -->
- <skip />
+ <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"ਪ੍ਰੋਫ਼ਾਈਲ ਅਤੇ ਡਿਵਾਈਸ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਪ੍ਰਬੰਧਿਤ ਕਰੋ"</string>
+ <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ਪ੍ਰੋਫ਼ਾਈਲ ਦੇ ਮਾਲਕ ਅਤੇ ਡਿਵਾਈਸ ਦਾ ਮਾਲਕ ਨੂੰ ਸੈੱਟ ਕਰਨ ਲਈ ਐਪਸ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"ਚੱਲ ਰਹੇ ਐਪਸ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
<string name="permdesc_reorderTasks" msgid="7734217754877439351">"ਐਪ ਨੂੰ ਕੰਮਾਂ ਨੂੰ ਅਗਲੇ ਭਾਗ ਅਤੇ ਪਿਛੋਕੜ ਵਿੱਚ ਮੂਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਐਪ ਤੁਹਾਡੇ ਇਨਪੁਟ ਤੋਂ ਬਿਨਾਂ ਇਹ ਕਰ ਸਕਦਾ ਹੈ।"</string>
<string name="permlab_enableCarMode" msgid="5684504058192921098">"ਕਾਰ ਮੋਡ ਸਮਰੱਥ ਬਣਾਓ"</string>
@@ -1080,6 +1078,22 @@
<string name="ext_media_init_action" msgid="8317198948634872507">"ਸੈੱਟਅੱਪ"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"ਬਾਹਰ ਕੱਢੋ"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"ਐਕਸਪਲੋਰ ਕਰੋ"</string>
+ <!-- no translation found for ext_media_missing_title (620980315821543904) -->
+ <skip />
+ <!-- no translation found for ext_media_missing_message (5761133583368750174) -->
+ <skip />
+ <!-- no translation found for ext_media_move_specific_title (1471100343872375842) -->
+ <skip />
+ <!-- no translation found for ext_media_move_title (1022809140035962662) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_title (8575300932957954671) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_message (4199002148206265426) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_title (7613189040358789908) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_message (1978096440816403360) -->
+ <skip />
<string name="activity_list_empty" msgid="1675388330786841066">"ਕੋਈ ਮੇਲ ਖਾਂਦੀਆਂ ਗਤੀਵਿਧੀਆਂ ਨਹੀਂ ਮਿਲੀਆਂ।"</string>
<string name="permlab_route_media_output" msgid="1642024455750414694">"ਰੂਟ ਮੀਡੀਆ ਆਊਟਪੁਟ"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੂੰ ਹੋਰਾਂ ਬਾਹਰੀ ਡਿਵਾਈਸਾਂ ਲਈ ਮੀਡੀਆ ਆਊਟਪੁਟ ਰੂਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index eb2f6e3..ea04ad8 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -129,7 +129,7 @@
<string-array name="wfcOperatorErrorNotificationMessages">
</string-array>
<string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
- <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Joaktiv"</string>
+ <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Çaktivizuar"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferohet Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="5920549484600758786">"Preferohet rrjeti celular"</string>
<string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Vetëm Wi-Fi"</string>
@@ -274,10 +274,8 @@
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Lejon aplikacionin të marrë dhe përpunojë mesazhe WAP. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"gjej aplikacionet në punë"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Lejon aplikacionin të gjejë informacione mbi detyrat aktuale dhe të fundit në punë. Kjo mund të lejojë aplikacionin të zbulojë informacione rreth aplikacioneve të përdorura në pajisje."</string>
- <!-- no translation found for permlab_manageProfileAndDeviceOwners (5979288447973722097) -->
- <skip />
- <!-- no translation found for permdesc_manageProfileAndDeviceOwners (106894851498657169) -->
- <skip />
+ <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"Menaxho pronarët e profilit dhe të pajisjes"</string>
+ <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Lejo aplikacionet që të caktojnë pronarët e profilit dhe pronarin e pajisjes"</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"ri-poziciono aplikacionet në punë"</string>
<string name="permdesc_reorderTasks" msgid="7734217754877439351">"Lejon aplikacionin të zhvendosë detyra në plan të parë dhe në sfond. Aplikacioni mund ta bëjë këtë pa hyrjen tënde."</string>
<string name="permlab_enableCarMode" msgid="5684504058192921098">"aktivizo modalitetin \"në makinë\""</string>
@@ -422,7 +420,7 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Lejon aplikacionin të komunikojë me etiketimet e \"Komunikimit të fushës së afërt (NFC)\", kartat dhe lexuesit."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"çaktivizo kyçjen e ekranit"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lejon aplikacionin të çaktivizojë kyçjen e tasteve dhe çdo mbrojtje të lidhur me fjalëkalimin. Për shembull, telefoni çaktivizon kyçjen e tasteve kur merr një telefonatë hyrëse, pastaj riaktivizon kyçjen e tasteve kur mbaron telefonata."</string>
- <string name="permlab_manageFingerprint" msgid="5640858826254575638">"të qaset te hardueri i gjurmës së gishtit"</string>
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"të menaxhojë harduerin e gjurmës së gishtit"</string>
<string name="permdesc_manageFingerprint" msgid="178208705828055464">"E lejon aplikacionin që të aktivizojë metoda për të shtuar dhe për të fshirë shabllonet e gjurmës së gishtit për përdorim."</string>
<string name="permlab_useFingerprint" msgid="3150478619915124905">"të përdorë harduerin e gjurmës së gishtit"</string>
<string name="permdesc_useFingerprint" msgid="9165097460730684114">"E lejon aplikacinin që të përdorë harduerin e gjurmës së gishtit për verifikimin"</string>
@@ -435,7 +433,7 @@
</string-array>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardueri i gjurmës së gishtit nuk mundësohet."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Gjurma e gishtit nuk mund të ruhet. Hiq një gjurmë gishti ekzistuese."</string>
- <string name="fingerprint_error_timeout" msgid="3927186043737732875">"U arrit vonesa e skadimit për gjurmën e gishtit. Provo përsëri."</string>
+ <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operacioni i gjurmës së gishtit u anulua."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Provo përsëri."</string>
@@ -939,9 +937,9 @@
<string name="new_app_action" msgid="5472756926945440706">"Fillo <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="new_app_description" msgid="1932143598371537340">"Ndalo aplikacionin e vjetër pa e ruajtur."</string>
<string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> e ka kaluar kufirin e memories"</string>
- <string name="dump_heap_notification_detail" msgid="2075673362317481664">"Hedhja e dëmtimit të grumbullimit është marrë; prek për ta ndarë"</string>
- <string name="dump_heap_title" msgid="5864292264307651673">"Të ndahet hedhja e dëmtimit të grumbullimit?"</string>
- <string name="dump_heap_text" msgid="4809417337240334941">"Procesi <xliff:g id="PROC">%1$s</xliff:g> ka kaluar kufirin e tij të memories së procesit me <xliff:g id="SIZE">%2$s</xliff:g>. Ofrohet një hedhje e dëmtimit të grumbullimit që ta ndani me zhvilluesit e tij. Trego kujdes: kjo hedhje e dëmtimit të grumbullimit mund të përmbajë çdo informacion tëndin personal ku ka qasje ky aplikacion."</string>
+ <string name="dump_heap_notification_detail" msgid="2075673362317481664">"Skedarët fiktivë u stivosën; prek për t\'i ndarë"</string>
+ <string name="dump_heap_title" msgid="5864292264307651673">"Të ndahet stiva e skedarëve fiktivë?"</string>
+ <string name="dump_heap_text" msgid="4809417337240334941">"Procesi <xliff:g id="PROC">%1$s</xliff:g> ka kaluar kufirin e tij të memories së procesit me <xliff:g id="SIZE">%2$s</xliff:g>. Mundësohet stivimi e skedarëve fiktivë në mënyrë që t\'i ndani me zhvilluesit e tyre. Bëni kujdes pasi stiva e skedarëve fiktivë mund të përmbajë ndonjë informacion tëndin personal ku aplikacioni ka qasje."</string>
<string name="sendText" msgid="5209874571959469142">"Zgjidh një veprim për tekstin"</string>
<string name="volume_ringtone" msgid="6885421406845734650">"Volumi i ziles"</string>
<string name="volume_music" msgid="5421651157138628171">"Volumi i klipeve \"media\""</string>
@@ -1080,6 +1078,22 @@
<string name="ext_media_init_action" msgid="8317198948634872507">"Konfigurimi"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Nxirr"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"Eksploro"</string>
+ <!-- no translation found for ext_media_missing_title (620980315821543904) -->
+ <skip />
+ <!-- no translation found for ext_media_missing_message (5761133583368750174) -->
+ <skip />
+ <!-- no translation found for ext_media_move_specific_title (1471100343872375842) -->
+ <skip />
+ <!-- no translation found for ext_media_move_title (1022809140035962662) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_title (8575300932957954671) -->
+ <skip />
+ <!-- no translation found for ext_media_move_success_message (4199002148206265426) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_title (7613189040358789908) -->
+ <skip />
+ <!-- no translation found for ext_media_move_failure_message (1978096440816403360) -->
+ <skip />
<string name="activity_list_empty" msgid="1675388330786841066">"Nuk u gjet asnjë aktivitet që përputhet."</string>
<string name="permlab_route_media_output" msgid="1642024455750414694">"Kalo daljet e medias"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"Lejon një aplikacion të kalojë daljet mediatike në pajisje të tjera të jashtme."</string>
@@ -1445,7 +1459,7 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Puna <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="7570091317001980053">"Për t\'i hequr gozhdimin ekranit, prek dhe mbaj shtypur njëkohësisht \"Prapa\" dhe \"Përmbledhje\"."</string>
<string name="lock_to_app_toast_accessible" msgid="8239120109365070664">"Për t\'i hequr gozhdimin ekranit, prek dhe mbaj shtypur \"Përmbledhje\"."</string>
- <string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ekrani është i mbërthyer. Anulimi i mbërthimit nuk lejohet nga organizata jote."</string>
+ <string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ekrani është i gozhduar. Anulimi i mbërthimit nuk lejohet nga organizata jote."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrani u gozhdua"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekrani u hoq nga gozhdimi"</string>
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Kërko PIN-in para se t\'i heqësh gozhdimin"</string>
@@ -1475,7 +1489,7 @@
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Shpalos"</string>
<string name="zen_mode_feature_name" msgid="5254089399895895004">"Mos shqetëso"</string>
- <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Koha joaktive"</string>
+ <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"periudha joaktive"</string>
<string name="zen_mode_default_weeknights_name" msgid="2069189413656431610">"Natën gjatë javës"</string>
<string name="zen_mode_default_weekends_name" msgid="2377398437072017011">"Fundjava"</string>
<string name="muted_by" msgid="6147073845094180001">"Lënë në heshtje nga <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
@@ -1487,7 +1501,7 @@
<string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Kërkesa SS është e modifikuar në kërkesën DIAL."</string>
<string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Kërkesa SS është modifikuar në kërkesën USSD."</string>
<string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Kërkesa SS është e modifikuar në kërkesën e re SS."</string>
- <string name="usb_midi_peripheral_name" msgid="7221113987741003817">"Porta periferike USB e Android"</string>
+ <string name="usb_midi_peripheral_name" msgid="7221113987741003817">"Porta periferike USB e Androidit"</string>
<string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
<string name="usb_midi_peripheral_product_name" msgid="4971827859165280403">"Porta periferike USB"</string>
<string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"Opsione të tjera"</string>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 4b8bd0f..842c72e 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -101,6 +101,18 @@
<!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_TO_POSITION}. -->
<item type="id" name="accessibilityActionScrollToPosition" />
+ <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_UP}. -->
+ <item type="id" name="accessibilityActionScrollUp" />
+
+ <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_LEFT}. -->
+ <item type="id" name="accessibilityActionScrollLeft" />
+
+ <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_DOWN}. -->
+ <item type="id" name="accessibilityActionScrollDown" />
+
+ <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_RIGHT}. -->
+ <item type="id" name="accessibilityActionScrollRight" />
+
<!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_STYLUS_BUTTON_PRESS}. -->
<item type="id" name="accessibilityActionStylusButtonPress" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1a5977f..91c3d2e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2652,6 +2652,10 @@
<public type="id" name="replaceText" />
<public type="id" name="accessibilityActionShowOnScreen" />
<public type="id" name="accessibilityActionScrollToPosition" />
+ <public type="id" name="accessibilityActionScrollUp" />
+ <public type="id" name="accessibilityActionScrollLeft" />
+ <public type="id" name="accessibilityActionScrollDown" />
+ <public type="id" name="accessibilityActionScrollRight" />
<public type="id" name="shareText" />
<public type="id" name="accessibilityActionStylusButtonPress" />
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 52f086e..ab3069e 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -57,7 +57,7 @@ Platform Versions</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on April 6, 2015.
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 4, 2015.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -88,7 +88,7 @@ Screens</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on April 6, 2015.
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 4, 2015.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -108,7 +108,7 @@ support for any lower version (for example, support for version 2.0 also implies
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0%7CGL%203.1&chf=bg%2Cs%2C00000000&chd=t%3A65.9%2C33.8%2C0.3&chco=c4df9b%2C6fad0c&cht=p&chs=400x250">
+src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0%7CGL%203.1&chf=bg%2Cs%2C00000000&chd=t%3A64.1%2C34.5%2C1.4&chco=c4df9b%2C6fad0c&cht=p&chs=400x250">
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -126,21 +126,21 @@ uses.</p>
</tr>
<tr>
<td>2.0</td>
-<td>65.9%</td>
+<td>64.1%</td>
</tr>
<tr>
<td>3.0</td>
-<td>33.8%</td>
+<td>34.5%</td>
</tr>
<tr>
<td>3.1</td>
-<td>0.3%</td>
+<td>1.4%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on April 6, 2015</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 4, 2015</em></p>
@@ -158,52 +158,52 @@ uses.</p>
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop&chf=bg%2Cs%2C00000000&chd=t%3A0.4%2C6.4%2C5.7%2C40.7%2C41.4%2C5.4&chco=c4df9b%2C6fad0c&chs=500x250&cht=p",
+ "chart": "//chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A0.3%2C5.7%2C5.3%2C39.2%2C39.8%2C9.7&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop&chs=500x250&cht=p&chco=c4df9b%2C6fad0c",
"data": [
{
"api": 8,
"name": "Froyo",
- "perc": "0.4"
+ "perc": "0.3"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "6.4"
+ "perc": "5.7"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "5.7"
+ "perc": "5.3"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "16.5"
+ "perc": "15.6"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "18.6"
+ "perc": "18.1"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "5.6"
+ "perc": "5.5"
},
{
"api": 19,
"name": "KitKat",
- "perc": "41.4"
+ "perc": "39.8"
},
{
"api": 21,
"name": "Lollipop",
- "perc": "5.0"
+ "perc": "9.0"
},
{
"api": 22,
"name": "Lollipop",
- "perc": "0.4"
+ "perc": "0.7"
}
]
}
@@ -222,14 +222,14 @@ var SCREEN_DATA =
"xhdpi": "0.6"
},
"Normal": {
- "hdpi": "39.3",
- "mdpi": "8.1",
+ "hdpi": "39.5",
+ "mdpi": "7.6",
"tvdpi": "0.1",
- "xhdpi": "19.5",
- "xxhdpi": "15.9"
+ "xhdpi": "19.8",
+ "xxhdpi": "16.2"
},
"Small": {
- "ldpi": "4.4"
+ "ldpi": "4.1"
},
"Xlarge": {
"hdpi": "0.3",
@@ -237,8 +237,8 @@ var SCREEN_DATA =
"xhdpi": "0.6"
}
},
- "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chf=bg%2Cs%2C00000000&chd=t%3A4.8%2C16.1%2C2.3%2C40.2%2C20.7%2C15.9&chco=c4df9b%2C6fad0c&chs=400x250&cht=p",
- "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chf=bg%2Cs%2C00000000&chd=t%3A4.1%2C8.6%2C82.9%2C4.4&chco=c4df9b%2C6fad0c&chs=400x250&cht=p"
+ "densitychart": "//chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A4.5%2C15.6%2C2.3%2C40.4%2C21.0%2C16.2&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chs=400x250&cht=p&chco=c4df9b%2C6fad0c",
+ "layoutchart": "//chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A4.1%2C8.6%2C83.2%2C4.1&chl=Xlarge%7CLarge%7CNormal%7CSmall&chs=400x250&cht=p&chco=c4df9b%2C6fad0c"
}
];
diff --git a/docs/html/auto/index.jd b/docs/html/auto/index.jd
index ca63a54..66ea15a 100644
--- a/docs/html/auto/index.jd
+++ b/docs/html/auto/index.jd
@@ -3,7 +3,7 @@ page.viewport_width=970
fullpage=true
no_footer_links=true
page.type=about
-page.image=/auto/images/hero.jpg
+page.image=/images/cards/android-auto_2x.png
@jd:body
@@ -12,9 +12,6 @@ page.image=/auto/images/hero.jpg
#jd-content>.content-footer.wrap {
display:none;
}
-#hero-height {
- height:calc(100% - 100px);
-}
.img-logo {
margin:0 auto;
display:block;
diff --git a/docs/html/design/building-blocks/buttons.jd b/docs/html/design/building-blocks/buttons.jd
index e698f38..713574a 100644
--- a/docs/html/design/building-blocks/buttons.jd
+++ b/docs/html/design/building-blocks/buttons.jd
@@ -21,27 +21,27 @@ page.tags=button,input
will occur when the user touches it. A button can have an image, text, or both.
</p>
-<div class="layout-content-row" style="margin-top:22px">
- <div class="layout-content-col span-3">
+<div class="cols" style="margin-top:22px">
+ <div class="col-3">
<img src="{@docRoot}design/media/icon_magnifying_glass.png" style="height:64px;padding:20px 0 0 40px;">
</div>
- <div class="layout-content-col span-3">
+ <div class="col-3">
<img src="{@docRoot}design/media/buttons_text.png" style="height:94px;">
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/buttons_image_and_text.png" style="height:94px;">
</div>
</div>
-<div class="layout-content-row" style="margin-top:0;">
- <div class="layout-content-col span-3">
+<div class="cols" style="margin-top:0;">
+ <div class="col-3">
<p>An image alone works best when the action can be represented by a symbol that's well understood.</p>
</div>
- <div class="layout-content-col span-3">
+ <div class="col-3">
<p>Text alone is most appropriate for actions that would be difficult to
represent visually, or are critical to convey in words to avoid any ambiguity.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<p>
Both an icon and text is most appropriate when they complement each other:
each carrying its own bit of information, but together making a larger whole.
@@ -57,24 +57,24 @@ page.tags=button,input
<h3>What about button backgrounds?</h3>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>For <strong>image-only</strong> buttons, a background isn't necessary because
users are accustomed to interacting with objects.</p>
- <div class="layout-content-row" style="margin-left:72px">
- <div class="layout-content-col span-2">
+ <div class="cols" style="margin-left:72px">
+ <div class="col-2">
<div class="do-dont-label bad emulate-content-left-padding" style="width:30px">Don't</div>
<img src="{@docRoot}design/media/buttons_image_bg_dont.png" style="padding-left:14px;">
</div>
- <div class="layout-content-col span-2" style="width:29px;margin-left:10px;">
+ <div class="col-2" style="width:29px;margin-left:10px;">
<div class="do-dont-label good"><strong>Do</strong></div>
<img src="{@docRoot}design/media/icon_alarm.png" style="width:31px;padding-top:7px;">
</div>
</div>
</div>
-<div class="layout-content-col span-7">
+<div class="col-7">
<p>
For buttons <strong>with text</strong>, a background is also usually
unnecessary. To invite users to touch, phrase it as a clear action (e.g.
diff --git a/docs/html/design/building-blocks/dialogs.jd b/docs/html/design/building-blocks/dialogs.jd
index 9c91abf..70460ba 100644
--- a/docs/html/design/building-blocks/dialogs.jd
+++ b/docs/html/design/building-blocks/dialogs.jd
@@ -62,13 +62,13 @@ user to adjust settings or enter text.</p>
proceeding. They differ slightly in appearance based upon the severity and impact of the message
conveyed.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/dialogs_w_no_title.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Alerts without title bars</h4>
<p>Most alerts don't need titles. Usually the decision doesn't have a severe impact and can be summed
@@ -79,13 +79,13 @@ this conversation?") or make a clear statement whose relationship to the action
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/dialogs_w_title.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Alerts with title bars</h4>
<p>Use alerts with title bars sparingly. They are appropriate only when a high-risk operation involving
@@ -99,8 +99,8 @@ available based on the title and the text of the action buttons.</p>
</div>
<p>When crafting a confirmation dialog, make the title meaningful by echoing the requested action.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<div class="do-dont-label bad">Don't</div>
<table class="ui-table bad">
<thead>
@@ -112,7 +112,7 @@ available based on the title and the text of the action buttons.</p>
</thead>
</table>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="do-dont-label bad">Don't</div>
<table class="ui-table bad">
<thead>
@@ -124,7 +124,7 @@ available based on the title and the text of the action buttons.</p>
</thead>
</table>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<div class="do-dont-label good">Do</div>
<table class="ui-table good">
<thead>
@@ -151,8 +151,8 @@ advances the workflow, and simply touching outside the popup dismisses it.</p>
<h2 id="toasts">Toasts</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<div class="vspace size-3"></div>
@@ -177,7 +177,7 @@ continue editing later. Toasts automatically disappear after a timeout.</p>
</a>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/dialogs_toasts.png">
diff --git a/docs/html/design/building-blocks/grid-lists.jd b/docs/html/design/building-blocks/grid-lists.jd
index ac3a3eb..7a1c652 100644
--- a/docs/html/design/building-blocks/grid-lists.jd
+++ b/docs/html/design/building-blocks/grid-lists.jd
@@ -36,13 +36,13 @@ cutting off grid items to communicate where the overflow is located.</p>
<p>Avoid creating grid lists that scroll in two dimensions.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<img src="{@docRoot}design/media/gridview_vertical.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Vertical scrolling</h4>
<p>Vertically scrolling grid list items are sorted in traditional western reading direction:
@@ -53,13 +53,13 @@ scheme when the user rotates the screen.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<img src="{@docRoot}design/media/gridview_horizontal.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Horizontal scrolling</h4>
<p>Horizontally scrolling lists fix the vertical axis of the item grid. Compared to vertically
@@ -80,13 +80,13 @@ navigation.</p>
<p>Use labels to display additional contextual information for your grid list items.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<img src="{@docRoot}design/media/gridview_style.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Style</h4>
<p>Use semi-transparent panels on top of the grid list items to display your labels. This allows you to
diff --git a/docs/html/design/building-blocks/lists.jd b/docs/html/design/building-blocks/lists.jd
index 6f69feb..85753c8 100644
--- a/docs/html/design/building-blocks/lists.jd
+++ b/docs/html/design/building-blocks/lists.jd
@@ -15,13 +15,13 @@ well as drilldown navigation.</p>
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row clearfix">
- <div class="layout-content-col span-9">
+<div class="cols clearfix">
+ <div class="col-9">
<img src="{@docRoot}design/media/lists_main.png">
</div>
- <div class="layout-content-col span-4 with-callouts">
+ <div class="col-4 with-callouts">
<ol style="margin-bottom: 60px;">
<li>
diff --git a/docs/html/design/building-blocks/pickers.jd b/docs/html/design/building-blocks/pickers.jd
index fb5e287..72da0f7 100644
--- a/docs/html/design/building-blocks/pickers.jd
+++ b/docs/html/design/building-blocks/pickers.jd
@@ -13,13 +13,13 @@ page.tags=datepicker,timepicker
up/down arrow buttons, it's possible to set the desired value from the keyboard or via a swipe
gesture.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/picker_space.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Space considerations</h4>
<p>Pickers can be used inline on a form, but their relatively large footprint is best suited for
diff --git a/docs/html/design/building-blocks/progress.jd b/docs/html/design/building-blocks/progress.jd
index 2de75dc..ae81440 100644
--- a/docs/html/design/building-blocks/progress.jd
+++ b/docs/html/design/building-blocks/progress.jd
@@ -32,13 +32,13 @@ page.tags=progressbar,download,network
<p>Two styles are available: a bar and a circle. Each is offered in a variety of sizes, in both Holo Light and Holo Dark themes. Choose the appropriate style and size for the surrounding context. For example, the largest activity circle works well when displayed in a blank content area, but not in a smaller dialog box. Each operation should only be represented by one activity indicator.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/progress_activity.png">
</div>
- <div class="layout-content-col span-7 with-callouts">
+ <div class="col-7 with-callouts">
<ol>
<li class="value-1"><h4>Activity bar</h4>
@@ -49,13 +49,13 @@ page.tags=progressbar,download,network
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/progress_activity2.png">
</div>
- <div class="layout-content-col span-7 with-callouts">
+ <div class="col-7 with-callouts">
<ol>
<li class="value-2"><h4>Activity circle</h4>
@@ -91,11 +91,11 @@ In all of the Google Play apps (Music, Books, Movies, Magazines), we wanted the
<p>The color indicates whether it's downloaded (blue) or not (gray). The appearance of the pin indicates whether the download is permanent (white, upright) or temporary (gray, diagonal). And when state is in the process of changing, progress is indicated by a moving pie chart.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-9">
+<div class="cols">
+ <div class="col-9">
<img src="{@docRoot}design/media/progress_activity_custom_app.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="figure-caption">
Across Google Play apps with different layouts, the same custom indicator appears with each item. It communicates download state as well as progress, in a compact package that can be incorporated into any screen design.
</div>
diff --git a/docs/html/design/building-blocks/seek-bars.jd b/docs/html/design/building-blocks/seek-bars.jd
index 5c42102..04446d2 100644
--- a/docs/html/design/building-blocks/seek-bars.jd
+++ b/docs/html/design/building-blocks/seek-bars.jd
@@ -15,13 +15,13 @@ by moving the slider thumb. The smallest value is to the left, the largest to th
interactive nature of the slider makes it a great choice for settings that reflect intensity levels,
such as volume, brightness, or color saturation.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-9">
+<div class="cols">
+ <div class="col-9">
<img src="{@docRoot}design/media/seekbar_example.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="vspace size-2">&nbsp;</div>
@@ -32,8 +32,8 @@ such as volume, brightness, or color saturation.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-9">
+<div class="cols">
+ <div class="col-9">
<img src="{@docRoot}design/media/seekbar_style.png">
<div class="figure-caption">
@@ -41,5 +41,5 @@ such as volume, brightness, or color saturation.</p>
</div>
</div>
- <div class="layout-content-col span-4">&nbsp;</div>
+ <div class="col-4">&nbsp;</div>
</div>
diff --git a/docs/html/design/building-blocks/spinners.jd b/docs/html/design/building-blocks/spinners.jd
index 3a74ccf..31c5558 100644
--- a/docs/html/design/building-blocks/spinners.jd
+++ b/docs/html/design/building-blocks/spinners.jd
@@ -22,8 +22,8 @@ its currently selected value. Touching the spinner displays a dropdown menu with
values, from which the user can select a new one.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/spinners_form.png">
@@ -34,7 +34,7 @@ fields. For example, a text field might let you edit an email address for a cont
associated spinner allows you to select whether it's a Home or Work address.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/spinners_actionbar.png">
diff --git a/docs/html/design/building-blocks/tabs.jd b/docs/html/design/building-blocks/tabs.jd
index 078de92..1315a2f 100644
--- a/docs/html/design/building-blocks/tabs.jd
+++ b/docs/html/design/building-blocks/tabs.jd
@@ -27,14 +27,14 @@ aspects of your app, or to browse categorized data sets.</p>
<h2 id="scrollable">Scrollable Tabs</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>Scrolling tab controls can contain a larger number of items than a standard tab control. To navigate
to the next/previous view, swipe left or right.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<video width="400" class="with-shadow play-on-hover" autoplay>
<source src="{@docRoot}design/media/tabs_scrolly.mp4" type="video/mp4">
diff --git a/docs/html/design/building-blocks/text-fields.jd b/docs/html/design/building-blocks/text-fields.jd
index 19c22f9..9403679 100644
--- a/docs/html/design/building-blocks/text-fields.jd
+++ b/docs/html/design/building-blocks/text-fields.jd
@@ -24,8 +24,8 @@ typing, text fields allow for a variety of other activities, such as text select
paste) and data lookup via auto-completion.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-12">
+<div class="cols">
+ <div class="col-12">
<img src="{@docRoot}design/media/text_input_singlevsmultiline.png">
@@ -39,8 +39,8 @@ overflow text and scroll vertically when the cursor reaches the lower edge.</p>
<img src="{@docRoot}design/media/text_input_typesandtypedown.png">
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Text field types</h4>
<p>Text fields can have different types, such as number, message, or email address. The type determines
@@ -48,7 +48,7 @@ what kind of characters are allowed inside the field, and may prompt the virtual
optimize its layout for frequently used characters.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Auto-complete text fields</h4>
<p>Use auto-complete text fields to present real-time completions or search results in popups, so users
@@ -63,13 +63,13 @@ can enter information more accurately and efficiently.</p>
mode that facilitates extending the selection or choosing an action to perform on the selected text.
Selection mode includes:</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-9">
+<div class="cols">
+ <div class="col-9">
<img src="{@docRoot}design/media/text_input_textselection.png">
</div>
- <div class="layout-content-col span-4 with-callouts">
+ <div class="col-4 with-callouts">
<ol>
<li>
diff --git a/docs/html/design/devices.jd b/docs/html/design/devices.jd
index c67e585..3d23d07 100644
--- a/docs/html/design/devices.jd
+++ b/docs/html/design/devices.jd
@@ -1,8 +1,9 @@
-page.title=Devices
+page.title=Android devices
page.viewport_width=970
section.landing=true
header.hide=1
footer.hide=1
+page.image=images/cards/android-devices_2x.jpg
@jd:body
<style>
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index 4111bca..0b9f59f 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -9,8 +9,8 @@ and implementation.</p>
<h2 id="stencils">Phone &amp; Tablet Stencils</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<p>Drag and drop your way to beautifully designed Android apps. The stencils feature the
@@ -19,13 +19,13 @@ phone and tablet outlines to frame your creations. Source files for icons and co
available.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_stencils.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="notice-designers-material"
style="width:218px;"
href="http://www.google.com/design/spec/resources/layout-templates.html">
@@ -36,7 +36,7 @@ available.</p>
</a>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="notice-designers-material"
style="width:218px;"
href="http://www.google.com/design/spec/resources/sticker-sheets-icons.html">
@@ -47,7 +47,7 @@ available.</p>
</a>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<p>
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Photoshop Sources');"
href="{@docRoot}downloads/design/Android_Design_Stencils_Sources_20131106.zip">Adobe&reg; Photoshop&reg; Stencils and Sources</a>
@@ -63,8 +63,8 @@ available.</p>
<h2 id="action-bar-icon-pack">Action Bar Icon Pack</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<p>Action bar icons are graphic buttons that represent the most important actions people can take
within your app. <a href="{@docRoot}design/style/iconography.html">More on Action Bar Iconography</a></p>
@@ -73,13 +73,13 @@ use with the Holo Light and Holo Dark themes. The package also includes unstyled
modify to match your theme, plus source files.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_actionbar_style.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="notice-designers-material"
style="width:218px;"
href="http://www.google.com/design/spec/resources/sticker-sheets-icons.html">
@@ -90,7 +90,7 @@ modify to match your theme, plus source files.</p>
</a>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<p>
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Action Bar Icons');"
@@ -106,18 +106,18 @@ modify to match your theme, plus source files.</p>
<h2 id="Wear">Android Wear Materials</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>UI toolkit</h4>
<p>The toolkit contains detailed specs and measurements of all of the primary Android Wear UI components. Available in PDF and Illustrator formats.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_toolkit.png" width="220">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear Toolkit AI');"
href="{@docRoot}downloads/design/Android_Wear_Toolkit_20140722.ai">Adobe&reg; Illustrator&reg; Toolkit</a>
@@ -127,18 +127,18 @@ modify to match your theme, plus source files.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Sample user flow patterns</h4>
<p>Examples of how to chain together simple Android Wear UI components into common user flow patterns, from simple notifications to complex interactions involving full screen activities.
</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_flows.png" width="220">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear App Patterns AI');"
href="{@docRoot}downloads/design/Android_Wear_Patterns_20140722.ai">Adobe&reg; Illustrator&reg; App Patterns</a>
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear App Patterns PDF');"
@@ -147,99 +147,99 @@ modify to match your theme, plus source files.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Sample app design mocks</h4>
<p>Stream cards and UI elements for some example apps in fully editable PSD format.
</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_psds.png" width="220">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear Sample PSD Mocks');"
href="{@docRoot}downloads/design/Android_Wear_Sample_Assets.zip">Adobe&reg; Photoshop&reg; mocks</a>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Watch faces UI toolkit</h4>
<p>Detailed specifications and measurements for the the background canvas, notification cards, and
system indicators.
</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_DesignSpec_Icon.png" width="220">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear Watch Face Specifications');"
href="{@docRoot}downloads/design/AndroidWear_DesignSpec_11.13.pdf">PDF Toolkit</a>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Slide watch face</h4>
<p>Example of a watch face design in AI format.
</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_Slide_Ai_Icon.png" width="150"
style="width:150px;margin:0 auto;display:block">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear Watch Face Example');"
href="{@docRoot}downloads/design/Slide.ai">Adobe&reg; Illustrator&reg; Design</a>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Slide watch face specifications</h4>
<p>Design specifications for the Slide watch face in PSD format.
</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_Slide_Psd_Icon.png" width="150"
style="width:150px;margin:0 auto;display:block">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear Watch Face Example Specifications');"
href="{@docRoot}downloads/design/Slide.psd">Adobe&reg; Photoshop&reg; Specifications</a>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Watch face icon example</h4>
<p>Template for creating watch face icons for the carousel on Android Wear devices.
</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_wear_Slide_IconExample.png" width="150"
style="width:150px;margin:0 auto;display:block">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Wear Watch Face Example Specifications');"
href="{@docRoot}downloads/design/Slide_IconExample.psd">Adobe&reg; Photoshop&reg; Icon</a>
</div>
@@ -250,8 +250,8 @@ system indicators.
<h2 id="style">Style</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4 id="roboto">Roboto</h4>
<p>Ice Cream Sandwich introduced a new type family named Roboto, created specifically for the
@@ -262,13 +262,13 @@ requirements of UI and high-resolution screens.</p>
<p><a href="http://www.google.com/fonts/specimen/Roboto+Condensed" class="external-link">Roboto Condensed on Google Fonts</a></p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_roboto_specimen_preview.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="notice-designers-material"
style="width:218px;"
href="http://www.google.com/design/spec/resources/roboto-noto-fonts.html">
@@ -279,7 +279,7 @@ requirements of UI and high-resolution screens.</p>
</a>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<p>
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Roboto ZIP');"
@@ -291,8 +291,8 @@ requirements of UI and high-resolution screens.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Color</h4>
<p>In Android's color palette, each color has a corresponding darker
@@ -300,13 +300,13 @@ shade that can be used as a complement when needed.</p>
<p><a href="{@docRoot}design/style/color.html">More on Color</a></p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/downloads_color_swatches.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<a class="notice-designers-material"
style="width:218px;"
href="http://www.google.com/design/spec/resources/color-palettes.html">
@@ -317,7 +317,7 @@ shade that can be used as a complement when needed.</p>
</a>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<p>
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Color Swatches');"
diff --git a/docs/html/design/get-started/creative-vision.jd b/docs/html/design/get-started/creative-vision.jd
index 9261c6e..3955494 100644
--- a/docs/html/design/get-started/creative-vision.jd
+++ b/docs/html/design/get-started/creative-vision.jd
@@ -1,4 +1,5 @@
page.title=Creative Vision
+page.image=images/cards/design-creative-vision_2x.jpg
@jd:body
<img src="{@docRoot}design/media/creative_vision_main.png">
@@ -14,8 +15,8 @@ page.title=Creative Vision
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Enchant me</h4>
<p>Beauty is more than skin deep. Android apps are sleek and aesthetically pleasing on multiple levels.
@@ -24,7 +25,7 @@ of art in their own right. Just like a well-made tool, your app should strive to
simplicity and purpose to create a magical experience that is effortless and powerful.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Simplify my life</h4>
<p>Android apps make life easier and are easy to understand. When people use your app for the first
@@ -35,7 +36,7 @@ of all ages and cultures feel firmly in control, and are never overwhelmed by to
irrelevant flash.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Make me amazing</h4>
<p>It's not enough to make an app that is easy to use. Android apps empower people to try new things
diff --git a/docs/html/design/get-started/principles.jd b/docs/html/design/get-started/principles.jd
index 73ec3a6..172a4e4 100644
--- a/docs/html/design/get-started/principles.jd
+++ b/docs/html/design/get-started/principles.jd
@@ -14,8 +14,8 @@ creativity and design thinking. Deviate with purpose.
<h2 id="enchant-me">Enchant Me</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="delight-me">Delight me in surprising ways</h4>
<p>A beautiful surface, a carefully-placed animation, or a well-timed sound effect is a joy to
@@ -23,7 +23,7 @@ experience. Subtle effects contribute to a feeling of effortlessness and a sense
force is at hand.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_delight.png">
@@ -32,15 +32,15 @@ force is at hand.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="real-objects-more-fun">Real objects are more fun than buttons and menus</h4>
<p>Allow people to directly touch and manipulate objects in your app. It reduces the cognitive effort
needed to perform a task while making it more emotionally satisfying.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_real_objects.png">
@@ -49,8 +49,8 @@ needed to perform a task while making it more emotionally satisfying.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="make-it-mine">Let me make it mine</h4>
<p>People love to add personal touches because it helps them feel at home and in control. Provide
@@ -58,7 +58,7 @@ sensible, beautiful defaults, but also consider fun, optional customizations tha
primary tasks.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_make_it_mine.png">
@@ -67,15 +67,15 @@ primary tasks.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="get-to-know-me">Get to know me</h4>
<p>Learn peoples' preferences over time. Rather than asking them to make the same choices over and
over, place previous choices within easy reach.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
@@ -84,14 +84,14 @@ over, place previous choices within easy reach.</p>
<h2 id="simplify-my-life">Simplify My Life</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="keep-it-brief">Keep it brief</h4>
<p>Use short phrases with simple words. People are likely to skip sentences if they're long.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
@@ -100,15 +100,15 @@ over, place previous choices within easy reach.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="pictures-faster-than-words">Pictures are faster than words</h4>
<p>Consider using pictures to explain ideas. They get people's attention and can be much more efficient
than words.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_pictures.png">
@@ -117,15 +117,15 @@ than words.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="decide-for-me">Decide for me but let me have the final say</h4>
<p>Take your best guess and act rather than asking first. Too many choices and decisions make people
unhappy. Just in case you get it wrong, allow for 'undo'.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_decide_for_me.png">
@@ -134,15 +134,15 @@ unhappy. Just in case you get it wrong, allow for 'undo'.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="only-show-when-i-need-it">Only show what I need when I need it</h4>
<p>People get overwhelmed when they see too much at once. Break tasks and information into small,
digestible chunks. Hide options that aren't essential at the moment, and teach people as they go.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
@@ -151,15 +151,15 @@ digestible chunks. Hide options that aren't essential at the moment, and teach p
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="always-know-where-i-am">I should always know where I am</h4>
<p>Give people confidence that they know their way around. Make places in your app look distinct and
use transitions to show relationships among screens. Provide feedback on tasks in progress.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_navigation.png">
@@ -168,8 +168,8 @@ use transitions to show relationships among screens. Provide feedback on tasks i
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="never-lose-my-stuff">Never lose my stuff</h4>
<p>Save what people took time to create and let them access it from anywhere. Remember settings,
@@ -177,7 +177,7 @@ personal touches, and creations across phones, tablets, and computers. It makes
easiest thing in the world.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
@@ -186,15 +186,15 @@ easiest thing in the world.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="looks-same-should-act-same">If it looks the same, it should act the same</h4>
<p>Help people discern functional differences by making them visually distinct rather than subtle.
Avoid modes, which are places that look similar but act differently on the same input.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_looks_same.png">
@@ -203,15 +203,15 @@ Avoid modes, which are places that look similar but act differently on the same
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="interrupt-only-if-important">Only interrupt me if it's important</h4>
<p>Like a good personal assistant, shield people from unimportant minutiae. People want to stay
focused, and unless it's critical and time-sensitive, an interruption can be taxing and frustrating.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_important_interruption.png">
@@ -220,8 +220,8 @@ focused, and unless it's critical and time-sensitive, an interruption can be tax
<h2 id="make-me-amazing">Make Me Amazing</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="give-me-tricks">Give me tricks that work everywhere</h4>
<p>People feel great when they figure things out for themselves. Make your app easier to learn by
@@ -229,7 +229,7 @@ leveraging visual patterns and muscle memory from other Android apps. For exampl
may be a good navigational shortcut.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_tricks.png">
@@ -238,8 +238,8 @@ may be a good navigational shortcut.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="its-not-my-fault">It's not my fault</h4>
<p>Be gentle in how you prompt people to make corrections. They want to feel smart when they use your
@@ -247,7 +247,7 @@ app. If something goes wrong, give clear recovery instructions but spare them th
If you can fix it behind the scenes, even better.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_error.png">
@@ -256,15 +256,15 @@ If you can fix it behind the scenes, even better.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="sprinkle-encouragement">Sprinkle encouragement</h4>
<p>Break complex tasks into smaller steps that can be easily accomplished. Give feedback on actions,
even if it's just a subtle glow.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
@@ -273,8 +273,8 @@ even if it's just a subtle glow.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="do-heavy-lifting-for-me">Do the heavy lifting for me</h4>
<p>Make novices feel like experts by enabling them to do things they never thought they could. For
@@ -282,7 +282,7 @@ example, shortcuts that combine multiple photo effects can make amateur photogra
only a few steps.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
@@ -291,15 +291,15 @@ only a few steps.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4 id="make-important-things-fast">Make important things fast</h4>
<p>Not all actions are equal. Decide what's most important in your app and make it easy to find and
fast to use, like the shutter button in a camera, or the pause button in a music player.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/principles_make_important_fast.png">
diff --git a/docs/html/design/handhelds/index.jd b/docs/html/design/handhelds/index.jd
index 882b070..81c2c19 100644
--- a/docs/html/design/handhelds/index.jd
+++ b/docs/html/design/handhelds/index.jd
@@ -20,8 +20,8 @@ and tablets.
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/ui_overview_home_screen.png">
@@ -34,7 +34,7 @@ regardless of which panel is currently showing.</p>
the Favorites Tray.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/ui_overview_all_apps.png">
@@ -45,7 +45,7 @@ device.</p>
any Home screen.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/ui_overview_recents.png">
@@ -94,13 +94,13 @@ provide updates, reminders, or information that's important, but not critical en
interrupting the user. Open the notifications drawer by swiping down on the status bar. Touching a
notification opens the associated app. <a href="{@docRoot}design/patterns/notifications.html">More on Notifications</a></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/ui_overview_notifications.png">
</div>
- <div class="layout-content-col span-9">
+ <div class="col-9">
<img src="{@docRoot}design/media/notifications_dismiss.png">
@@ -116,13 +116,13 @@ notification opens the associated app. <a href="{@docRoot}design/patterns/notifi
<h2 id="app">Common App UI</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<img src="{@docRoot}design/media/app_structure_drawer.png">
</div>
- <div class="layout-content-col span-6 with-callouts">
+ <div class="col-6 with-callouts">
<p>A typical Android app uses action bars, and many apps will include a navigation drawer.</p>
<ol>
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
index 47e8d26..74af6e7 100644
--- a/docs/html/design/index.jd
+++ b/docs/html/design/index.jd
@@ -1,3 +1,4 @@
+fullpage=true
page.title=Design
page.viewport_width=970
section.landing=true
@@ -6,43 +7,70 @@ header.hide=1
footer.hide=1
@jd:body
-<style>
-#landing-graphic-container {
- position: relative;
-}
-
-#text-overlay {
- position: absolute;
- left: 0;
- top: 42px;
- width: 266px;
-
-}
-#hero-image {
- padding-left:68px;
-}
-</style>
-
-<div id="landing-graphic-container">
- <div id="text-overlay">
- <span itemprop="description">Welcome to <strong>Android Design</strong>, your place for
- learning how to design exceptional Android apps.</span>
- <br><br>
- Want to know what <strong>Android 5.0</strong> has for designers? See <a href="{@docRoot}design/patterns/new.html">New in Android</a>.<br><br>
- <a href="/design/get-started/creative-vision.html" class="landing-page-link">Creative Vision</a>
+<section class="dac-expand dac-hero dac-light">
+ <div class="wrap">
+ <div class="cols dac-hero-content">
+ <div class="col-1of2 col-push-1of2 dac-hero-figure">
+ <img class="dac-hero-image" src="/design/media/hero-material-design.png">
+ </div>
+ <div class="col-1of2 col-pull-1of2">
+ <h1 class="dac-hero-title">Up and running with Material Design</h1>
+ <p class="dac-hero-description">
+ Android 5.0 introduces a design metaphor inspired by paper and ink that provides a reassuring sense of tactility.
+ </p>
+ <a class="dac-hero-cta" href="https://www.google.com/design/spec/material-design/introduction.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Introducing Material Design
+ </a><br>
+ <a class="dac-hero-cta" href="/design/material/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Material Design for Android
+ </a><br>
+ <a class="dac-hero-cta" href="https://www.google.com/design/spec/resources/color-palettes.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Downloads for designers
+ </a><br>
+ <a class="dac-hero-cta" href="https://google.com/design/articles/">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Articles
+ </a>
+ </div>
+ </div>
+ <div class="dac-section dac-small">
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:design/landing/materialdesign"
+ data-cardSizes="6x2"
+ data-maxResults="6"></div>
+ </div>
</div>
- <a id="hero-image" href="/design/get-started/creative-vision.html">
- <img src="{@docRoot}design/media/index_landing_page.png" width="760" height="600" alt=""
- srcset="{@docRoot}design/media/index_landing_page_2x.png 2x"/>
- </a>
+</section>
-<div style="background: hsl(8, 70%, 54%); margin: 0; padding: 20px 20px 10px 20px;color: #fff; position: absolute;top: 255px;width: 179px;">
-<h2 style="color: #fff;margin:0 0 10px; font-size:18px" class="norule">Material Design</h2>
-<p>Android 5.0 introduces a design
-metaphor inspired by paper and ink that provides a reassuring sense of tactility.
-</p>
-<p><a class="white" href="{@docRoot}design/material/index.html">Learn more</a></p>
-</div>
+<section class="dac-section dac-gray dac-small dac-invert"><div class="wrap">
+ <h2 class="norule">Latest</h2>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:design/landing/latest"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+</div></section>
-</div>
+<section class="dac-section dac-light"><div class="wrap">
+ <h1 class="dac-section-title">Pure Android</h1>
+ <div class="dac-section-subtitle">
+ This is a place holder paragraph. Some text here would povide some context.
+ </div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:design/landing/pureandroid"
+ data-cardSizes="6x6"
+ data-maxResults="6"></div>
+</div></section>
+<section class="dac-section dac-gray"><div class="wrap">
+ <h1 class="dac-section-title">Resources</h1>
+ <div class="dac-section-subtitle">
+ This is a place holder paragraph. Some text here would povide some context.
+ </div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:design/landing/resources"
+ data-cardSizes="6x2"
+ data-maxResults="6"></div>
+</div></section>
diff --git a/docs/html/design/material/index.jd b/docs/html/design/material/index.jd
index 4d9a1a7..c5893a7 100644
--- a/docs/html/design/material/index.jd
+++ b/docs/html/design/material/index.jd
@@ -1,7 +1,7 @@
-page.title=Material Design
+page.title=Material Design for Android
page.tags=Material,design
page.type=design
-page.image=design/material/images/MaterialLight.png
+page.image=images/cards/design-material-for-android_2x.jpg
@jd:body
diff --git a/docs/html/design/media/hero-material-design.png b/docs/html/design/media/hero-material-design.png
new file mode 100644
index 0000000..55c4420
--- /dev/null
+++ b/docs/html/design/media/hero-material-design.png
Binary files differ
diff --git a/docs/html/design/patterns/accessibility.jd b/docs/html/design/patterns/accessibility.jd
index b968237..b910294 100644
--- a/docs/html/design/patterns/accessibility.jd
+++ b/docs/html/design/patterns/accessibility.jd
@@ -48,11 +48,11 @@ page.metaDescription=Design an app that's universally accessible to people with
<h4>Label visual UI elements meaningfully</h4>
<p>In your wireframes, <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">label functional UI components</a> that have no visible text. Those components might be buttons, icons, tabs with icons, and icons with state (like stars). Developers can use the <code><a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">contentDescription</a></code> attribute to set the label.</p>
-<div class ="layout-content-row">
- <div class="layout-content-col span-8">
+<div class ="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/accessibility_contentdesc.png">
</div>
- <div class="layout-content-col span-5 with-callouts">
+ <div class="col-5 with-callouts">
<ol>
<li class="value-1">group</li>
<li class="value-2">all contacts</li>
@@ -95,4 +95,4 @@ page.metaDescription=Design an app that's universally accessible to people with
<li>Provide alternatives to affordances that time out</li>
<li>Use standard framework controls or enable TalkBack for custom controls</li>
<li>Try it out yourself</li>
-</ul> \ No newline at end of file
+</ul>
diff --git a/docs/html/design/patterns/actionbar.jd b/docs/html/design/patterns/actionbar.jd
index 5467722..ef02c53 100644
--- a/docs/html/design/patterns/actionbar.jd
+++ b/docs/html/design/patterns/actionbar.jd
@@ -34,8 +34,8 @@ page.metaDescription=The Action bar is an essential design element for all apps.
<p>The action bar is split into four different functional areas that apply to most apps.</p>
<img src="{@docRoot}design/media/action_bar_basics.png">
-<div class="layout-content-row">
- <div class="layout-content-col span-7 with-callouts">
+<div class="cols">
+ <div class="col-7 with-callouts">
<ol>
<li class="value-1"><h4>App icon</h4>
@@ -57,7 +57,7 @@ Up navigation, see the <a href="{@docRoot}design/patterns/navigation.html">Navig
</ol>
</div>
- <div class="layout-content-col span-6 with-callouts">
+ <div class="col-6 with-callouts">
<ol>
<li class="value-2"><h4>View control</h4>
@@ -107,8 +107,8 @@ content across multiple bars located below the main action bar or at the bottom
<h2 id="considerations-split-action-bars">Layout Considerations for Split Action Bars</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-8 with-callouts">
+<div class="cols">
+ <div class="col-8 with-callouts">
<p>When splitting up content across multiple action bars, you generally have three possible locations
for action bar content:</p>
@@ -124,7 +124,7 @@ the top bar.</p>
<p>To display actions and, if necessary, the action overflow, use the bottom bar.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<img src="{@docRoot}design/media/action_bar_pattern_considerations.png">
@@ -144,8 +144,8 @@ action overflow. The action bar should show only those actions that are availabl
<p>For guidance on prioritizing actions, use the FIT scheme.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<p><strong>F &mdash; Frequent</strong></p>
<ul>
@@ -155,7 +155,7 @@ action overflow. The action bar should show only those actions that are availabl
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<p><strong>I &mdash; Important</strong></p>
<ul>
@@ -164,7 +164,7 @@ action overflow. The action bar should show only those actions that are availabl
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<p><strong>T &mdash; Typical</strong></p>
<ul>
@@ -194,8 +194,8 @@ files for further customization.
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Action overflow</h4>
<p>The action overflow in the action bar provides access to your app's less frequently used actions.
@@ -203,7 +203,7 @@ The overflow icon only appears on phones that have no menu hardware keys. Phones
display the action overflow when the user presses the key.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/action_bar_pattern_overflow.png">
<div class="figure-caption">
@@ -285,4 +285,4 @@ actions exceeds the capacity of the main action bar, display them separately in
<p>Sometimes it is important to display contextual information for your app that's always visible.
Examples are the number of unread messages in a messaging inbox view or the Now Playing information
in a music player. Carefully plan which important information you would like to display and
-structure your action bars accordingly.</p> \ No newline at end of file
+structure your action bars accordingly.</p>
diff --git a/docs/html/design/patterns/app-structure.jd b/docs/html/design/patterns/app-structure.jd
index 404dd4d..4f3106e 100644
--- a/docs/html/design/patterns/app-structure.jd
+++ b/docs/html/design/patterns/app-structure.jd
@@ -25,13 +25,13 @@ page.tags=navigation,layout,tablet
<p>A typical Android app consists of top level and detail/edit views. If the navigation hierarchy is
deep and complex, category views connect top level and detail views.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-9">
+<div class="cols">
+ <div class="col-9">
<img src="{@docRoot}design/media/app_structure_overview.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Top level views</h4>
<p>The top level of the app typically consists of the different views that your app supports. The views
@@ -57,8 +57,8 @@ visitors alike.</p>
<p>Ask yourself: "What are my typical users most likely going to want to do in my app?", and structure
your start screen experience accordingly.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Put content forward</h4>
<p>Many apps focus on the content display. Avoid navigation-only screens and instead let people get to
@@ -66,7 +66,7 @@ the meat of your app right away by making content the centerpiece of your start
layouts that are visually engaging and appropriate for the data type and screen size.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/app_structure_market.png">
<div class="figure-caption">
@@ -80,8 +80,8 @@ layouts that are visually engaging and appropriate for the data type and screen
<h4>Set up action bars for navigation and actions</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<p>All screens in your app should display action bars to provide consistent navigation and surface
important actions.</p>
@@ -96,7 +96,7 @@ important actions.</p>
</ul>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/app_structure_gmail.png">
<div class="figure-caption">
@@ -111,8 +111,8 @@ important actions.</p>
<p>The top level communicates your app’s capabilities by introducing the user to the major functional areas. In many cases the top level will consist of multiple views, and you need to make sure that the user can navigate between them efficiently. Android supports a number of view controls for this task. Use the control that best matches your app's navigation needs:</p>
<h4>Fixed tabs</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p><em>Fixed tabs</em> display top-level views concurrently and make it easy to explore and switch between them. They are always visible on the screen, and can't be moved out of the way like scrollable tabs. <em>Fixed tabs</em> should always allow the user to navigate between the views by swiping left or right on the content area.</p>
<p><strong>Use tabs if</strong>:</p>
<ul>
@@ -122,7 +122,7 @@ important actions.</p>
</ul>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/app_structure_default_tabs.png">
<div class="figure-caption">
@@ -132,8 +132,8 @@ important actions.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Spinners</h4>
<p>A <em>spinner</em> is a drop-down menu that allows users to switch between views of your app. </p>
@@ -144,7 +144,7 @@ important actions.</p>
</ul>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/app_structure_spinner.png">
<div class="figure-caption">
@@ -155,8 +155,8 @@ important actions.</p>
</div>
<h4>Navigation drawers</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>A <em>navigation drawer</em> is a slide-out menu that allows users to switch between views of your app. It can hold a large number of items and is accessible from anywhere in your app. Navigation drawers show your app's top-level views, but can also provide navigation to lower-level screens. This makes them particularly suitable for complex apps.</p>
<p><strong>Use navigation drawers if</strong>:</p>
@@ -169,7 +169,7 @@ important actions.</p>
</ul>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/app_structure_drawer.png">
<div class="figure-caption">
Navigation drawer from the Keep app.
@@ -196,8 +196,8 @@ experience than to an explicit navigation step.</p>
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<p>If the categories are familiar, predictable, or closely related, use scrolling tabs (where not all
items are in view simultaneously). Keep the number of scrolling tabs at a manageable level to
@@ -210,7 +210,7 @@ minimize navigational effort. Rule of thumb: no more than 5&ndash;7 tabs.</p>
</div>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<p>If the categories in the tabs are not closely related, favor fixed tabs, so that all categories are
in view at the same time.</p>
@@ -257,14 +257,14 @@ design guide.</p>
<p>The detail view allows you to view and act on your data. The layout of the detail view depends on the data type being displayed, and therefore differs widely among apps.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Layout</h4>
<p>Consider the activities people will perform in the detail view and arrange the layout accordingly.</p>
</div>
- <div class="layout-content-col span-9">
+ <div class="col-9">
<img src="{@docRoot}design/media/app_structure_people_detail.png">
diff --git a/docs/html/design/patterns/buttons.jd b/docs/html/design/patterns/buttons.jd
index 2d65b2d..085acec 100644
--- a/docs/html/design/patterns/buttons.jd
+++ b/docs/html/design/patterns/buttons.jd
@@ -19,13 +19,13 @@ page.tags=buttons
back into view.
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Lean Back</h4>
<p>Touch the screen anywhere to bring back system bars. </p>
<img src="{@docRoot}design/media/fullscreen_leanback.png" style="width:311px;">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Immersive</h4>
<p>Swipe from the any edge of the screen with a hidden bar to bring back system bars. </p>
<img src="{@docRoot}design/media/fullscreen_immersive_swipe_bottom.png" style="width:160px;float:right">
@@ -69,8 +69,8 @@ page.tags=buttons
interrupted by accidental touches and swipes.
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/fullscreen_immersive_swipe_bottom.png" style="width:160px;float:right">
<img src="{@docRoot}design/media/fullscreen_immersive_swipe_top.png" style="width:160px">
</div>
diff --git a/docs/html/design/patterns/compatibility.jd b/docs/html/design/patterns/compatibility.jd
index dfc52c0..2905676 100644
--- a/docs/html/design/patterns/compatibility.jd
+++ b/docs/html/design/patterns/compatibility.jd
@@ -20,8 +20,8 @@ page.metaDescription=Notes on how Android 4.x adapts UI designed for older hardw
<h2 id="older-hardware">Adapting Android 4.0 to Older Hardware and Apps</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Phones with virtual navigation controls</h4>
<p>Android apps written for Android 3.0 and later display actions in the action bar. Actions that don't
@@ -30,15 +30,15 @@ action overflow.</p>
<p>Users access the action overflow by touching it in the action bar.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Phones with physical navigation keys</h4>
<p>Android phones with traditional navigation hardware keys don't display the virtual navigation bar at
@@ -46,15 +46,15 @@ the bottom of the screen. Instead, the action overflow is available from the men
resulting actions popup has the same style as in the previous example, but is displayed at the bottom of the screen.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Legacy apps on phones with virtual navigation controls</h4>
<p>When you run an app that was built for Android 2.3 or earlier on a phone with virtual navigation
@@ -62,7 +62,7 @@ controls, an action overflow control appears at the right side of the virtual na
can touch the control to display the app's actions in the traditional Android menu styling.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
diff --git a/docs/html/design/patterns/confirming-acknowledging.jd b/docs/html/design/patterns/confirming-acknowledging.jd
index d39d32d..201e5a0 100644
--- a/docs/html/design/patterns/confirming-acknowledging.jd
+++ b/docs/html/design/patterns/confirming-acknowledging.jd
@@ -4,12 +4,12 @@ page.tags=dialog,toast,notification
<p>In some situations, when a user invokes an action in your app, it's a good idea to <em>confirm</em> or <em>acknowledge</em> that action through text.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
<p><strong>Confirming</strong> is asking the user to verify that they truly want to proceed with an action they just invoked. In some cases, the confirmation is presented along with a warning or critical information related to the action that they need to consider.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
<p><strong>Acknowledging</strong> is displaying text to let the user know that the action they just invoked has been completed. This removes uncertainty about implicit operations that the system is taking. In some cases, the acknowledgment is presented along with an option to undo the action.</p>
</div>
@@ -22,14 +22,14 @@ page.tags=dialog,toast,notification
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
<h2>Confirming</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Example: Google Play Books</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
<p>In this example, the user has requested to delete a book from their Google Play library. An <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">alert</a> appears to confirm this action because it's important to understand that the book will no longer be available from any device.</p>
<p>When crafting a confirmation dialog, make the title meaningful by echoing the requested action.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<h4>Example: Android Beam</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
<p>Confirmations don't necessarily have to be presented in an alert with two buttons. After initiating Android Beam, the user is prompted to touch the content to be shared (in this example, it's a photo). If they decide not to proceed, they simply move their phone away.</p>
@@ -37,15 +37,15 @@ page.tags=dialog,toast,notification
</div>
<h2>Acknowledging</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Example: Abandoned Gmail draft saved</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
<p>In this example, if the user navigates back or up from the Gmail compose screen, something possibly unexpected happens: the current draft is automatically saved. An acknowledgment in the form of a toast makes that apparent. It fades after a few seconds.</p>
<p>Undo isn't appropriate here because saving was initiated by the app, not the user. And it's quick and easy to resume composing the message by navigating to the list of drafts.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Example: Gmail conversation deleted</h4>
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
<p>After the user deletes a conversation from the list in Gmail, an acknowledgment appears with an undo option. The acknowledgment remains until the user takes an unrelated action, such as scrolling the list.</p>
@@ -53,14 +53,14 @@ page.tags=dialog,toast,notification
</div>
<h2>No Confirmation or Acknowledgment</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Example: +1'ing</h4>
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
<p><strong>Confirmation is unnecessary</strong>. If the user +1'd by accident, it's not a big deal. They can just touch the button again to undo the action.</p>
<p><strong>Acknowledgment is unnecessary</strong>. The user will see the +1 button bounce and turn red. That's a very clear signal.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<h4>Example: Removing an app from the Home Screen</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
<p><strong>Confirmation is unnecessary</strong>. This is a deliberate action: the user must drag and drop an item onto a relatively large and isolated target. Therefore, accidents are highly unlikely. But if the user regrets the decision, it only takes a few seconds to bring it back again.</p>
diff --git a/docs/html/design/patterns/fullscreen.jd b/docs/html/design/patterns/fullscreen.jd
index 624d44c..1c95f21 100644
--- a/docs/html/design/patterns/fullscreen.jd
+++ b/docs/html/design/patterns/fullscreen.jd
@@ -19,13 +19,13 @@ page.tags=full screen,immersive,leanback
back into view.
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Lean Back</h4>
<p>Touch the screen anywhere to bring back system bars. </p>
<img src="{@docRoot}design/media/fullscreen_leanback.png" style="width:311px;">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Immersive</h4>
<p>Swipe from the any edge of the screen with a hidden bar to bring back system bars. </p>
<img src="{@docRoot}design/media/fullscreen_immersive_swipe_bottom.png" style="width:160px;float:right">
@@ -69,8 +69,8 @@ page.tags=full screen,immersive,leanback
interrupted by accidental touches and swipes.
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/fullscreen_immersive_swipe_bottom.png" style="width:160px;float:right">
<img src="{@docRoot}design/media/fullscreen_immersive_swipe_top.png" style="width:160px">
</div>
diff --git a/docs/html/design/patterns/gestures.jd b/docs/html/design/patterns/gestures.jd
index ada0735..b471ee3 100644
--- a/docs/html/design/patterns/gestures.jd
+++ b/docs/html/design/patterns/gestures.jd
@@ -15,9 +15,9 @@ following table shows the core gesture set that is supported in Android.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
+<div class="cols">
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_touch.png">
<h4>Touch</h4>
<p>Triggers the default functionality for a given item.</p>
@@ -28,7 +28,7 @@ following table shows the core gesture set that is supported in Android.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_longtouch.png">
<h4>Long press</h4>
<p>Enters data selection mode. Allows you to select one or more items in a view and act upon
@@ -40,7 +40,7 @@ following table shows the core gesture set that is supported in Android.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_swipe.png">
<h4>Swipe or drag</h4>
<p>Scrolls overflowing content, or navigates between views in the same hierarchy. Swipes are
@@ -57,9 +57,9 @@ following table shows the core gesture set that is supported in Android.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
+<div class="cols">
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_drag.png">
<h4>Long press drag</h4>
<p>Rearranges data within a view, or moves data into a container (e.g. folders on Home Screen).</p>
@@ -70,7 +70,7 @@ following table shows the core gesture set that is supported in Android.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_doubletouch.png">
<h4>Double touch </h4>
<p> Scales up a standard amount around the target with each repeated gesture until reaching
@@ -84,7 +84,7 @@ following table shows the core gesture set that is supported in Android.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_doubletouchdrag.png">
<h4>Double touch drag</h4>
<p>Scales content by pushing away or pulling closer, centered around gesture.</p>
@@ -106,9 +106,9 @@ following table shows the core gesture set that is supported in Android.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
+<div class="cols">
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_pinchopen.png" style="margin-left:-4px">
<h4>Pinch open</h4>
<p>Zooms into content.</p>
@@ -119,7 +119,7 @@ following table shows the core gesture set that is supported in Android.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/gesture_pinchclose.png">
<h4>Pinch close</h4>
<p>Zooms out of content.</p>
diff --git a/docs/html/design/patterns/help.jd b/docs/html/design/patterns/help.jd
index 97949e2..6ef155a 100644
--- a/docs/html/design/patterns/help.jd
+++ b/docs/html/design/patterns/help.jd
@@ -21,8 +21,8 @@ page.tags=settings,preferences
<em>To teach high value functionality that's only available through a gesture.</em></p>
<p>For example, we use help content to teach users how to place apps on their Home screen. This functionality is:</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<ul>
<li><strong>High value</strong>
<p style="margin-top:0;">Without it, users wouldn't be able to customize the most frequently visited Android screen to meet their needs.</p></li>
@@ -31,7 +31,7 @@ page.tags=settings,preferences
</ul>
<p>However, not all high value gesture-only functionality needs a tutorial. For example, don't teach users how to scroll content. They already know how because it's a fundamental, system-wide interaction.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<img src="{@docRoot}design/media/help_cling.png">
<div class="figure-caption">
The first time each user visits the All Apps screen, a semi-transparent overlay appears to teach an important gesture.
@@ -44,11 +44,11 @@ page.tags=settings,preferences
<p>On every screen in your app, offer help in the <a href="{@docRoot}design/patterns/actionbar.html">action overflow</a>. Always make it the very last item in the menu and label it "Help".</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<img src="{@docRoot}design/media/help_overflow.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/help_solo_overflow.png">
<div class="figure-caption">
Even if your screen has no other action overflow items, "Help" should appear there and not be promoted to the action bar.
@@ -67,28 +67,28 @@ page.tags=settings,preferences
<p>When someone chooses "Help":</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/help_dont.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/help_better.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<img src="{@docRoot}design/media/help_evenbetter.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4 class="do-dont-label bad">Don't</h4>
<p>Present a dialog asking them to choose between help and other options.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4 class="do-dont-label good">Better</h4>
<p>Immediately launch a web browser with help content. Place other options in a footer.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4 class="do-dont-label good">Even Better</h4>
<p>Build a help screen in your app and offer other options in the action bar. For example, you could let users contact you with questions or feedback through an action button. The action overflow is the ideal place for non-help information that users rarely need.</p>
<p>This requires more development work than launching a web browser, but it's a nicer experience for users because they don't leave your app to get the help they need and doesn't require a network connection.</p>
diff --git a/docs/html/design/patterns/multi-pane-layouts.jd b/docs/html/design/patterns/multi-pane-layouts.jd
index dbe7d01..c9d3d84 100644
--- a/docs/html/design/patterns/multi-pane-layouts.jd
+++ b/docs/html/design/patterns/multi-pane-layouts.jd
@@ -51,13 +51,13 @@ relationship between the panels.</p>
one orientation, try not to split it up when the user rotates the screen. There are several techniques
you can use to adjust the layout after orientation change while keeping functional parity intact.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/multipane_stretch.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Stretch/compress</h4>
<p>Adjust the column width of your left pane to achieve a balanced layout in both orientations.</p>
@@ -65,13 +65,13 @@ you can use to adjust the layout after orientation change while keeping function
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/multipane_stack.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Stack</h4>
<p>Rearrange the panels on your screen to match the orientation.</p>
@@ -79,13 +79,13 @@ you can use to adjust the layout after orientation change while keeping function
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/multipane_expand.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Expand/collapse</h4>
<p>When the device rotates, collapse the left pane view to only show the most important information.</p>
@@ -93,13 +93,13 @@ you can use to adjust the layout after orientation change while keeping function
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/multipane_show.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Show/hide</h4>
<p>If your screen cannot accommodate the compound view on rotation show the right pane in full screen view on rotation to portrait. Use the Up icon in action bar to show the parent screen.</p>
diff --git a/docs/html/design/patterns/navigation-drawer.jd b/docs/html/design/patterns/navigation-drawer.jd
index dbac459..b359470 100644
--- a/docs/html/design/patterns/navigation-drawer.jd
+++ b/docs/html/design/patterns/navigation-drawer.jd
@@ -112,8 +112,8 @@ likely visit often and make those navigation hubs as well.</p>
screens as well as important lower-level screens.
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<p> To facilitate access to the navigation drawer on navigation hubs, all screens that
correspond to an entry in your navigation drawer should show the navigation drawer indicator
next to the application icon in the action bar. Touching the app icon causes the navigation
@@ -121,7 +121,7 @@ likely visit often and make those navigation hubs as well.</p>
<p> All other lower-level screens show the traditional Up indicator next to the application
icon. The drawer is still accessible with an edge-swipe, but is not featured in the action bar.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<img src="{@docRoot}design/media/navigation_drawer_indicator_big.png">
<div class="figure-caption">
App icon with navigation drawer indicator.
@@ -135,8 +135,8 @@ likely visit often and make those navigation hubs as well.</p>
<p> Keep the content of the navigation drawer focused on app navigation. Expose the navigation
hubs of your app as list items inside the navigation drawer - one item per row.
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<h4>Titles, icons, and counters</h4>
<p> You can structure navigation targets by adding titles. The titles are not interactive,
but just organize navigation targets into functional topics. If you have many navigation
@@ -144,7 +144,7 @@ hubs of your app as list items inside the navigation drawer - one item per row.
<p> Navigation targets can have optional leading icons as well as trailing counters. Use
the counters to inform users about a changed state of data in the corresponding view.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<img src="{@docRoot}design/media/navigation_drawer_titles_icons.png">
<div class="figure-caption">
Use titles and icons to organize your drawer.
@@ -152,15 +152,15 @@ hubs of your app as list items inside the navigation drawer - one item per row.
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/navigation_drawer_collapse.png">
<div class="figure-caption">
Collapsible navigation items are split. Use the left side for navigation and the right
to collapse and expand items.
</div>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Collapsible navigation items</h4>
<p>If you have many views with some subordinate to others, consider collapsing them into one
expandable item to conserve space.
@@ -201,27 +201,27 @@ is fully expanded:</p>
</div>
<h4>Actions</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/navigation_drawer_nav_and_actions.png">
<div class="figure-caption">
Keep actions on the right side of the action bar and in the overflow
</div>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<p> Don’t place actions in the navigation drawer. Actions belong in the action bar, and the
user expects to see them there. Keep in mind that not all applications use the navigation
drawer pattern. It may be tempting to expose all your app’s capabilities in a single place,
but keep the bigger picture in mind. Place your actions where all apps display them.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p> This also applies to common navigation targets, such as access to Help or the app’s
Settings. As per style guide convention Help and Settings are always located in the action
overflow.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/navigation_drawer_settings_help.png">
<div class="figure-caption">
Keep Help and Settings in the overflow.
diff --git a/docs/html/design/patterns/new.jd b/docs/html/design/patterns/new.jd
index 1523cea..47b05b2 100644
--- a/docs/html/design/patterns/new.jd
+++ b/docs/html/design/patterns/new.jd
@@ -1,5 +1,6 @@
page.title=New in Android
page.tags=KitKat,Android 4.4
+page.image=images/cards/design-new-in-android_2x.jpg
@jd:body
@@ -92,8 +93,8 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<h3>
Gestures
</h3>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>
The updated <a href="{@docRoot}design/patterns/gestures.html">Gestures</a>
page covers new and updated gestures introduced in Android KitKat:
@@ -101,7 +102,7 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
gestures are used for changing the viewing size of content.
</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/gesture_doubletouch.png">
<img src="{@docRoot}design/media/gesture_doubletouchdrag.png">
</div>
@@ -111,8 +112,8 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<h2>Android 4.1 Jelly Bean</h2>
<h4>Notifications</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<p>Notifications have received some notable enhancements in Android 4.1:</p>
<ul>
<li>Users can act on notifications immediately from the drawer</li>
@@ -126,7 +127,7 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
href="{@docRoot}design/patterns/notifications.html">Notifications</a> page for
more details.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/new_notifications.png">
</div>
</div>
@@ -134,8 +135,8 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<div class="vspace size-2">&nbsp;</div>
<h4>Resizable Application Widgets</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<p>Widgets are an essential aspect of home screen customization, allowing
"at-a-glance" views of an app's most important data and functionality right from
the user's home screen. Android 4.1 introduces improved App Widgets that can
@@ -152,7 +153,7 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
href="{@docRoot}design/patterns/widgets.html">Application Widgets</a> page has useful
details about widget types, limitations, and design considerations.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/new_widgets.png">
</div>
</div>
@@ -160,8 +161,8 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<div class="vspace size-2">&nbsp;</div>
<h4>Accessibility</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-11">
+<div class="cols">
+ <div class="col-11">
<p>One of Android's missions is to organize the world's information and
make it universally accessible and useful. Our mission applies to all
users-including people with disabilities such as visual impairment, color
@@ -183,7 +184,7 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<a href="{@docRoot}design/patterns/widgets.html">Widgets</a> page has
useful details about widget types, limitations, and design considerations.</p>
</div>
- <div class="layout-content-col span-2">
+ <div class="col-2">
<img src="{@docRoot}design/media/new_accessibility.png">
</div>
</div>
@@ -191,8 +192,8 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<h2>Android 4.0 Ice Cream Sandwich</h2>
<h4>Navigation bar</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<p>Android 4.0 removes the need for traditional hardware keys on
phones by replacing them with a virtual navigation bar that houses
the Back, Home and Recents buttons. Read the
@@ -200,7 +201,7 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
pattern to learn how the OS adapts to phones with hardware buttons and
how pre-Android 3.0 apps that rely on menu keys are supported.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/whats_new_nav_bar.png">
</div>
</div>
@@ -208,13 +209,13 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<div class="vspace size-2">&nbsp;</div>
<h4>Action bar</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<p>The action bar is the most important structural element of an Android
app. It provides consistent navigation across the platform and allows your
app to surface actions.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/whats_new_action_bar.png">
</div>
</div>
@@ -222,14 +223,14 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<div class="vspace size-2">&nbsp;</div>
<h4>Multi-pane layouts</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<p>Creating apps that scale well across different form factors and screen
sizes is important in the Android world. Multi-pane layouts allow you to
combine different activities that show separately on smaller devices into
richer compound views for tablets.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/whats_new_multipanel.png">
</div>
</div>
@@ -238,13 +239,13 @@ lockscreen, priority notifications, and cloud-synced notifications.</p>
<h4>Selection</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<p>The long press gesture which was traditionally used to show contextual
actions for objects is now used for data selection. When selecting data,
contextual action bars allow you to surface actions.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/whats_new_multiselect.png">
</div>
</div>
diff --git a/docs/html/design/patterns/notifications_k.jd b/docs/html/design/patterns/notifications_k.jd
index c8ef50b..01a12a7 100644
--- a/docs/html/design/patterns/notifications_k.jd
+++ b/docs/html/design/patterns/notifications_k.jd
@@ -22,8 +22,8 @@ paying attention.</p>
<h2>Anatomy of a notification</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Base Layout</h4>
<p>At a minimum, all notifications consist of a base layout, including:</p>
<ul>
@@ -34,7 +34,7 @@ paying attention.</p>
image is shown for the main icon</li>
</ul>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/notifications_pattern_anatomy.png">
<div class="figure-caption">
Base layout of a notification
@@ -54,8 +54,8 @@ for you to re-use in your application.</p>
<img src="{@docRoot}design/media/notifications_pattern_expandable.png">
<h4>Actions</h4>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>Android supports optional actions that are displayed at the bottom of
the notification. With actions, users can handle the most common tasks for a
particular notification from within the notification shade without having to
@@ -80,7 +80,7 @@ displaying</li>
or "Open")</li>
</ul>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/notifications_pattern_two_actions.png">
<div class="figure-caption">
Calendar reminder notification with two actions
@@ -96,11 +96,11 @@ otherwise hidden, you must make sure that any action a user can invoke from a
notification is available from within the associated application as well.</p>
<h2>Design guidelines</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/notifications_pattern_personal.png">
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<h4>Make it personal</h4>
<p>For notifications of items sent by another user (such as a message or
status update), include that person's image.</p>
@@ -264,8 +264,8 @@ other people.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h4>When not to display a notification</h4>
<p>There are however many other cases where notifications should not be
@@ -312,20 +312,20 @@ develop a widget that they can choose to place on their home screen.</p>
</ul>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/notifications_pattern_social_fail.png">
</div>
</div>
<h2 id="interacting-with-notifications">Interacting With Notifications</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/notifications_pattern_phone_icons.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<p>Notifications are indicated by icons in the notification area and can be
accessed by opening the notification drawer.</p>
@@ -337,8 +337,8 @@ removes it from the drawer.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p><h4>Ongoing notifications</h4>
<p>Ongoing notifications keep users informed about an ongoing process in the
@@ -349,15 +349,15 @@ downloading a file, or encoding a video. Ongoing notifications cannot be
manually removed from the notification drawer.</p></p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/notifications_pattern_ongoing_music.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-12">
+<div class="cols">
+ <div class="col-12">
<h4>Dialogs and toasts are for feedback not notification</h4>
<p>Your app should not create a dialog or toast if it is not currently on
screen. Dialogs and Toasts should only be displayed as the immediate response
diff --git a/docs/html/design/patterns/pure-android.jd b/docs/html/design/patterns/pure-android.jd
index a0f672e..e617711 100644
--- a/docs/html/design/patterns/pure-android.jd
+++ b/docs/html/design/patterns/pure-android.jd
@@ -1,4 +1,5 @@
page.title=Pure Android
+page.image=images/cards/design-pure-android_2x.png
@jd:body
<p>Most developers want to distribute their apps on multiple platforms. As you plan your app for
@@ -10,8 +11,8 @@ guidelines to avoid the most common traps and pitfalls.</p>
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Don't mimic UI elements from other platforms</h4>
<p>Platforms typically provide a carefully designed set of UI elements that are themed in a very
@@ -28,7 +29,7 @@ elements, customize carefully according to your specific branding - and not acco
conventions of a different platform.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/migrating_ui_elements.png">
<div class="figure-caption">
@@ -40,8 +41,8 @@ conventions of a different platform.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Don't carry over platform-specific icons</h4>
<p>Platforms typically provide sets of icons for common functionality, such as sharing, creating a new
@@ -52,7 +53,7 @@ counterparts.</p>
<a href="{@docRoot}design/downloads/index.html">Downloads</a> page.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/migrating_icons.png">
<div class="figure-caption">
@@ -64,8 +65,8 @@ counterparts.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Don't use bottom tab bars</h4>
<p>Other platforms use the bottom tab bar to switch between the app's views. Per platform convention,
@@ -77,7 +78,7 @@ platform and to avoid confusion between actions and view switching on Android.</
<a href="{@docRoot}design/patterns/actionbar.html">Action Bars</a>.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/migrating_ios_dialers.png">
<div class="figure-caption">
@@ -87,8 +88,8 @@ platform and to avoid confusion between actions and view switching on Android.</
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Don't hardcode links to other apps</h4>
<p>In some cases you might want your app to take advantage of another app's feature set. For
@@ -101,7 +102,7 @@ Action Provider</em> in your action bar to provide faster access to the user's m
sharing target.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/migrating_intents.png">
<div class="figure-caption">
@@ -114,8 +115,8 @@ sharing target.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Don't use labeled back buttons on action bars</h4>
<p>Other platforms use an explicit back button with label to allow the user to navigate up the
@@ -125,7 +126,7 @@ please review the <a href="{@docRoot}design/patterns/navigation.html">Navigation
<p>Follow this guideline to provide a consistent navigation experience across the platform.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/migrating_ios_galleries.png">
<div class="figure-caption">
@@ -135,8 +136,8 @@ please review the <a href="{@docRoot}design/patterns/navigation.html">Navigation
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<h4>Don't use right-pointing carets on line items</h4>
<p>A common pattern on other platforms is the display of right-pointing carets on line items that allow
@@ -145,7 +146,7 @@ the user to drill deeper into additional content.</p>
the platform and in order to not have the user guess as to what the meaning of those carets may be.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/migrating_ios_settings.png">
<div class="figure-caption">
diff --git a/docs/html/design/patterns/selection.jd b/docs/html/design/patterns/selection.jd
index 7ed6dcc..e00f726 100644
--- a/docs/html/design/patterns/selection.jd
+++ b/docs/html/design/patterns/selection.jd
@@ -23,8 +23,8 @@ handle multi-select and contextual actions in your apps.</p>
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>What has changed?</h4>
<p>In previous versions of Android, the long press gesture was universally used to display contextual
@@ -34,7 +34,7 @@ contextual actions and selection management functions for selected data into a n
the contextual action bar (CAB).</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/selection_context_menu.png">
<div class="figure-caption">
@@ -52,8 +52,8 @@ is selected. It appears after the user long-presses on a selectable data item.</
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>From here the user can:</p>
<ul>
@@ -65,15 +65,15 @@ is selected. It appears after the user long-presses on a selectable data item.</
</ul>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/selection_cab_example.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Selecting CAB actions</h4>
<p>You can decide which actions and elements appear in the CAB. Use the guidelines in the <a href="actionbar.html">Action Bar
@@ -85,7 +85,7 @@ the selection. Actions that apply to a single selected data item don't necessari
selected data items of the same kind.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/selection_adjusting_actions.png">
<div class="figure-caption">
diff --git a/docs/html/design/patterns/settings.jd b/docs/html/design/patterns/settings.jd
index a24d6c0..9ba837a 100644
--- a/docs/html/design/patterns/settings.jd
+++ b/docs/html/design/patterns/settings.jd
@@ -64,8 +64,8 @@ meets the bar:</p>
<div class="vspace size-3">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-5 with-callouts">
+<div class="cols">
+ <div class="col-5 with-callouts">
<h4 id="group-settings">If you still have lots of settings, group related settings together</h4>
@@ -89,7 +89,7 @@ to a subscreen of related settings. In addition, the items themselves are groupe
dividers.</p>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<img src="{@docRoot}design/media/settings_grouping.png">
@@ -101,26 +101,26 @@ on the total number of settings in your app.</p>
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-2">
+<div class="cols">
+ <div class="col-2">
<h4>7 or fewer</h4>
</div>
- <div class="layout-content-col span-11">
+ <div class="col-11">
<p>Don't group them at all. It won't benefit users and will seem like overkill.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-2">
+<div class="cols">
+ <div class="col-2">
<h4>8 to 10</h4>
</div>
- <div class="layout-content-col span-11">
+ <div class="col-11">
<p>Try grouping related settings under 1 or 2 section dividers. If you have any "singletons"
(settings that don't relate to any other settings and can't be grouped under your section
@@ -136,13 +136,13 @@ importance.</li>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-2">
+<div class="cols">
+ <div class="col-2">
<h4>11 to 15</h4>
</div>
- <div class="layout-content-col span-11">
+ <div class="col-11">
<p>Same advice as above, but try 2 to 4 section dividers.</p>
@@ -161,13 +161,13 @@ setting.</li>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-2">
+<div class="cols">
+ <div class="col-2">
<h4>16 or more</h4>
</div>
- <div class="layout-content-col span-11">
+ <div class="col-11">
<p>If you have any instances of 4 or more related settings, group them under a subscreen. Then use
the advice suggested above for the reduced list size.</p>
@@ -178,66 +178,66 @@ the advice suggested above for the reduced list size.</p>
<h2 id="patterns">Design Patterns</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Checkbox</h4>
<p>Use this pattern for a setting that is either selected or not selected.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_checkbox.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Multiple choice</h4>
<p>Use this pattern for a setting that needs to present a discrete set of options, from which the
user can choose only one.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_multiple_choice.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Slider</h4>
<p>Use this pattern for a setting where the range of values are not discrete and fall along a
continuum.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_slider.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Date/time</h4>
<p>Use this pattern for a setting that needs to collect a date and/or time from the user.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_date_time.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Subscreen navigation</h4>
<p>Use this pattern for navigating to a subscreen or sequence of subscreens that guide the user
@@ -250,15 +250,15 @@ first step in the sequence.</li>
</ul>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_subscreen_navigation.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>List subscreen</h4>
<p>Use this pattern for a setting or category of settings that contains a list of equivalent items.
@@ -268,15 +268,15 @@ example, status is reinforced with an icon to the right of the label.) Any actio
the list appear in the action bar rather than the list itself.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_list_subscreen.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Master on/off switch</h4>
<p>Use this pattern for a category of settings that need a mechanism for turning on or off as a
@@ -286,15 +286,15 @@ is turned off, the items in the list disappear, replaced by text that describes
empty. If any actions require the switch to be on, they become disabled.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_master_on_off.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<div class="vspace size-2">&nbsp;</div>
@@ -303,15 +303,15 @@ However, you should only do this in cases where users rarely need to access the
it's initially set up and more often just want to toggle the switch.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_master_on_off_2.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Individual on/off switch</h4>
<p>Use this pattern for an individual setting that requires a more elaborate description than can
@@ -323,15 +323,15 @@ reflect the current selection.</p>
does, we made the status more descriptive than just "On".</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_individual_on_off.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Dependency</h4>
<p>Use this pattern for a setting that changes availability based on the value of another setting.
@@ -344,7 +344,7 @@ master on/off switch so that your main settings screen isn't cluttered by lots o
</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<img src="{@docRoot}design/media/settings_dependency.png">
@@ -408,8 +408,8 @@ they'll fit everywhere.</p>
it or provide instructions. Starting in Ice Cream Sandwich, we're using secondary text for status.
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<div class="do-dont-label bad emulate-content-left-padding">Before</div>
@@ -431,7 +431,7 @@ it or provide instructions. Starting in Ice Cream Sandwich, we're using secondar
</table>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="do-dont-label good">After</div>
@@ -490,8 +490,8 @@ provide a description. Only include one if necessary.</p>
<p>The following are examples of changes we made to labels and secondary text in the Settings app
in Ice Cream Sandwich.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<div class="do-dont-label bad emulate-content-left-padding">Before</div>
@@ -506,7 +506,7 @@ in Ice Cream Sandwich.</p>
</table>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="do-dont-label good">After</div>
@@ -521,7 +521,7 @@ in Ice Cream Sandwich.</p>
</table>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<p>In this checkbox setting, we eliminated the throwaway word "Use" and rephrased the label to be
more direct and understandable.</p>
@@ -530,8 +530,8 @@ more direct and understandable.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<div class="do-dont-label bad emulate-content-left-padding">Before</div>
@@ -553,7 +553,7 @@ more direct and understandable.</p>
</table>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="do-dont-label good">After</div>
@@ -575,7 +575,7 @@ more direct and understandable.</p>
</table>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<p>In this multiple choice setting, we changed the label to a friendlier term and also replaced
the description with status. We put some descriptive words around the selected value, "10
@@ -584,8 +584,8 @@ minutes", because on its own, the meaning could be misinterpreted as "sleep for
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<div class="do-dont-label bad emulate-content-left-padding">Before</div>
@@ -607,7 +607,7 @@ minutes", because on its own, the meaning could be misinterpreted as "sleep for
</table>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="do-dont-label good">After</div>
@@ -629,7 +629,7 @@ minutes", because on its own, the meaning could be misinterpreted as "sleep for
</table>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<p>This setting navigates to a a sequence of subscreens that allow users to choose a type of
screen lock and then set it up. We eliminated the throwaway word "Change" in the label, and
@@ -639,8 +639,8 @@ hasn't set up a screen lock, the secondary text says "None".</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<div class="do-dont-label bad emulate-content-left-padding">Before</div>
@@ -662,7 +662,7 @@ hasn't set up a screen lock, the secondary text says "None".</p>
</table>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<div class="do-dont-label good">After</div>
@@ -684,7 +684,7 @@ hasn't set up a screen lock, the secondary text says "None".</p>
</table>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<p>In this checkbox setting&mdash;although it's technical jargon&mdash;we kept the "NFC" label
because: (1) we couldn't find a clear, concise alternative, and (2) user familiarity with the
diff --git a/docs/html/design/patterns/swipe-views.jd b/docs/html/design/patterns/swipe-views.jd
index af5c9dc..9ee33db 100644
--- a/docs/html/design/patterns/swipe-views.jd
+++ b/docs/html/design/patterns/swipe-views.jd
@@ -42,8 +42,8 @@ using the swipe gesture to navigate to the next/previous detail view.</p>
<h2 id="between-tabs">Swiping Between Tabs</h2>
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay>
@@ -58,7 +58,7 @@ using the swipe gesture to navigate to the next/previous detail view.</p>
</div>
</div>
- <div class="layout-content-col span-8">
+ <div class="col-8">
<p>If your app uses action bar tabs, use swipe to navigate between the different views.</p>
<div class="vspace size-1">&nbsp;</div>
diff --git a/docs/html/design/patterns/widgets.jd b/docs/html/design/patterns/widgets.jd
index 47acc7b..b149af6 100644
--- a/docs/html/design/patterns/widgets.jd
+++ b/docs/html/design/patterns/widgets.jd
@@ -21,18 +21,18 @@ page.metaDescription=Design guide to creating widgets that are easy to use and l
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h3>Collection widgets</h3>
<p>As the name implies, collection widgets specialize in displaying multitude elements of the same type, such as a collection of pictures from a gallery app, a collection of articles from a news app or a collection of emails/messages from a communication app. Collection widgets typically focus on two use cases: browsing the collection, and opening an element of the collection to its detail view for consumption. Collection widgets can scroll vertically.</p>
</div>
- <div class="layout-content-col span-3">
+ <div class="col-3">
<img src="{@docRoot}design/media/widgets_collection_gmail.png">
<div class="figure-caption">
ListView widget
</div>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/widgets_collection_bookmarks.png">
<div class="figure-caption">
GridView widget
@@ -84,8 +84,8 @@ A music player widget is primarily a control widget, but also keeps the user inf
<li>Open application at top level: Tapping on an information element will usually navigate the user to a lower level detail screen. Providing access to the top level of your application provides more navigation flexibility and can replace a dedicated app shortcut that users would otherwise use to navigate to the app from the home screen. Using your application icon as an affordance can also provide your widget with a clear identity in case the data you're displaying is ambiguous.</li>
</ul>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h3>Widget resizing</h3>
<p>With version 3.1, Android introduced resizable widgets to the platform. Resizing allows users to adjust the height and/or the width of a widget within the constraints of the home panel placement grid. You can decide if your widget is freely resizable or if it is constrained to horizontal or vertical size changes. You do not have to support resizing if your particular widget is inherently fixed-size.</p>
<p>Allowing users to resize widgets has important benefits:</p>
@@ -95,7 +95,7 @@ A music player widget is primarily a control widget, but also keeps the user inf
</ul>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/widgets_resizing01.png">
<div class="figure-caption">
A long press and subsequent release sets resizable widgets into resize mode. Users can use the drag handles or the widget corners to set the desired size.
@@ -116,14 +116,14 @@ A music player widget is primarily a control widget, but also keeps the user inf
</ul>
<h3>Widget configuration</h3>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>Sometimes widgets need to be setup before they can become useful. Think of an email widget for example, where you need to provide an account before the inbox can be displayed. Or a static photo widget where the user has to assign the picture that is to be displayed from the gallery.</p>
<p>Android widgets display their configuration choices right after the widget is dropped onto a home panel. Keep the widget configuration light and don't present more than 2-3 configuration elements. Use dialog-style instead of full-screen activities to present configuration choices and retain the user's context of place, even if doing so requires use of multiple dialogs.</p>
<p>Once setup, there typically is not a lot of reason to revisit the setup. Therefore Android widgets do not show a "Setup" or "Configuration" button.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/widgets_config.png">
<div class="figure-caption">
After adding a Play widget to a home panel, the widget asks the user to specify the type of media the widget should display.
diff --git a/docs/html/design/style/branding.jd b/docs/html/design/style/branding.jd
index b5bb77c..5995d03 100644
--- a/docs/html/design/style/branding.jd
+++ b/docs/html/design/style/branding.jd
@@ -23,15 +23,15 @@ everyone else's. In Android, your app can shine as an extension of your brand. <
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/branding_wallet.png" style="width:94%">
<div class="figure-caption">
The four colors of the Google Wallet logo provide a playful accent to the four dots
that appear as the user enters a PIN.
</div>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/branding_googlemusic.png" style="width:94%">
<div class="figure-caption">
The Google Play Music app has an orange theme color, which is used for emphasis
@@ -56,15 +56,15 @@ and app name in the action bar.</p>
<div class="vspace size-1">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6" style="padding-top:24px;">
+<div class="cols">
+ <div class="col-6" style="padding-top:24px;">
<img src="{@docRoot}design/media/branding_launcher_icon.png" style="width:60px;float:left;padding-right:1em;">
<div class="figure-caption" style="width:290px;margin-left:20px;">
Google+ reinforces its brand by carrying its launcher icon through to the action bar.
</div>
<img src="{@docRoot}design/media/branding_logo_icon_action_bar.png" style="width:320px;float:left;padding-right:1em;">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/yourbranding_app.png" style="width:320px;">
<div class="figure-caption" style="width:320px;">
Example of a the logo in the action bar. This works well in cases where the brand's logo matches the name of the app.
@@ -87,8 +87,8 @@ Android app as well. <strong>If you take this approach, make sure your brand sty
applied to every single icon in your app.</strong></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p>One exception: For any icon in your existing set where the symbol is different from
Android's, use Android's symbol but give it your brand's styling. That way, users will
understand what the purpose of the icon is based on what they've learned in other
@@ -99,20 +99,20 @@ applied to every single icon in your app.</strong></p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/yourbranding_in-app-icons.png" style="width:300px;margin:12px 48px 0 16px;">
</div>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<p><strong>Example</strong>:<br />
</p>
<p>The brand's normal icon for sharing on other platforms is a right arrow.
</div>
- <div class="layout-content-col span-6 lasyout-with-list-item-margins">
+ <div class="col-6 lasyout-with-list-item-margins">
<div style="margin-bottom:1em;">
<span class="do-dont-label bad" style="margin-left:12px">Don't</span>
diff --git a/docs/html/design/style/devices-displays.jd b/docs/html/design/style/devices-displays.jd
index 1590363..caa77da 100644
--- a/docs/html/design/style/devices-displays.jd
+++ b/docs/html/design/style/devices-displays.jd
@@ -19,15 +19,15 @@ gracefully scale from large tablets to smaller phones.</p>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Be flexible</h4>
<p>Stretch and compress your layouts to accommodate various heights and widths.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Optimize layouts</h4>
@@ -35,7 +35,7 @@ gracefully scale from large tablets to smaller phones.</p>
multiple views to reveal more content and ease navigation.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Assets for all</h4>
<p>Provide resources for different screen densities (<acronym title="Dots per inch">DPI</acronym>) to
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index e2cdf3f..8b6f3ab 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -53,26 +53,26 @@ effectively down-scales your HDPI assets by 1/2 to match the expected size.</p>
user can change the Home screen's wallpaper, make sure that your launcher icon is clearly visible on
any type of background.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_launcher_size.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_launcher_focal.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_launcher_style.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Sizes &amp; scale</h4>
@@ -84,7 +84,7 @@ any type of background.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Proportions</h4>
@@ -95,7 +95,7 @@ any type of background.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Style</h4>
<p>Use a distinct silhouette. Three-dimensional, front view, with a slight perspective as if viewed
@@ -105,11 +105,11 @@ from above, so that users perceive some depth.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
&nbsp;
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/iconography_launcher_example.png">
@@ -117,8 +117,8 @@ from above, so that users perceive some depth.</p>
<!-- 2 free columns -->
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-12">
+<div class="cols">
+ <div class="col-12">
<img src="{@docRoot}design/media/iconography_launcher_example2.png">
@@ -160,26 +160,26 @@ files for further customization.
href="{@docRoot}downloads/design/Android_Design_Icons_20131106.zip">Download the Action Bar Icon Pack</a>
</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_actionbar_size.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_actionbar_focal.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_actionbar_style.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Sizes &amp; scale</h4>
@@ -189,7 +189,7 @@ files for further customization.
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Focal area &amp; proportions</h4>
@@ -201,7 +201,7 @@ files for further customization.
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Style</h4>
<p>Pictographic, flat, not too detailed, with smooth curves or sharp shapes. If the graphic is thin,
@@ -212,8 +212,8 @@ spaces should be a minimum of 2 dp.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Colors</h4>
<p>Colors: <strong>#333333</strong><br />
@@ -226,7 +226,7 @@ Enabled: <strong>80%</strong> opacity<br />
Disabled: <strong>30%</strong> opacity</p>
</div>
- <div class="layout-content-col span-9">
+ <div class="col-9">
<img src="{@docRoot}design/media/iconography_actionbar_colors.png">
@@ -249,26 +249,26 @@ items. For example, in the Gmail app, each message has a star icon that marks th
important.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_small_size.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_small_focal.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_small_style.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Sizes &amp; scale</h4>
@@ -278,7 +278,7 @@ important.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Focal area &amp; proportions</h4>
@@ -290,7 +290,7 @@ important.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Style</h4>
<p>Neutral, flat, and simple. Filled shapes are easier to see than thin strokes. Use a single visual
@@ -300,8 +300,8 @@ metaphor so that a user can easily recognize and understand its purpose.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_small_colors.png">
@@ -313,7 +313,7 @@ to indicate a bookmarked message. If an icon is actionable, choose a color that
the background.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/iconography_small_example.png">
@@ -337,26 +337,26 @@ the background.</p>
whenever a new notification is available.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_notification_size.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_notification_focal.png">
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<img src="{@docRoot}design/media/iconography_notification_style.png">
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Sizes &amp; scale</h4>
@@ -366,7 +366,7 @@ whenever a new notification is available.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Focal area &amp; proportions</h4>
@@ -378,7 +378,7 @@ whenever a new notification is available.</p>
</ul>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Style</h4>
<p>Keep the style flat and simple, using the same single, visual metaphor as your launcher icon.</p>
@@ -387,14 +387,14 @@ whenever a new notification is available.</p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-4">
+<div class="cols">
+ <div class="col-4">
<h4>Colors</h4>
<p>Notification icons must be entirely white. Also, the system may scale down and/or darken the icons.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/iconography_notification_example.png">
diff --git a/docs/html/design/style/metrics-grids.jd b/docs/html/design/style/metrics-grids.jd
index d7b5f78..97915b8 100644
--- a/docs/html/design/style/metrics-grids.jd
+++ b/docs/html/design/style/metrics-grids.jd
@@ -40,13 +40,13 @@ refer to layout dimensions with <acronym title="Density-independent pixels: One
on a 160 dpi (mdpi) screen.">dp</acronym> measurements instead of pixels.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/metrics_diagram.png">
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<h4>Space considerations</h4>
<p>Devices vary in the amount of density-independent pixels (dp) they can display.</p>
diff --git a/docs/html/design/style/themes.jd b/docs/html/design/style/themes.jd
index 3313a2b..6c8169b 100644
--- a/docs/html/design/style/themes.jd
+++ b/docs/html/design/style/themes.jd
@@ -1,8 +1,8 @@
page.title=Themes
@jd:body
-<div class="layout-content-row">
- <div class="layout-content-col span-5">
+<div class="cols">
+ <div class="col-5">
<img src="{@docRoot}design/media/themes_holo_light.png">
<div class="figure-caption">
@@ -15,7 +15,7 @@ page.title=Themes
</div>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<a class="notice-designers-material"
diff --git a/docs/html/design/style/touch-feedback.jd b/docs/html/design/style/touch-feedback.jd
index b6d6407..e1fac2f 100644
--- a/docs/html/design/style/touch-feedback.jd
+++ b/docs/html/design/style/touch-feedback.jd
@@ -2,8 +2,8 @@ page.title=Touch Feedback
page.tags=input,button
@jd:body
-<div class="layout-content-row" style="margin-bottom: -100px">
-<div class="layout-content-col span-7">
+<div class="cols" style="margin-bottom: -100px">
+<div class="col-7">
<a class="notice-designers-material"
href="http://www.google.com/design/spec/animation/responsive-interaction.html">
@@ -31,7 +31,7 @@ easier because the default touch feedback works with whatever hue you choose.</l
</div>
-<div class="layout-content-col span-6" style="float:right;">
+<div class="col-6" style="float:right;">
<video class="play-on-hover" width="268" height="442" autoplay style="border:1px solid #ddd;background-color:#f9f9f9;" poster="">
<source src="{@docRoot}design/media/touch_feedback.mp4" type="video/mp4">
<source src="{@docRoot}design/media/touch_feedback.webm" type="video/webm">
@@ -55,8 +55,8 @@ easier because the default touch feedback works with whatever hue you choose.</l
<div class="vspace size-3">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Communication</h4>
<p>When your objects react to more complex gestures, help users
@@ -66,7 +66,7 @@ understand what the outcome will be.</p>
begins to dim. This helps the user understand that swiping will cause the
item to be removed.</p>
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<img src="{@docRoot}design/media/touch_feedback_manipulation.png">
@@ -74,8 +74,8 @@ item to be removed.</p>
</div>
<div class="vspace size-3">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/touch_feedback_communication.png">
<p><em>If a user attempts to scroll past the last home screen panel, the screen
@@ -83,7 +83,7 @@ item to be removed.</p>
isn’t possible.</em></p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Boundaries</h4>
<p>
diff --git a/docs/html/design/style/typography.jd b/docs/html/design/style/typography.jd
index 2f8e91b..af76c40 100644
--- a/docs/html/design/style/typography.jd
+++ b/docs/html/design/style/typography.jd
@@ -3,8 +3,8 @@ page.tags="textview","font"
page.metaDescription=How to use typography in your Android apps.
@jd:body
-<div class="layout-content-row">
- <div class="layout-content-col span-8">
+<div class="cols">
+ <div class="col-8">
<img src="{@docRoot}design/media/typography_main.png">
@@ -19,7 +19,7 @@ page.metaDescription=How to use typography in your Android apps.
</div>
</a>
-<div class="layout-content-col span-5">
+<div class="col-5">
<p>
<a class="download-button" onClick="ga('send', 'event', 'Design', 'Download', 'Roboto ZIP');"
@@ -48,8 +48,8 @@ variant in regular and bold weights, along with an italic style for each weight.
<hr>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>Default type colors</h4>
<p>The Android UI uses the following default color styles: <code>textColorPrimary</code> and
@@ -60,7 +60,7 @@ touch feedback states when used inside UI elements.</p>
<img src="{@docRoot}design/media/typography_defaults.png">
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>Typographic Scale</h4>
<p>Contrast in type sizes can go a long way to create ordered, understandable layouts. However, too
diff --git a/docs/html/design/style/writing.jd b/docs/html/design/style/writing.jd
index 4f62253..0c62a55 100644
--- a/docs/html/design/style/writing.jd
+++ b/docs/html/design/style/writing.jd
@@ -16,8 +16,8 @@ page.tags=dialog,toast,notification
<p><em>Avoid wordy, stilted text</em></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6 layout-with-list-item-margins">
+<div class="cols">
+ <div class="col-6 layout-with-list-item-margins">
<div class="do-dont-label bad">Don't</div>
@@ -26,7 +26,7 @@ page.tags=dialog,toast,notification
</td></tr></tbody></table>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<div class="do-dont-label good">Do</div>
@@ -39,8 +39,8 @@ page.tags=dialog,toast,notification
<p><em>Don't provide unnecessary information</em></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6 layout-with-list-item-margins">
+<div class="cols">
+ <div class="col-6 layout-with-list-item-margins">
<div class="do-dont-label bad">From a Setup Wizard screen</div>
@@ -64,7 +64,7 @@ page.tags=dialog,toast,notification
</table>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<div class="do-dont-label good">From a Setup Wizard screen</div>
@@ -100,8 +100,8 @@ page.tags=dialog,toast,notification
<p><em>Focus on the user's concern, not technical details</em></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6 layout-with-list-item-margins">
+<div class="cols">
+ <div class="col-6 layout-with-list-item-margins">
<div class="do-dont-label bad">Don't</div>
@@ -110,7 +110,7 @@ page.tags=dialog,toast,notification
</td></tr></tbody></table>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<div class="do-dont-label good">Do</div>
@@ -123,8 +123,8 @@ page.tags=dialog,toast,notification
<p><em>Put top news first</em></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6 layout-with-list-item-margins">
+<div class="cols">
+ <div class="col-6 layout-with-list-item-margins">
<div class="do-dont-label bad">Don't</div>
@@ -133,7 +133,7 @@ page.tags=dialog,toast,notification
</td></tr></tbody></table>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<div class="do-dont-label good">Do</div>
@@ -146,8 +146,8 @@ page.tags=dialog,toast,notification
<p><em>Put the user's goal first</em></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6 layout-with-list-item-margins">
+<div class="cols">
+ <div class="col-6 layout-with-list-item-margins">
<div class="do-dont-label bad">Don't</div>
@@ -156,7 +156,7 @@ page.tags=dialog,toast,notification
</td></tr></tbody></table>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<div class="do-dont-label good">Do</div>
@@ -178,8 +178,8 @@ page.tags=dialog,toast,notification
</ul>
<p><em>Avoid being confusing or annoying</em></p>
-<div class="layout-content-row">
- <div class="layout-content-col span-6 layout-with-list-item-margins">
+<div class="cols">
+ <div class="col-6 layout-with-list-item-margins">
<div class="do-dont-label bad">Don't</div>
<table class="ui-table bad">
<thead>
@@ -200,7 +200,7 @@ page.tags=dialog,toast,notification
</table>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<div class="do-dont-label good">Do</div>
<table class="ui-table good">
<thead>
diff --git a/docs/html/design/tv/patterns.jd b/docs/html/design/tv/patterns.jd
index e786ee5..ccec285 100644
--- a/docs/html/design/tv/patterns.jd
+++ b/docs/html/design/tv/patterns.jd
@@ -43,8 +43,8 @@ Your application provides these recommendations, as described in <a href="{@docR
</a>. For a visual overview of recommendations, see <a href="design/tv/index.html#recommendations">
Design for Android TV</a>.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-8 with-callouts">
+<div class="cols">
+ <div class="col-8 with-callouts">
<p>The design elements of the recommendation card are as follows:</p>
<ol>
@@ -61,7 +61,7 @@ Design for Android TV</a>.</p>
Recommendations</a> for more information.</p>
</div>
- <div class="layout-content-col span-5">
+ <div class="col-5">
<img src="{@docRoot}images/tv/recommend-card.png">
diff --git a/docs/html/design/videos/index.jd b/docs/html/design/videos/index.jd
index 976767d..3845b44 100644
--- a/docs/html/design/videos/index.jd
+++ b/docs/html/design/videos/index.jd
@@ -7,60 +7,60 @@ page.title=Videos
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326368573">Enchant, Simplify, Amaze: Android's Design Principles</a></h3>
<p>Want to enchant people, simplify their lives, and make them feel amazing with your app? Learn how Android's Design Principles can help you create products that resonate with people. Find out about the meaning and research behind the principles. See real-world examples and practices from the Android Design team. Discover techniques for applying the principles in your daily work. No design experience necessary.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/s0HIP8EdlnE" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326301704">Structure in Android App Design</a></h3>
<p>Life is simple when your app is simple. But when your apps gets more complex, how do you choose between spinners, tabs, and drawers for navigation? Members of the Android Design team look at techniques for making your app predictable and pleasing to use.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/XpqyiBR0lJ4" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326425499">Fireside Chat with the Android Team</a></h3>
<p>Pull up a chair and join the Android platform team for a fireside chat. It's your opportunity to ask us about the platform and learn a little bit more about why things work the way they do, from the people who built it. </p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/A5OOJDIrYls" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326483138">Agile UX Research Practice in Android</a></h3>
<p>In the Android UX team, it is critical to get user feedback frequently and consistently so that we are able to iterate and develop the best-in-class designs for our users. We will discuss how the team applied "Pulse Studies" (iterative research sessions) in order to put new ideas, designs, and concepts in front of users on a regular basis; it requires minimal advance planning, it can have an immediate product impact, and it can meet urgent needs. </p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/6MOeVNbh9cY" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326460111">Cognitive Science and Design</a></h3>
<p>This session will provide an in-depth look at human perception and cognition, and its implications for interactive and visual design. The human brain is purely treated as an information processing machine, and we will teach the audience its attributes, its advantages, its limitations, and generally how to hack it. </p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/z2exxj4COhU" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
@@ -69,60 +69,60 @@ page.title=Videos
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-success"><a href="https://developers.google.com/events/io/sessions/gooio2012/112/">Android Design for Success</a></h3>
<p>You have a great idea for an Android app. You want it to stand out among hundreds of thousands. You want your users to love it and tell everyone they know. The Android User Experience team is here to help. We talk about the Android Design guide and other tricks of the trade for creating apps that delight users and help them accomplish their goals. No design background is required.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/2NL_83EG0no" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="design-for-engineers"><a href="https://developers.google.com/events/io/sessions/gooio2012/1204/">Android Design for Engineers</a></h3>
<p>Design isn't black magic, it's a field that people can learn. In this talk two elite designers from Google give you an advanced crash course in interactive and visual design. Topics include mental models, natural mappings, metaphors, mode errors, visual hierarchies, typography and gestalt principles. Correctly applied, this knowledge can drastically improve the quality of your work.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/iJDoxOTyMdk" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="navigation-in-android"><a href="https://developers.google.com/events/io/sessions/gooio2012/114/">Navigation in Android</a></h3>
<p>An app is useless if people can't find their way around it. Android introduced big navigation-support changes in 3.0 and 4.0. The Action Bar offers a convenient control for Up navigation, the Back key's behavior became more consistent within tasks, and the Recent Tasks UI got an overhaul. In this talk, we discuss how and why we got where we are today, how to think about navigation when designing your app's user experience, and how to write apps that offer effortless navigation in multiple Android versions.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/XwGHJJYBs0Q" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="now-what"><a href="https://developers.google.com/events/io/sessions/gooio2012/115/">So You've Read the Design Guide&#59; Now What?</a></h3>
<p>The Android Design Guide describes how to design beautiful Android apps, but not how to build them. In this talk we give practical tips for how to apply fit &amp; finish as you implement your design, we show you how to avoid some common pitfalls, we describe some useful patterns, and show how tools can help.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/2jCVmfCse1E" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-7">
+<div class="cols">
+ <div class="col-7">
<h3 id="playing-with-patterns"><a href="https://developers.google.com/events/io/sessions/gooio2012/131/">Playing with Patterns</a></h3>
<p>Best-in-class application designers and developers talk about their experience in developing for Android, showing screenshots from their app, exploring the challenges they faced, and offering creative solutions congruent with the Android Design guide. Guests are invited to show examples of visual and interaction patterns in their application that manage to keep it simultaneously consistent and personal.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<iframe width="355" height="200" src="//www.youtube.com/embed/8iUbr8RZKtg" frameborder="0" allowfullscreen=""></iframe>
</div>
</div>
diff --git a/docs/html/design/wear/creative-vision.jd b/docs/html/design/wear/creative-vision.jd
index a879cf9..0955240 100644
--- a/docs/html/design/wear/creative-vision.jd
+++ b/docs/html/design/wear/creative-vision.jd
@@ -2,17 +2,19 @@ page.title=Creative Vision for Android Wear
@jd:body
<style>
-div.span-13 {
- margin:10px 0;
+.page-vision {
+ float: left;
+ margin: 10px 0;
+ width: 100%;
}
-div.span-13 img {
+.page-vision img {
float:left;
margin:2px 20px 40px 0;
}
-div.span-13 p {
+.page-vision p {
margin-left:167px;
}
-div.span-13 h2 {
+.page-vision h2 {
margin-top:0;
}
</style>
@@ -22,28 +24,28 @@ allowing users to be more connected to both the virtual world and the real world
Wear experiences are:</p>
- <div class="layout-content-col span-13">
+ <div class="page-vision">
<img src="{@docRoot}design/media/wear/vision_traffic.png" width="147" height="147" />
<h2 id="Launched">Launched automatically</h2>
<p>Most people are used to launching apps by clicking an icon. Android Wear is different. Wearable apps are aware of the user’s context - time, location, physical activity, and so on. The apps use this information to insert cards into the stream when they become relevant. This makes Android Wear timely, relevant and very specific.</p>
</div>
- <div class="layout-content-col span-13">
+ <div class="page-vision">
<img src="{@docRoot}design/media/wear/vision_navigation.png" width="147" height="147" />
<h2 id="Glanceable">Glanceable</h2>
<p>A classic wrist watch is designed to let you see the time in a split second and get on with what you were doing. Designing for Android Wear is no different. The less time it takes to use your software, the more time the user can be present in whatever they are doing. Android wear is fast, sharp, and immediate.</p>
</div>
- <div class="layout-content-col span-13">
+ <div class="page-vision">
<img src="{@docRoot}design/media/wear/vision_voice.png" width="147" height="147" style="border: 1px solid #ddd;" />
<h2 id="SuggestDemand">All about suggest and demand</h2>
<p>Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. Android Wear is helpful, respectful, and responsive.</p>
</div>
- <div class="layout-content-col span-13">
+ <div class="page-vision">
<img src="{@docRoot}design/media/wear/vision_music.png" width="147" height="147" />
<h2 id="Interaction">Zero or low interaction</h2>
diff --git a/docs/html/design/wear/style.jd b/docs/html/design/wear/style.jd
index abd3a9a..bb559fe 100644
--- a/docs/html/design/wear/style.jd
+++ b/docs/html/design/wear/style.jd
@@ -21,26 +21,26 @@ href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary"><code>WatchViewS
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<img src="{@docRoot}design/media/wear/assets_specifics.png" width="300"
style="margin:32px 0 20px;">
</div>
- <div class="layout-content-col span-7">
+ <div class="col-7">
<h2 id="Assets" style="clear:both">Specific Assets Required</h2>
<p>A core set of standard assets may need to be provided depending on your card design: app icon, background image or images, action icons, and action confirmation animations. Of course, your specific design may necessitate other assets. Background images should be provided in landscape format at least 600px width for notifications that include pages of cards, since the system automatically adds a parallaxing effect.</p>
</div>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h2 id="PeekCard" style="clear:both">Peek Card Readability</h2>
<p>Test your card layout to ensure that useful information is conveyed in the peek state on the Home screen. The main message of the card should be readable in the peek state, particularly for contextual cards. Content that requires an interaction to be read, for example a long message, should be cropped appropriately to provide an affordance to the user to swipe the card to read more.</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="{@docRoot}design/media/wear/peek-card.png" width="300"
style="margin:12px 0 0 20px">
diff --git a/docs/html/design/wear/watchfaces.jd b/docs/html/design/wear/watchfaces.jd
index 2a00802..2def05b 100644
--- a/docs/html/design/wear/watchfaces.jd
+++ b/docs/html/design/wear/watchfaces.jd
@@ -55,42 +55,42 @@ format.</p>
<p>These guidelines help your concepts align across devices:</p>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-6">
+<div class="cols" style="margin-top:20px">
+<div class="col-6">
<h3>Create flexible concepts</h3>
<p>Ideally, the visual functionality of the watch face works for both round and square
formats. In this example, the visual functionality of the watch face is flexible enough
to work well in either format without any adjustment. However, other design concepts require
different executions for square and round screens.</p>
</div>
-<div class="layout-content-col span-7">
+<div class="col-7">
<img src="{@docRoot}design/media/wear/ScreenShapes_Invert.png" width="400"
height="221" alt="" style="margin-top:-30px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-6">
+<div class="cols" style="margin-top:20px">
+<div class="col-6">
<h3>Use a common design language</h3>
<p>Try using a common set of colors, line weights, shading, and other design elements
to draw a visual connection between your square and round versions. By using similar color
palettes and a few consistent visual elements, the overall appearance of square and round
can be appropriately customized while still feeling like part of the same visual system.</p>
</div>
-<div class="layout-content-col span-7">
+<div class="col-7">
<img src="{@docRoot}design/media/wear/ScreenShapes_Pyramids.png" width="400"
height="221" alt="" style="margin-top:-30px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-6">
+<div class="cols" style="margin-top:20px">
+<div class="col-6">
<h3>Adjust for analog concepts</h3>
<p>Some of your concepts will naturally take the shape of an analog clock, like a center
dial with hour and minute hands. In this case, consider the corner areas that are exposed
when translating to a square format. Try extending and exploring this extra space.</p>
</div>
-<div class="layout-content-col span-7">
+<div class="col-7">
<img src="{@docRoot}design/media/wear/ScreenShapes_Rift.png" width="400"
height="221" alt="" style="margin-top:-30px">
</div>
@@ -137,8 +137,8 @@ You can configure your watch face to display different ambient designs depending
of screen available on the device. Consider the best design for your watch faces on all
screens.</p>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>Reduced color space</h3>
<p>Some displays use a reduced color space in ambient mode to save power.</p>
<p>One reduced color space power saving method is to use a "low-bit" mode. In low-bit mode,
@@ -152,14 +152,14 @@ screens.</p>
displays which do not use color in ambient mode, the background may be either black or
white.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Render_LowBit.png" width="200"
height="" alt="" style="margin-top:45px;margin-left:13px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>Burn protection techniques</h3>
<p>When designing for OLED screens, you should consider power efficiency and the screen
burn-in effect. When these screens are in ambient mode, the system shifts the contents of
@@ -169,7 +169,7 @@ screens.</p>
replace filled images with pixel patterns. For analog watch face designs, hollow out the center
where the hands meet to avoid pixel burn-in in this mode.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Render_1Bit.png" width="200"
height="" alt="" style="margin-top:-10px;margin-left:13px">
</div>
@@ -183,8 +183,8 @@ screens.</p>
user the status of the wearable and show notifications from services on the user's phone. Try
to keep critical elements in your watch face designs from being obscured by the UI elements.</p>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>Cards</h3>
<p>Cards are the notification system that bridges information between the wearable and a
mobile device. Cards are also how most applications communicate with users. The user will be
@@ -202,14 +202,14 @@ the bottom half of the face should leverage the small peek card instead.</p>
<p>The system notifies your watch face when the bounds of a peek card change, so you can
rearrange the elements in your design if necessary.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/CardsRender_Build.png" width="200"
height="" alt="" style="margin-top:20px;margin-left:13px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>Indicators</h3>
<p>Indicators tell the user the status of the wearable, such as charging and airplane mode.
When designing a watch face, consider how the indicator will fall over the watch face.</p>
@@ -219,14 +219,14 @@ position the status icons or the hotword on the bottom of the screen, the system
peek cards. If the edge of the watch face contains strong visual elements, such as
ticks or numbers, place the indicators on the center of the screen.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Indicators_Cropped.png" width="200"
height="" alt="" style="margin-top:0px;margin-left:13px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>The hotword</h3>
<p>The hotword is the phrase "OK Google", which tells the user that they can interact with
the watch using voice commands. When a user turns on the wearable, the hotword appears on
@@ -237,7 +237,7 @@ watch face. Finally, background protection for the hotword and the indicators sh
turned on unless your design is tailored to have these elements appear on top of them, for example
using dark solid colors with no patterns.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Hotword_Cropped.png" width="200"
height="" alt="" style="margin-top:0px;margin-left:13px">
</div>
@@ -253,8 +253,8 @@ using dark solid colors with no patterns.</p>
<p>Your watch face can show users contextually relevant data and react to it by changing styles
and colors in your design.</p>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>What do you want your user to know?</h3>
<p>The first step in designing a data-integrated watch face is to define a conceptual user
outcome based on available data. First, generate a strong concept or outcome you believe is
@@ -262,14 +262,14 @@ supported by real user needs. What do you want your users to know after they hav
at your design? Once you have identified your outcome, you need to determine how to obtain
the required data.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Render_Saturn.png" width="200"
height="" alt="" style="margin-top:-10px;margin-left:13px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>A watch dial is a timeline; add data to it</h3>
<p>Your watch face concept may include use of data beyond time, such as weather, calendar
and fitness data. Consider the inclusion of data integration creatively. Avoid simply
@@ -279,14 +279,14 @@ watch face as a clock with an indication of the current temperature in degrees o
you might design a watch face that describes how the temperature will change over the
course of the day.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Render_Episode.png" width="200"
height="" alt="" style="margin-top:-10px;margin-left:13px">
</div>
</div>
-<div class="layout-content-row" style="margin-top:20px">
-<div class="layout-content-col span-9">
+<div class="cols" style="margin-top:20px">
+<div class="col-9">
<h3>Stick to one message</h3>
<p>Once you have solidified your conceptual direction or desired outcome, you will need to
begin visualizing your watch face. The strongest watch face designs are highly glanceable
@@ -296,7 +296,7 @@ an entire month of calendar events, you might decide to display only the next
upcoming event. By a process of reduction, you should arrive at a powerful singular
expression of data to include in your design.</p>
</div>
-<div class="layout-content-col span-4">
+<div class="col-4">
<img src="{@docRoot}design/media/wear/Render_Albumem.png" width="200"
height="" alt="" style="margin-top:-10px;margin-left:13px">
</div>
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index e89e228..5c3990c 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -9,378 +9,100 @@ tabbedList=1
excludeFromSuggestions=true
@jd:body
-<style>
-#noplayer-message {
-position:absolute;top:50%;left:0;width:100%;z-index:-1;text-align:center;display:none;
-}
-#player-frame object {z-index:1;}
-</style>
-
-<div id="player-wrapper">
- <div id="player-frame">
- <div id="noplayer-message">
- <!-- busted flash player message -->
- Your video is supposed to appear here.<br/>
- Make sure you have the <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash&reg; Player</a>.
+<section class="dac-expand dac-hero dac-light">
+ <div class="wrap">
+ <div class="cols dac-hero-content">
+ <div class="col-1of2 col-push-1of2 dac-hero-figure">
+ <img class="dac-hero-image" src="/images/develop/hero-android-studio-on-device.png">
+ </div>
+ <div class="col-1of2 col-pull-1of2">
+ <h1 class="dac-hero-title">Start!</h1>
+ <p class="dac-hero-description">
+ Set up your environment and create an app. Build faster with sample projects and templates.
+ </p>
+ <a class="dac-hero-cta" href="/sdk/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Set up Android Studio
+ </a><br>
+ <a class="dac-hero-cta" href="/training/basics/firstapp/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Make your first app
+ </a><br>
+ <a class="dac-hero-cta" href="/guide/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Learn about Android
+ </a><br>
+ </div>
+ </div>
+ <div class="dac-section dac-small">
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:develop/landing/mainlinks"
+ data-cardSizes="6x2"
+ data-maxResults="6"></div>
</div>
- <div id="player"><!-- Youtube embeds here... actually replaces this div --></div>
- <a class="close" onclick="$('#player-wrapper').hide()">close video</a>
</div>
-</div>
-<div class="wrap">
- <!-- Slideshow -->
- <div class="slideshow-container slideshow-develop col-16">
- <a href="" class="slideshow-prev">Prev</a>
- <a href="" class="slideshow-next">Next</a>
- <div class="frame">
- <ul>
-
- <li class="item carousel-home">
- <div class="col-8">
- <img
- style="max-height: 250px; margin-top:5px;
- margin-left: 30px; max-width: 451px;"
-src="{@docRoot}design/tv/images/focus.png"
-class="play no-shadow no-transform" />
- </div>
- <div class="content-right col-6">
- <h2>Create Quality Apps for TV</h2>
- <p>Now that the Android platform has
- extended to TVs, your apps on Google Play have
- a new opportunity for engagement in the
- living room. To provide the best
- "leanback" experience on the couch, follow
- this quality checklist.</p>
- <p><a
-href="{@docRoot}distribute/essentials/quality/tv.html" class="button">Read
-more</a></p>
- </div>
- </li>
-
- <li class="item carousel-home">
- <div class="col-8">
- <img
-src="//lh4.ggpht.com/-lfjzgG5Dqrk/UHMThRtpRwI/AAAAAAAABpk/h4d3nsmkgPM/s400/mint.png"
-class="play no-shadow no-transform" />
- </div>
- <div class="content-right col-6">
- <h2>Building Great Apps for Tablets</h2>
- <p>Tablets are a fast-growing part of the Android installed base and they offer new opportunities for user engagement and monetization. If you are targeting tablets, check out this list of tips and techniques on how to deliver a great app experience for tablet users. </p>
- <p><a
-href="//android-developers.blogspot.com/2012/11/designing-for-tablets-were-here-to-help.html" class="button">Read
-more</a></p>
- </div>
- </li>
- <li class="item carousel-home">
- <div class="col-8">
- <img src="{@docRoot}images/google/gps-location.png"
-class="play no-shadow no-transform" style="margin:0 0 0 70px;height:230px;width:340px" />
- </div>
- <div class="content-right col-6" style="width:350px">
- <h2>New Location APIs from Google</h2>
- <p>The latest version of Google Play services includes new APIs that provide more
- efficient and immediate user location data on devices running Android 2.2
- and higher. Features include geofencing APIs, user activity recognition, and
- power-efficient location updates.</p>
- <p><a
-href="{@docRoot}google/play-services/location.html" class="button">Read more</a></p>
- </div>
- </li>
-
- <li class="item carousel-home">
- <div class="col-8">
- <img src="{@docRoot}images/google/gps-plus-signin-hero.jpg"
-class="play no-shadow no-transform" style="margin:0 0 0 40px;max-height:250px;height:250px;
- max-width:409px;width:409px" />
- </div>
- <div class="content-right col-6" style="width:350px">
- <h2>New Cross-Platform Single Sign On</h2>
- <p>Google+ Sign-In is an easy, trusted way to sign a user into your app.
- Now it's even more seamless. A user can sign in to your app on one device and
- pick it up on another&mdash;without signing in again. Best of all, it's built
- into Google+ Sign-in, so there's no change needed in your app.</p>
- <p><a
-href="{@docRoot}google/play-services/plus.html" class="button">Read more</a></p>
- </div>
- </li>
-
- <li class="item carousel-home">
- <div class="col-8">
- <img src="{@docRoot}images/google/maps-v2-trulia-n7.png"
-class="play no-shadow no-transform" style="margin:0 0 0 40px;max-height:250px;height:250px;
- max-width:409px;width:409px" />
- </div>
- <div class="content-right col-6" style="width:350px">
- <h2>New Google Maps Android APIs!</h2>
- <p>Google Maps Android API version 2 is now available with enhanced
- features such as 3D buildings, vector-based map tiles, rich overlay capabilities,
- indoor maps, support for fragments, and much more.</p>
-
- <p>The APIs are bundled with Google Play services and are
- compatible with Android 2.2 and higher.</p>
- <p><a
-href="{@docRoot}google/play-services/maps.html" class="button">Read more</a></p>
- </div>
- </li>
- </ul>
- </div>
- </div>
- <!-- /End slideshow -->
-</div>
-<div class="wrap">
- <!-- news and feature feed -->
- <div class="feed col-8" style="margin-left:0">
- <ul class="feed-nav">
- <li class="active">DEVELOPER NEWS</li>
- <li>FEATURED DOCS</li>
- </ul>
- <div class="feed-container">
- <div class="feed-frame">
- <!-- DEVELOPER NEWS -->
- <ul>
- <li><a href="//android-developers.blogspot.com/2013/07/making-beautiful-android-app-icons.html">
- <div class="feed-image" style="background:url('//2.bp.blogspot.com/-HfoO6KNFBKA/UeiyRoELb7I/AAAAAAAAAFs/bHR-5viktU4/s1000/icons.png') no-repeat 0 0;background-size:500px;background-position:center center;"></div>
- <h4>Making Beautiful Android App Icons</h4>
- <p>As higher density screens gain popularity, it's important to make sure your launcher icon is crisp and high quality...</p>
- </a></li>
- <li><a href="//android-developers.blogspot.com/2013/07/beautiful-design-collection-summer-2013.html">
- <div class="feed-image" style="background:url('//1.bp.blogspot.com/-k8DZYu0daT4/UdRt1AzstvI/AAAAAAAAAFM/CvEkb2yh-i0/s965/beautifulapps_4.png') no-repeat 0 0"></div>
- <h4>The Beautiful Design Summer 2013 Collection</h4>
- <p>See the apps chosen by the Android Design team for their masterfully crafted design details...</p>
- </a></li>
- <li><a href="//android-developers.blogspot.com/2013/10/new-developer-features-in-google-play.html">
- <div class="feed-image" style="background:url('//3.bp.blogspot.com/-k33rf398Lqw/UlRUMQQRUNI/AAAAAAAAClM/pSwz2YgQpmY/s1600/gps-play_games_logo.png') no-repeat 0 0;background-size:130px;background-position:8px -4px;"></div>
- <h4>New Features in Google Play Games</h4>
- <p>Three new features that make it easier to understand what players are doing in your game and help you manage game features...</p>
- </a></li>
- <li><a href="//android-developers.blogspot.com/2013/05/new-ways-to-optimize-your-business-in.html">
- <div class="feed-image" style="background:url('//3.bp.blogspot.com/-_8WvpdTVGsE/UkxxxrVoNNI/AAAAAAAACj8/FrQyA-BO11c/s1600/gp-referral-ga.png') no-repeat 0 0;background-size:180px"></div>
- <h4>Linking Google Analytics with Google Play</h4>
- <p>Understanding your users easier through a new integration between Google Analytics and the Google Play Developer Console...</p>
- </a></li>
- </ul>
- <!-- FEATURED DOCS -->
- <ul>
- <li><a href="{@docRoot}distribute/googleplay/spotlight/tablets.html">
- <h4>Tablet Stories</h4>
- <p>More developers are investing in a full tablet experience for their apps. Here are some stories from developers who are seeing real results as they expand their offering to include Android tablets. </p>
- </a></li>
- <li><a href="{@docRoot}distribute/googleplay/quality/core.html">
- <h4>Core App Quality Guidelines</h4>
- <p>This document helps you assess basic aspects of quality in your app through a compact set of core app quality criteria and associated tests. All Android apps should meet these criteria.</p>
- </a></li>
- <li><a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">
- <h4>Updated Notifications API Guide</h4>
- <p>The Notifications API Guide is updated to include information about building Jelly Bean rich notifications using the Support Library APIs for backwards-compatibility.</p>
- </a></li>
- <li><a href="{@docRoot}guide/topics/ui/dialogs.html">
- <h4>Updated Dialogs API Guide</h4>
- <p>The Dialogs API Guide now shows to use DialogFragment class, a simpler way to manage your dialogs and embed them in alternative layouts.</p>
- </a></li>
- </ul>
- </div>
- </div>
- </div> <!-- /news and feature feed -->
- <!-- video feed -->
- <div class="feed col-8" style="margin-right:0">
- <ul class="feed-nav">
- <li class="active">DEVELOPERS LIVE</li>
- <li>VIDEO PLAYLISTS</li>
- </ul>
- <div class="feed-container">
- <div class="feed-frame">
- <ul id="DevelopersLive">
- </ul>
- <ul id="VideoPlaylists">
- </ul>
- </div>
- </div>
- </div>
- <!-- /video feed -->
-</div>
-
-<br class="clearfix"/>
-
-
-
-
-
-
-
-
-
-
-<script src="//swfobject.googlecode.com/svn/trunk/swfobject/swfobject.js" type="text/javascript"></script>
-<script type="text/javascript">
-
-/* Load a video into the player box.
- * @param id The YouTube video ID
- * @param title The video title to display in the player box (character escaped)
- * @param autoplay Whether to automatically play the video
- */
-function loadVideo(id, title, autoplay) {
- swfobject.embedSWF('//www.youtube.com/v/' + id + '&rel=1&border=0&fs=1&autoplay=' +
- (autoplay?1:0), 'player', '525', '330', '9.0.0', false, false, {allowfullscreen: 'true'});
- $("#videoPlayerTitle").html("<h2>" + unescape(title) + "</h2>");
- $("#player-wrapper").show();
- setTimeout(function(){$('#noplayer-message').show()}, 2000);
-}
-
-/* Draw all videos from a playlist into a 'videoPreviews' list
- * @param data The feed data returned from the youtube request
- */
-function renderVideoPlaylists(data) {
- var MAX_LIST_DESC_LENGTH = 130; // the length at which we will trim the description
- var MAX_VIDEO_DESC_LENGTH = 100; // the length at which we will trim the description
- var MAX_LIST_LENGTH = 4; // number of videos to put in the list
- var feed = data.feed;
- var entries = feed.entry || [];
- var playlistId = feed.yt$playlistId.$t;
-
- var $ulVideos = $('<ul style="display:none"/>');
- var summary = feed.media$group.media$description != null ? feed.media$group.media$description.$t : feed.subtitle.$t;
-
- var $liPlaylist = $('<li class="playlist"></li>');
- var $aPlaylist = $('<a href="" onclick="togglePlaylist(this);return false;"></a>');
- $liPlaylist.append($aPlaylist);
- $aPlaylist.append('<h4>' + feed.title.$t + '</h4>');
-
- var playlistDescription = summary.substr(0, MAX_LIST_DESC_LENGTH);
- playlistDescription += playlistDescription.length == MAX_LIST_DESC_LENGTH ? "..." : ""; // add ellipsis if we've chopped the description
- $aPlaylist.append('<p>' + playlistDescription + '</p>');
-
- // Loop through each entry (each video) and add it to the 'videoPreviews' list
- var length = feed.entry.length < MAX_LIST_LENGTH ? feed.entry.length : MAX_LIST_LENGTH; // max of 4 videos per list
- for (var i = 0; i < length; i++) {
- var entry = entries[i];
-
- var title = entry.title.$t;
- var id = entry.media$group.yt$videoid.$t;
- var thumbUrl = entry.media$group.media$thumbnail[0].url;
- var fullDescription = entry.media$group.media$description.$t;
- var playerUrl = entry.media$group.media$content[0].url;
-
- var shortDescription = fullDescription.substr(0, MAX_VIDEO_DESC_LENGTH);
- shortDescription += shortDescription.length == MAX_VIDEO_DESC_LENGTH ? "..." : ""; // add ellipsis if we've chopped the description
-
- var img = $('<img src="' + thumbUrl + '" width="60" height="45"/>');
- var a = $('<a href="#" onclick="loadVideo(\'' + id + '\',\'' + escape(title) + '\',true); return false;" />');
- var pShortDescription = $('<p>' + shortDescription + '</p>');
- var h5Title = "<h5>" + title + "</h5>";
- var li = $('<li class="playlist-video"/>');
-
- li.append(a);
- a.append(img).append(h5Title).append(pShortDescription);
-
- $ulVideos.append(li);
-
- // use the first entry's thumbnail for the playlist
- if (i == 0) {
- $aPlaylist.prepend('<img src="' + thumbUrl + '" width="120" height="90"/>');
- }
- }
-
- if (feed.entry.length > MAX_LIST_LENGTH) {
- // add item to go to youtube for playlist
- $ulVideos.append('<li class="more"><a href="//www.youtube.com/playlist?list=' + playlistId + '">More &raquo;</a></li>');
- }
-
- $liPlaylist.append($ulVideos);
- $('#VideoPlaylists').append($liPlaylist);
-}
-
-
-function renderDevelopersLivePlaylist(data) {
-
- var MAX_DESC_LENGTH = 125; // the length at which we will trim the description
- var feed = data.feed;
- var entries = feed.entry || [];
- var playlistId = feed.yt$playlistId.$t;
-
- var ul = $('#DevelopersLive');
-
- // Loop through each entry (each video) and add it to the '#DevelopersLive' list
- for (var i = 0; i < 4; i++) {
- var entry = entries[i];
-
- var title = entry.title.$t;
- var id = entry.media$group.yt$videoid.$t;
- var thumbUrl = entry.media$group.media$thumbnail[0].url;
- var fullDescription = entry.media$group.media$description.$t;
- var playerUrl = entry.media$group.media$content[0].url;
- var shortDescription = fullDescription.substr(0, MAX_DESC_LENGTH);
- shortDescription += shortDescription.length == MAX_DESC_LENGTH ? "..." : ""; // add ellipsis if we've chopped the description
-
- var img = $('<img src="' + thumbUrl + '" width="120" height="90"/>');
- var a = $('<a href="#" onclick="loadVideo(\'' + id + '\',\'' + escape(title) + '\',true); return false;" />');
- var pShortDescription = $('<p>' + shortDescription + '</p>');
- var h4Title = "<h4>" + title + "</h4>";
- var li = $('<li/>');
-
- li.append(a);
- a.append(img).append(h4Title).append(pShortDescription);
-
- ul.append(li);
- }
-}
-
-/* This 'playlist' object defines the playlist IDs for each tab.
- * Each name inside 'playlist' corresponds to class names for the tab that the playlists belong to (eg: "googleioTab" and "googleioBox" divs).
- * Each string in 'ids' is the ID of a YouTube playlist that belongs in the corresponding tab.
- */
-var playlists = {
- 'designinaction' : {
- 'ids': ["PLWz5rJ2EKKc8j2B95zGMb8muZvrIy-wcF"]
- },
- 'bizdevbytes' : {
- 'ids': ["PLWz5rJ2EKKc8-Osr0TuHyTMEhKV0xJ6ql"]
- },
- 'thisweek' : {
- 'ids': ["PLWz5rJ2EKKc9Wam5jE-9oY8l6RpeAx-XM"]
- },
- 'googleio' : {
- 'ids': ["PLWz5rJ2EKKc9WGUwq2gQ-coU3fSyexgOx"]
- }
-};
-
-/* Request the playlist feeds from YouTube */
-function showVideosPlaylists() {
- for (var x in playlists) {
- var ids = playlists[x].ids;
- for (var i in ids) {
- var script = "<script type='text/javascript' src='//gdata.youtube.com/feeds/api/playlists/"
- + ids[i] +
- "?v=2&alt=json-in-script&max-results=50&callback=renderVideoPlaylists&orderby=position'><\/script>";
- $("body").append(script);
- }
- }
-}
-
-
-/* Request the playlist feeds from YouTube */
-function showDevelopersLivePlaylist() {
- var playlistId = "PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0"; /* DevBytes */
- var script = "<script type='text/javascript' src='//gdata.youtube.com/feeds/api/playlists/"
- + playlistId +
- "?v=2&alt=json-in-script&max-results=10&callback=renderDevelopersLivePlaylist&orderby=position'><\/script > ";
- $("body").append(script);
-}
-
-
-function togglePlaylist(listLink) {
- var $list = $(listLink).parent();
- var $ul = $list.find('ul');
- if ($ul.is(":visible")) {
- $ul.slideUp(function() {
- $list.css({'height':'inherit'});
- });
- } else {
- $list.closest('ul').find('li.playlist').find('ul').slideUp();
- $ul.slideDown();
- $list.css({'height':'auto'});
- }
-}
-
-showDevelopersLivePlaylist();
-showVideosPlaylists();
-</script>
+</section>
+
+<section class="dac-section dac-gray dac-small dac-invert"><div class="wrap">
+ <h2 class="norule">Latest</h2>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:develop/landing/latest"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+</div></section>
+
+<section class="dac-section dac-light"><div class="wrap">
+ <h1 class="dac-section-title">Android performance patterns</h1>
+ <div class="dac-section-subtitle">
+ Everything you need to know about improving your app’s performance.
+ </div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:develop/landing/performance"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+ <ul class="dac-section-links">
+ <li class="dac-section-link"><a href="https://www.youtube.com/playlist?list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Playlist
+ </a></li>
+ </ul>
+</div></section>
+
+<section class="dac-section dac-dark dac-invert"><div class="wrap">
+ <h1 class="dac-section-title">Build with Google</h1>
+ <div class="dac-section-subtitle">Services on billions of Android devices worldwide to help you build better apps.</div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:develop/landing/buildwithgoogle"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+ <ul class="dac-section-links">
+ <li class="dac-section-link"><a href="https://developers.google.com/">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Get started with Google << NEEDS LINK
+ </a></li>
+ </ul>
+</div></section>
+
+<section class="dac-section dac-light"><div class="wrap">
+ <h1 class="dac-section-title">DevBytes</h1>
+ <div class="dac-section-subtitle">Learn Android in short, focused tutorials.</div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:develop/landing/devbytes"
+ data-cardSizes="6x6"
+ data-maxResults="6"></div>
+ <ul class="dac-section-links">
+ <li class="dac-section-link"><a href="https://www.youtube.com/watch?v=wlFVIIstKmA&list=PLOU2XLYxmsIJJHY5OrsREtKewtBhc0Uy2">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ DevBytes 2014 playlist
+ </a></li>
+ </ul>
+</div></section>
+
+<section class="dac-section dac-gray"><div class="wrap">
+ <h1 class="dac-section-title">Courses</h1>
+ <div class="dac-section-subtitle">Take free online courses from Android experts that bring you step-by-step to building your own apps.</div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:develop/landing/courses"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+</div></section>
diff --git a/docs/html/distribute/analyze/index.jd b/docs/html/distribute/analyze/index.jd
index d8ab59e..f948dbd 100644
--- a/docs/html/distribute/analyze/index.jd
+++ b/docs/html/distribute/analyze/index.jd
@@ -1,5 +1,6 @@
page.title=Analyze
page.metaDescription=Understanding what your users do inside your app is the key to engaging and monetizing them.
+page.image=images/cards/analytics-mobile_2x.jpg
section.landing=true
excludefromsuggestions=true
nonavpage=true
@@ -37,4 +38,3 @@ nonavpage=true
data-cardSizes="6x6"
data-maxResults="10">
</div>
- \ No newline at end of file
diff --git a/docs/html/distribute/engage/deep-linking.jd b/docs/html/distribute/engage/deep-linking.jd
index a25c3c6..ea1f1de 100644
--- a/docs/html/distribute/engage/deep-linking.jd
+++ b/docs/html/distribute/engage/deep-linking.jd
@@ -1,7 +1,7 @@
page.title=Deep Link to Bring Users Back
page.metaDescription=Use deep links to bring your users into your apps from social posts, search, or ads.
page.tags="app indexing, google+ signin"
-page.image=/images/gp-listing-4.jpg
+page.image=images/cards/google-search_2x.png
@jd:body
@@ -96,4 +96,4 @@ page.image=/images/gp-listing-4.jpg
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/engage/deeplinks" data-sortorder="-timestamp"
data-cardsizes="9x3" data-maxresults="6">
-</div> \ No newline at end of file
+</div>
diff --git a/docs/html/distribute/engage/easy-signin.jd b/docs/html/distribute/engage/easy-signin.jd
index d066181..2bfa5d1 100644
--- a/docs/html/distribute/engage/easy-signin.jd
+++ b/docs/html/distribute/engage/easy-signin.jd
@@ -1,7 +1,7 @@
page.title=Make Signing In Easy
page.metaDescription=Increase conversion rates while helping users minimize typing by letting users sign in with Google+.
page.tags="google+"
-page.image=/images/google/gps-googleplus.png
+page.image=images/cards/google-sign-in_2x.png
@jd:body
diff --git a/docs/html/distribute/googleplay/about.jd b/docs/html/distribute/googleplay/about.jd
index c25a9cf..2652046 100644
--- a/docs/html/distribute/googleplay/about.jd
+++ b/docs/html/distribute/googleplay/about.jd
@@ -2,7 +2,7 @@ page.title=The Google Play Opportunity
meta.tags="visibility, growth, distributing"
page.tags="play, apps, distributing, publishing"
page.metaDescription=Billons of downloads a month and growing. Get your apps in front of users at Google's scale.
-page.image=/distribute/images/about-play.jpg
+page.image=images/cards/google-play_2x.png
@jd:body
@@ -369,4 +369,4 @@ page.image=/distribute/images/about-play.jpg
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="4"></div>
- </div> \ No newline at end of file
+ </div>
diff --git a/docs/html/distribute/googleplay/developer-console.jd b/docs/html/distribute/googleplay/developer-console.jd
index f5b3ac6..748c1d1 100644
--- a/docs/html/distribute/googleplay/developer-console.jd
+++ b/docs/html/distribute/googleplay/developer-console.jd
@@ -1,6 +1,6 @@
page.title=Developer Console
page.metaDescription=Learn about the Developer Console, your home for app publishing on Google Play.
-page.image=/distribute/images/developer-console.jpg
+page.image=images/cards/dev-console_2x.jpg
Xnonavpage=true
@jd:body
@@ -600,4 +600,4 @@ Xnonavpage=true
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>
- </div> \ No newline at end of file
+ </div>
diff --git a/docs/html/distribute/googleplay/index.jd b/docs/html/distribute/googleplay/index.jd
index b25f6b7..72e2de8 100644
--- a/docs/html/distribute/googleplay/index.jd
+++ b/docs/html/distribute/googleplay/index.jd
@@ -1,4 +1,5 @@
page.title=Google Play
+page.image=images/cards/program-edu_2x.jpg
section.landing=true
nonavpage=true
diff --git a/docs/html/distribute/images/advertising.jpg b/docs/html/distribute/images/advertising.jpg
index 9625671..7747097 100644
--- a/docs/html/distribute/images/advertising.jpg
+++ b/docs/html/distribute/images/advertising.jpg
Binary files differ
diff --git a/docs/html/distribute/index.jd b/docs/html/distribute/index.jd
index d0ea661..c49fe3e 100644
--- a/docs/html/distribute/index.jd
+++ b/docs/html/distribute/index.jd
@@ -1,3 +1,4 @@
+fullpage=true
page.title=Distribute Your Apps
page.viewport_width=970
section.landing=true
@@ -6,21 +7,74 @@ nonavpage=true
page.metaDescription=The most visited store in the world for Android apps. Cloud-connected and always synced, it's never been easier for users to find and download your apps.
@jd:body
+<div class="dac-hero-carousel" data-carousel-query="collection:distribute/landing/carousel">
+</div>
- <div class="resource-widget resource-carousel-layout col-16"
- style="height:420px;margin-top:20px;padding-top:0"
- data-query="type:youtube+tag:googleplay+tag:developerstory+tag:featured"
- data-sortOdrder="-timestamp"
- data-maxResults="4"></div>
+<section class="dac-section dac-gray dac-small dac-invert"><div class="wrap">
+ <h2 class="norule">Latest</h2>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="type:youtube+tag:googleplay+tag:developerstory+tag:featured, type:blog+tag:googleplay+tag:distribute+tag:featured"
+ data-sortOrder="-timestamp"
+ data-cardSizes="6x6"
+ data-maxResults="6"></div>
+</div></section>
+<section class="dac-section dac-invert dac-darken-bg" style="background-image: url(/images/distribute/google-play-bg.jpg)"><div class="wrap">
+ <div class="cols"><div class="col-10of12 col-push-1of12">
+ <h1 class="dac-section-title">Reach the world with Google Play</h1>
+ <div class="dac-section-subtitle">
+ Publish your apps and games on Google Play and reach over a billion active Android users in over 190 countries around the world.
+ </div>
+ </div></div>
<div class="resource-widget resource-flow-layout col-16"
- data-query="type:blog+tag:googleplay+tag:distribute+tag:featured"
- data-sortOrder=""
- data-cardSizes="9x6"
- data-maxResults="2"></div>
+ data-query="collection:distribute/landing/googleplay"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+
+ <ul class="dac-section-links">
+ <li class="dac-section-link"><a href="/distribute/googleplay/start.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Get started
+ </a></li>
+ <li class="dac-section-link"><a href="/distribute/essentials/index.html#quality-guidelines">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Quality guidelines
+ </a></li>
+ <li class="dac-section-link"><a href="/distribute/essentials/index.html#tools-and-resources">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Resources &amp; tools
+ </a></li>
+ <li class="dac-section-link"><a href="/distribute/stories/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Developer stories
+ </a></li>
+ <li class="dac-section-link"><a href="/distribute/users/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Get users
+ </a></li>
+ <li class="dac-section-link"><a href="/distribute/engage/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Engage &amp; retain
+ </a></li>
+ <li class="dac-section-link"><a href="/distribute/monetize/index.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Monetize
+ </a></li>
+ </ul>
+</div></section>
+<section class="dac-section dac-light"><div class="wrap">
+ <div class="cols"><div class="col-10of12 col-push-1of12">
+ <h1 class="dac-section-title">More from Google</h1>
+ <div class="dac-section-subtitle">Reach and retain a valuable audience and grow your revenue.</div>
+ </div></div>
<div class="resource-widget resource-flow-layout col-16"
- data-query="collection:launch/static"
- data-sortOrder=""
- data-cardSizes="6x2x3,6x6,6x6,6x6,6x6,6x2x3,6x2x3,6x6,6x6,6x6,6x6,6x6"
- data-maxResults="24"></div>
+ data-query="collection:distribute/landing/more"
+ data-cardSizes="6x6"></div>
+ <ul class="dac-section-links">
+ <li class="dac-section-link"><a href="https://developers.google.com/">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ More on Google Developers
+ </a></li>
+ </ul>
+</div></section>
diff --git a/docs/html/distribute/monetize/ads.jd b/docs/html/distribute/monetize/ads.jd
index 9a847ff..b5c5f4a 100644
--- a/docs/html/distribute/monetize/ads.jd
+++ b/docs/html/distribute/monetize/ads.jd
@@ -1,7 +1,7 @@
page.title=Monetize with Ads
page.metaDescription=Ads are a quick and easy way to incorporate a monetization option into both your free and paid apps.
page.tags="monetizing", "free", "freemium", "ads"
-page.image=/distribute/images/advertising.png
+page.image=/distribute/images/advertising.jpg
@jd:body
diff --git a/docs/html/distribute/tools/promote/device-art-resources/nexus_6/port_back.png b/docs/html/distribute/tools/promote/device-art-resources/nexus_6/port_back.png
index 6e1aec6..cf3e15a 100644
--- a/docs/html/distribute/tools/promote/device-art-resources/nexus_6/port_back.png
+++ b/docs/html/distribute/tools/promote/device-art-resources/nexus_6/port_back.png
Binary files differ
diff --git a/docs/html/distribute/tools/promote/device-art.jd b/docs/html/distribute/tools/promote/device-art.jd
index 814177b..d321074 100644
--- a/docs/html/distribute/tools/promote/device-art.jd
+++ b/docs/html/distribute/tools/promote/device-art.jd
@@ -16,12 +16,12 @@ feature image or screenshots for your Google Play app listing.</p>
<div class="supported-browser">
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Step 1</h4>
<p>Drag a screenshot from your desktop onto a device to the right.</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<ul class="device-list primary"></ul>
<a href="#" id="archive-expando">Older devices</a>
<ul class="device-list archive"></ul>
@@ -30,8 +30,8 @@ feature image or screenshots for your Google Play app listing.</p>
-<div class="layout-content-row">
- <div class="layout-content-col span-3">
+<div class="cols">
+ <div class="col-3">
<h4>Step 2</h4>
<p>Customize the generated image and drag it to your desktop to save.</p>
<p id="frame-customizations">
@@ -48,7 +48,7 @@ feature image or screenshots for your Google Play app listing.</p>
<label for="output-round">Round</label><br><br>
</p>
</div>
- <div class="layout-content-col span-10">
+ <div class="col-10">
<!-- position:relative fixes an issue where dragging an image out of a inline-block container
produced no drag feedback image in Chrome 28. -->
<div id="output" style="position:relative">No input image.</div>
diff --git a/docs/html/distribute/users/promote-with-ads.jd b/docs/html/distribute/users/promote-with-ads.jd
index 1e28ae1..c1d79fc 100644
--- a/docs/html/distribute/users/promote-with-ads.jd
+++ b/docs/html/distribute/users/promote-with-ads.jd
@@ -1,6 +1,6 @@
page.title=Promote Your App with Ads
page.metaDescription=Promote your app through AdMob, AdWords, and YouTube to find new users at the right moment.
-page.image=/images/gp-ads-console.jpg
+page.image=images/cards/adwords_2x.jpg
page.tags="users, ads, analytics"
@jd:body
@@ -42,4 +42,4 @@ page.tags="users, ads, analytics"
data-query="collection:distribute/users/promotewithads"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
- data-maxResults="6"></div> \ No newline at end of file
+ data-maxResults="6"></div>
diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd
index 4778a85..cc209cd 100644
--- a/docs/html/google/index.jd
+++ b/docs/html/google/index.jd
@@ -16,7 +16,7 @@ div.cell-icon img {
}
</style>
-<div class="landing-banner">
+<div class="landing-banner cols">
<div class="col-6" style="min-height:0">
<img src="{@docRoot}images/google/google-services.png" alt="" width="340" height="193" />
diff --git a/docs/html/google/play-services/index.jd b/docs/html/google/play-services/index.jd
index 5ccdcb9..11060e8 100644
--- a/docs/html/google/play-services/index.jd
+++ b/docs/html/google/play-services/index.jd
@@ -24,8 +24,8 @@ page.metaDescription=With Google Play services, your app can take advantage of t
</div>
</div>
- <div class="layout-content-row">
- <div class="layout-content-col span-4">
+ <div class="cols">
+ <div class="col-4">
<h4>Google Technology</h4>
<p>Google Play services provides you with easy access to Google services and is
@@ -34,7 +34,7 @@ provided for each service that let you implement the functionality you want
easier and faster.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Standard Authorization</h4>
<p>All products in Google Play services share a common authorization API
@@ -43,7 +43,7 @@ easier and faster.</p>
to Google services.</p>
</div>
- <div class="layout-content-col span-4">
+ <div class="col-4">
<h4>Automatic Updates</h4>
<p>Devices running Android 2.3 or higher that have the Google Play Store
@@ -666,8 +666,8 @@ announcement <a href="http://android-developers.blogspot.com/2014/03/google-play
<div class="vspace size-2">&nbsp;</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4 id="apk">The Google Play services APK</h4>
<p>
The Google Play services APK contains the individual Google services and runs
@@ -687,7 +687,7 @@ announcement <a href="http://android-developers.blogspot.com/2014/03/google-play
</p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<img src="/images/play-services-diagram.png" />
<p class="img-caption"><em>The Google Play services APK on user devices receives regular updates
for new APIs, features, and bug fixes.</em></p>
diff --git a/docs/html/google/play-services/location.jd b/docs/html/google/play-services/location.jd
index b28302c..98b0544 100644
--- a/docs/html/google/play-services/location.jd
+++ b/docs/html/google/play-services/location.jd
@@ -30,8 +30,8 @@ developer guide.
</div>
<div class="landing-docs">
<h3 style="clear:left">Key Developer Features</h3>
- <div class="layout-content-row normal-links">
- <div class="layout-content-col span-6">
+ <div class="cols normal-links">
+ <div class="col-6">
@@ -74,7 +74,7 @@ developer guide.
</ul>
</div>
-<div class="layout-content-col span-6">
+<div class="col-6">
<h4 style="font-weight:bold">Places API</h4>
diff --git a/docs/html/google/play/dist.jd b/docs/html/google/play/dist.jd
index f1ad834..02bb42b 100644
--- a/docs/html/google/play/dist.jd
+++ b/docs/html/google/play/dist.jd
@@ -9,8 +9,8 @@ page.title=Google Play Distribution
<div class="vspace size-1">
&nbsp;
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>
Device Filtering
</h4>
@@ -20,7 +20,7 @@ page.title=Google Play Distribution
</p><p><a href="{@docRoot}google/play/filters.html">Learn more &raquo;</a></p>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>
Multiple APK Support
</h4>
@@ -30,8 +30,8 @@ page.title=Google Play Distribution
</p><p><a href="{@docRoot}google/play/publishing/multiple-apks.html">Learn more &raquo;</a></p>
</div>
-<div class="layout-content-row">
- <div class="layout-content-col span-6">
+<div class="cols">
+ <div class="col-6">
<h4>
APK Expansion files
</h4>
@@ -42,14 +42,14 @@ page.title=Google Play Distribution
</p><a href="{@docRoot}google/play/expansion-files.html">Learn more &raquo;</a>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>
Application Licensing
</h4>
<p>Protect your revenue streams and integrate policies for usage into your app.
</p><a href="{@docRoot}google/play/licensing/index.html">Learn more &raquo;</a>
</div>
- <div class="layout-content-col span-6">
+ <div class="col-6">
<h4>
Google Play Developer API
</h4>
diff --git a/docs/html/images/cards/adwords_2x.jpg b/docs/html/images/cards/adwords_2x.jpg
new file mode 100644
index 0000000..cd83b26
--- /dev/null
+++ b/docs/html/images/cards/adwords_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/analytics-mobile_2x.jpg b/docs/html/images/cards/analytics-mobile_2x.jpg
new file mode 100644
index 0000000..e668991
--- /dev/null
+++ b/docs/html/images/cards/analytics-mobile_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/android-auto_2x.png b/docs/html/images/cards/android-auto_2x.png
new file mode 100644
index 0000000..6acdcb1
--- /dev/null
+++ b/docs/html/images/cards/android-auto_2x.png
Binary files differ
diff --git a/docs/html/images/cards/android-devices_2x.jpg b/docs/html/images/cards/android-devices_2x.jpg
new file mode 100644
index 0000000..cefff15
--- /dev/null
+++ b/docs/html/images/cards/android-devices_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/android-studio_2x.png b/docs/html/images/cards/android-studio_2x.png
new file mode 100644
index 0000000..87f9e70
--- /dev/null
+++ b/docs/html/images/cards/android-studio_2x.png
Binary files differ
diff --git a/docs/html/images/cards/android-tv_2x.png b/docs/html/images/cards/android-tv_2x.png
new file mode 100644
index 0000000..deb41a2
--- /dev/null
+++ b/docs/html/images/cards/android-tv_2x.png
Binary files differ
diff --git a/docs/html/images/cards/android-wear-apps_2x.jpg b/docs/html/images/cards/android-wear-apps_2x.jpg
new file mode 100644
index 0000000..614ef19
--- /dev/null
+++ b/docs/html/images/cards/android-wear-apps_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/android-wear-materials_2x.jpg b/docs/html/images/cards/android-wear-materials_2x.jpg
new file mode 100644
index 0000000..19a78c3
--- /dev/null
+++ b/docs/html/images/cards/android-wear-materials_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/android-wear_2x.png b/docs/html/images/cards/android-wear_2x.png
new file mode 100644
index 0000000..5d1a796
--- /dev/null
+++ b/docs/html/images/cards/android-wear_2x.png
Binary files differ
diff --git a/docs/html/images/cards/cloud-platform_2x.png b/docs/html/images/cards/cloud-platform_2x.png
new file mode 100644
index 0000000..d3c203d
--- /dev/null
+++ b/docs/html/images/cards/cloud-platform_2x.png
Binary files differ
diff --git a/docs/html/images/cards/design-creative-vision_2x.jpg b/docs/html/images/cards/design-creative-vision_2x.jpg
new file mode 100644
index 0000000..9c7dde3
--- /dev/null
+++ b/docs/html/images/cards/design-creative-vision_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/design-material-for-android_2x.jpg b/docs/html/images/cards/design-material-for-android_2x.jpg
new file mode 100644
index 0000000..e47594a
--- /dev/null
+++ b/docs/html/images/cards/design-material-for-android_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/design-new-in-android_2x.jpg b/docs/html/images/cards/design-new-in-android_2x.jpg
new file mode 100644
index 0000000..3bdd542
--- /dev/null
+++ b/docs/html/images/cards/design-new-in-android_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/design-pure-android_2x.png b/docs/html/images/cards/design-pure-android_2x.png
new file mode 100644
index 0000000..94758f7
--- /dev/null
+++ b/docs/html/images/cards/design-pure-android_2x.png
Binary files differ
diff --git a/docs/html/images/cards/dev-console_2x.jpg b/docs/html/images/cards/dev-console_2x.jpg
new file mode 100644
index 0000000..f2d10eb
--- /dev/null
+++ b/docs/html/images/cards/dev-console_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/google-play_2x.png b/docs/html/images/cards/google-play_2x.png
new file mode 100644
index 0000000..8680639
--- /dev/null
+++ b/docs/html/images/cards/google-play_2x.png
Binary files differ
diff --git a/docs/html/images/cards/google-search_2x.png b/docs/html/images/cards/google-search_2x.png
new file mode 100644
index 0000000..2564121
--- /dev/null
+++ b/docs/html/images/cards/google-search_2x.png
Binary files differ
diff --git a/docs/html/images/cards/google-sign-in_2x.png b/docs/html/images/cards/google-sign-in_2x.png
new file mode 100644
index 0000000..60078a7
--- /dev/null
+++ b/docs/html/images/cards/google-sign-in_2x.png
Binary files differ
diff --git a/docs/html/images/cards/material-animation_2x.png b/docs/html/images/cards/material-animation_2x.png
new file mode 100644
index 0000000..79315e4
--- /dev/null
+++ b/docs/html/images/cards/material-animation_2x.png
Binary files differ
diff --git a/docs/html/images/cards/material-color-palette_2x.jpg b/docs/html/images/cards/material-color-palette_2x.jpg
new file mode 100644
index 0000000..bae8d07
--- /dev/null
+++ b/docs/html/images/cards/material-color-palette_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/material-components_2x.jpg b/docs/html/images/cards/material-components_2x.jpg
new file mode 100644
index 0000000..7ac1012
--- /dev/null
+++ b/docs/html/images/cards/material-components_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/material-layout-template_2x.jpg b/docs/html/images/cards/material-layout-template_2x.jpg
new file mode 100644
index 0000000..d2fa3c5
--- /dev/null
+++ b/docs/html/images/cards/material-layout-template_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/material-layout_2x.png b/docs/html/images/cards/material-layout_2x.png
new file mode 100644
index 0000000..6c5dca1
--- /dev/null
+++ b/docs/html/images/cards/material-layout_2x.png
Binary files differ
diff --git a/docs/html/images/cards/material-patterns_2x.png b/docs/html/images/cards/material-patterns_2x.png
new file mode 100644
index 0000000..8e8d8aa
--- /dev/null
+++ b/docs/html/images/cards/material-patterns_2x.png
Binary files differ
diff --git a/docs/html/images/cards/material-sticker-sheet_2x.jpg b/docs/html/images/cards/material-sticker-sheet_2x.jpg
new file mode 100644
index 0000000..8e9f3f7c
--- /dev/null
+++ b/docs/html/images/cards/material-sticker-sheet_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/material-style_2x.jpg b/docs/html/images/cards/material-style_2x.jpg
new file mode 100644
index 0000000..38ae540
--- /dev/null
+++ b/docs/html/images/cards/material-style_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/material-typography_2x.jpg b/docs/html/images/cards/material-typography_2x.jpg
new file mode 100644
index 0000000..537db8e
--- /dev/null
+++ b/docs/html/images/cards/material-typography_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/material-usability_2x.png b/docs/html/images/cards/material-usability_2x.png
new file mode 100644
index 0000000..468e1c8
--- /dev/null
+++ b/docs/html/images/cards/material-usability_2x.png
Binary files differ
diff --git a/docs/html/images/cards/material_2x.png b/docs/html/images/cards/material_2x.png
new file mode 100644
index 0000000..e759d9f
--- /dev/null
+++ b/docs/html/images/cards/material_2x.png
Binary files differ
diff --git a/docs/html/images/cards/program-edu_2x.jpg b/docs/html/images/cards/program-edu_2x.jpg
new file mode 100644
index 0000000..4430dfd
--- /dev/null
+++ b/docs/html/images/cards/program-edu_2x.jpg
Binary files differ
diff --git a/docs/html/images/cards/samples-new_2x.png b/docs/html/images/cards/samples-new_2x.png
new file mode 100644
index 0000000..270f4a3
--- /dev/null
+++ b/docs/html/images/cards/samples-new_2x.png
Binary files differ
diff --git a/docs/html/images/develop/hero-android-studio-on-device.png b/docs/html/images/develop/hero-android-studio-on-device.png
new file mode 100644
index 0000000..eac0e1f
--- /dev/null
+++ b/docs/html/images/develop/hero-android-studio-on-device.png
Binary files differ
diff --git a/docs/html/images/distribute/google-play-bg.jpg b/docs/html/images/distribute/google-play-bg.jpg
new file mode 100644
index 0000000..effd422
--- /dev/null
+++ b/docs/html/images/distribute/google-play-bg.jpg
Binary files differ
diff --git a/docs/html/images/distribute/hero-family.jpg b/docs/html/images/distribute/hero-family.jpg
new file mode 100644
index 0000000..6e467a5
--- /dev/null
+++ b/docs/html/images/distribute/hero-family.jpg
Binary files differ
diff --git a/docs/html/images/distribute/hero-g-play-guidebooks_2x.png b/docs/html/images/distribute/hero-g-play-guidebooks_2x.png
new file mode 100644
index 0000000..3dfda18
--- /dev/null
+++ b/docs/html/images/distribute/hero-g-play-guidebooks_2x.png
Binary files differ
diff --git a/docs/html/images/distribute/hero-ginlemon.jpg b/docs/html/images/distribute/hero-ginlemon.jpg
new file mode 100644
index 0000000..11837b3
--- /dev/null
+++ b/docs/html/images/distribute/hero-ginlemon.jpg
Binary files differ
diff --git a/docs/html/images/distribute/hero-haystack.jpg b/docs/html/images/distribute/hero-haystack.jpg
new file mode 100644
index 0000000..36b6d9f
--- /dev/null
+++ b/docs/html/images/distribute/hero-haystack.jpg
Binary files differ
diff --git a/docs/html/images/distribute/hero-jelly-button.jpg b/docs/html/images/distribute/hero-jelly-button.jpg
new file mode 100644
index 0000000..032755b
--- /dev/null
+++ b/docs/html/images/distribute/hero-jelly-button.jpg
Binary files differ
diff --git a/docs/html/images/distribute/hero-outfit7.jpg b/docs/html/images/distribute/hero-outfit7.jpg
new file mode 100644
index 0000000..a013417
--- /dev/null
+++ b/docs/html/images/distribute/hero-outfit7.jpg
Binary files differ
diff --git a/docs/html/images/home/hero-lollipop_2x.png b/docs/html/images/home/hero-lollipop_2x.png
new file mode 100644
index 0000000..6f41e13
--- /dev/null
+++ b/docs/html/images/home/hero-lollipop_2x.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 2838959..cfbe7b6 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -6,96 +6,53 @@ page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3
@jd:body
-<div class="home-new-carousel-1">
- <div class="fullscreen-carousel-content">
- <div class="vcenter">
- <div class="wrap clearfix">
+<div class="dac-hero-carousel" data-carousel-query="collection:index/carousel">
+</div>
- <div class="static resource-flow-layout wrap col-16">
- <div class="resource resource-card resource-card-18x6">
-
- <div class="landing-section-header">
- <div class="col-10"><img src="{@docRoot}images/home/l-hero_2x.png"
- srcset="{@docRoot}images/home/l-hero.png 1x, {@docRoot}images/home/l-hero_2x.png 2x"
- width="510" style="margin:20px 30px 0 30px"></div>
- <div class="col-5" style=" margin-top:70px ">
- <h3 stye="font-weight:300;">Android 5.0 Lollipop</h3>
- <p>The Android 5.0 update adds a variety of new
- features for your apps, such as notifications on the lock screen, an all-new camera API,
- OpenGL ES 3.1, the new Material design interface, and much more.</p>
- <a href="{@docRoot}about/versions/lollipop.html" class="landing-button landing-primary">Learn More</a>
- </div>
- </div>
- </div>
- </div>
- <h2>&nbsp;</h2>
- <div style="margin-top:20px;height:115px" class="resource-widget resource-flow-layout wrap col-16
- no-section" data-query="collection:index/primary" data-resourcestyle="card"
- data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget -->
- </div> <!-- end .wrap -->
- </div> <!-- end .vcenter -->
- </div> <!-- end .fullscreen-carousel-content -->
-</div> <!-- end .fullscreen-carousel -->
-
-<div class="actions-bar" style="margin-top:20px">
+<div class="actions-bar dac-expand dac-invert">
<div class="wrap">
<div class="actions">
- <div><a href="{@docRoot}sdk/index.html">Get the SDK</a></div>
- <div><a href="{@docRoot}samples/index.html">Browse Samples</a></div>
- <div><a href="//www.youtube.com/user/androiddevelopers">Watch Videos</a></div>
- <div><a href="{@docRoot}distribute/googleplay/developer-console.html">Manage Your Apps</a></div>
+ <div><a href="{@docRoot}sdk/index.html">
+ <span class="dac-sprite dac-auto-chevron-large"></span>
+ Get the SDK
+ </a></div>
+ <div><a href="{@docRoot}samples/index.html">
+ <span class="dac-sprite dac-auto-chevron-large"></span>
+ Browse Samples
+ </a></div>
+ <div><a href="//www.youtube.com/user/androiddevelopers">
+ <span class="dac-sprite dac-auto-chevron-large"></span>
+ Watch Videos
+ </a></div>
+ <div><a href="{@docRoot}distribute/googleplay/developer-console.html">
+ <span class="dac-sprite dac-auto-chevron-large"></span>
+ Manage Your Apps
+ </a></div>
</div><!-- end .actions -->
</div><!-- end .wrap -->
</div><!-- end .actions-bar -->
-
-
-<div class="landing-rest-of-page">
- <div class="landing-section">
- <div class="wrap">
- <div class="landing-section-header">
-
- <div class="landing-h1" style="margin-top:0px">Build for a Multi-Screen World</div>
- <div class="landing-subhead" style="margin-top: 20px;">
- Android runs on hundreds of millions of handheld devices around the world, <br>
- and it now supports these exciting, new form-factors.
- </div>
- </div>
- <div class="landing-body" style="margin-top: 50px;">
- <div class="landing-breakout cols">
- <div class="col-3-wide">
- <img src="{@docRoot}images/home/wear-wordmark.png">
- <img src="{@docRoot}images/home/wear.png">
- <p class="landing-small">
- Provide information on-the-go for your users, whenever they need it.
- </p>
- <p class="landing-small">
- <a href="{@docRoot}wear/index.html">Learn about Android Wear</a>
- </p>
- </div>
- <div class="col-3-wide">
- <img src="{@docRoot}images/home/tv-wordmark.png">
- <img src="{@docRoot}images/home/tv.png">
- <p class="landing-small">
- Build your apps for the big screen and bring your content to life.
- </p>
- <p class="landing-small">
- <a href="{@docRoot}tv/index.html">Learn about Android TV</a>
-
- </p>
- </div>
- <div class="col-3-wide">
- <img src="{@docRoot}images/home/auto-wordmark.png">
- <img src="{@docRoot}images/home/auto.png">
- <p class="landing-small">
- Extend your music apps to automobile
- entertainment systems.
- </p>
- <p class="landing-small">
- <a href="{@docRoot}auto/index.html">Learn about Android Auto</a>
- </p>
- </div>
- </div>
- </div>
- </div> <!-- end .wrap -->
- </div> <!-- end .landing-section --> \ No newline at end of file
+<section class="dac-section dac-section-light"><div class="wrap">
+ <h1 class="dac-section-title">Build Beautiful Apps</h1>
+ <div class="dac-section-subtitle">
+ See what’s new or find the resources to get you started with designing and developing for Android.
+ </div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:index/primary"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+</div></section>
+
+<section class="dac-section dac-gray"><div class="wrap">
+ <div class="cols"><div class="col-10of12 col-push-1of12">
+ <h1 class="dac-section-title">Build for a Multi-Screen World</h1>
+ <div class="dac-section-subtitle">
+ Android runs on hundreds of millions of handheld devices around the world,
+ and it now supports these exciting, new form-factors.
+ </div>
+ </div></div>
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:index/multiscreen"
+ data-cardSizes="6x6"
+ data-maxResults="3"></div>
+</div></section>
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index e2d0eb9..b28f978 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -1,4 +1,10 @@
var RESOURCE_COLLECTIONS = {
+ "index/carousel": {
+ "title": "",
+ "resources": [
+ "about/versions/lollipop.html"
+ ]
+ },
"index/primary": {
"title": "",
"resources": [
@@ -7,6 +13,14 @@ var RESOURCE_COLLECTIONS = {
"sdk/index.html"
]
},
+ "index/multiscreen": {
+ "title": "",
+ "resources": [
+ "wear/index.html",
+ "tv/index.html",
+ "auto/index.html"
+ ]
+ },
"index/primary/zhcn": {
"title": "",
"resources": [
@@ -15,6 +29,119 @@ var RESOURCE_COLLECTIONS = {
"intl/zh-cn/distribute/tools/localization-checklist.html"
]
},
+ "design/landing/latest": {
+ "title": "",
+ "resources": [
+ "http://www.youtube.com/watch?v=p4gmvHyuZzw",
+ "http://www.youtube.com/watch?v=YaG_ljfzeUw",
+ "http://www.youtube.com/watch?v=XOcCOBe8PTc"
+ ]
+ },
+ "design/landing/materialdesign": {
+ "title": "",
+ "resources": [
+ "https://www.google.com/design/spec/animation/",
+ "https://www.google.com/design/spec/style/",
+ "https://www.google.com/design/spec/layout/",
+ "https://www.google.com/design/spec/components/",
+ "https://www.google.com/design/spec/patterns/",
+ "https://www.google.com/design/spec/usability/"
+ ]
+ },
+ "design/landing/pureandroid": {
+ "title": "",
+ "resources": [
+ "design/get-started/creative-vision.html",
+ "design/material/index.html",
+ "training/material/index.html",
+ "design/patterns/pure-android.html",
+ "design/patterns/new.html",
+ "design/devices.html"
+ ]
+ },
+ "design/landing/resources": {
+ "title": "",
+ "resources": [
+ "https://www.google.com/design/spec/resources/color-palettes.html",
+ "https://www.google.com/design/spec/resources/layout-templates.html",
+ "https://www.google.com/design/spec/resources/sticker-sheets-icons.html",
+ "https://www.google.com/design/spec/resources/roboto-noto-fonts.html",
+ "design/downloads/index.html#Wear"
+ ]
+ },
+ "develop/landing/mainlinks": {
+ "title": "",
+ "resources": [
+ "tools/studio/index.html",
+ "samples/new/index.html",
+ "tools/projects/templates.html"
+ ]
+ },
+ "develop/landing/latest": {
+ "title": "",
+ "resources": [
+ "http://android-developers.blogspot.com/2015/04/new-android-code-samples.html",
+ "http://android-developers.blogspot.com/2015/04/android-support-library-221.html",
+ "http://android-developers.blogspot.com/2015/03/a-new-reference-app-for-multi-device.html"
+ ]
+ },
+ "develop/landing/performance": {
+ "title": "",
+ "resources": [
+ "http://www.youtube.com/watch?v=fEEulSk1kNY",
+ "http://www.youtube.com/watch?v=-3ry8PxcJJA",
+ "http://www.youtube.com/watch?v=_kKTGK-Cb_4"
+ ]
+ },
+ "develop/landing/buildwithgoogle": {
+ "title": "",
+ "resources": [
+ ]
+ },
+ "develop/landing/devbytes": {
+ "title": "",
+ "resources": [
+ "http://www.youtube.com/watch?v=K2dodTXARqc",
+ "http://www.youtube.com/watch?v=FOn64iqlphk",
+ "http://www.youtube.com/watch?v=p4gmvHyuZzw",
+ "http://www.youtube.com/watch?v=tDmnGNkTtlE",
+ "http://www.youtube.com/watch?v=6K_jxccHv5M",
+ "http://www.youtube.com/watch?v=KNKGM4ss5Sc"
+ ]
+ },
+ "develop/landing/courses": {
+ "title": "",
+ "resources": [
+ ]
+ },
+ "distribute/landing/carousel": {
+ "title": "",
+ "resources": [
+ "http://www.youtube.com/watch?v=Pd49vTkvu0U",
+ "http://www.youtube.com/watch?v=ekxABqJeRBc",
+ "http://www.youtube.com/watch?v=MPnH7h12h0U",
+ "http://www.youtube.com/watch?v=700gYRkhkLM"
+ ]
+ },
+ "distribute/landing/googleplay": {
+ "title": "",
+ "resources": [
+ "distribute/googleplay/about.html",
+ "distribute/googleplay/developer-console.html",
+ "distribute/googleplay/index.html#opportunities"
+ ]
+ },
+ "distribute/landing/more": {
+ "title": "",
+ "resources": [
+ "distribute/users/promote-with-ads.html",
+ "distribute/monetize/ads.html",
+ "distribute/analyze/index.html",
+ "distribute/engage/deep-linking.html",
+ "distribute/engage/easy-signin.html",
+ "https://cloud.google.com/docs/"
+ ]
+ },
"distribute/edu/videos/stories": {
"title": "",
"resources": [
@@ -40,21 +167,20 @@ var RESOURCE_COLLECTIONS = {
"launch/static": {
"title": "",
"resources": [
- "distribute/googleplay/about.html",
- "distribute/googleplay/guide.html",
- "about/versions/lollipop.html",
- "distribute/googleplay/wear.html",
- "distribute/googleplay/tv.html",
- "distribute/googleplay/edu/about.html",
- "distribute/googleplay/families/about.html",
- "distribute/monetize/subscriptions.html",
+ "http://www.youtube.com/watch?v=1RIz-cmTQB4",
+ "http://www.youtube.com/watch?v=MVBMWDzyHAI",
+ "http://android-developers.blogspot.com/2013/11/app-translation-service-now-available.html",
+ "http://android-developers.blogspot.com/2013/10/more-visibility-for-tablet-apps-in.html",
+ "http://android-developers.blogspot.com/2013/11/bring-your-apps-into-classroom-with.html",
+ "distribute/essentials/quality/tablets.html",
+ "distribute/users/build-buzz.html",
+ "distribute/monetize/premium.html",
"distribute/monetize/freemium.html",
"distribute/monetize/ads.html",
- "distribute/users/promote-with-ads.html",
- "distribute/engage/deep-linking.html",
- "distribute/engage/game-services.html",
- "distribute/essentials/optimizing-your-app.html",
- "distribute/engage/easy-signin.html",
+ "distribute/essentials/best-practices/apps.html",
+ "distribute/essentials/best-practices/games.html",
+ "distribute/users/know-your-user.html",
+ "distribute/googleplay/developer-console.html"
]
},
"launch/static/ja": {
diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js
index f91550f..82ff029 100644
--- a/docs/html/jd_extras.js
+++ b/docs/html/jd_extras.js
@@ -99,6 +99,138 @@ DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([
"type":"video"
},
{
+ "title":"DesignBytes: Intro To Material Design",
+ "titleFriendly":"",
+ "summary":"These days, UI designers need to be thinking about phones, tablets, laptops, TVs, smartwatches, and beyond. In this DesignByte we talk about how Google designers have been working on making cross-platform and multi-screen design easier. We wanted to build a design system that felt at home on every screen, from the smallest watch to the largest TV.",
+ "url":"http://www.youtube.com/watch?v=p4gmvHyuZzw",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/p4gmvHyuZzw/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"DesignBytes: Paper and Ink: The Materials that Matter",
+ "titleFriendly":"",
+ "summary":"Join Rich Fulcher to learn about the materials of material design. See how virtual paper and ink form the foundation of your tactile user interface and master the rules that govern their behaviour.",
+ "url":"http://www.youtube.com/watch?v=YaG_ljfzeUw",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/YaG_ljfzeUw/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"DesignBytes: Material Design in the Google I/O App",
+ "titleFriendly":"",
+ "summary":"Roman Nurik shares details on the design process for the Google I/O 2014 app. To check out the app's source code, visit github.com/google/iosched.",
+ "url":"http://www.youtube.com/watch?v=XOcCOBe8PTc",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/XOcCOBe8PTc/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Battery Drain and Networking",
+ "titleFriendly":"",
+ "summary":"Let’s take a moment to make something insanely clear: As far as battery is concerned, NETWORKING is the biggest, baddest, dirtiest offender there is. And optimizing performance here isn’t easy. Since the chip isn’t always awake and draining power, means you can optimize how it wakes up, sends traffic, and saves battery.",
+ "url":"http://www.youtube.com/watch?v=fEEulSk1kNY",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/fEEulSk1kNY/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Batching Background Work Until Later",
+ "titleFriendly":"",
+ "summary":"Yes, your app is special. But when it comes to battery use, sometimes it’s better to be part of the crowd. Why not spread the battery blame around a bit? Ian Ni-Lewis shows you how ridiculously easy it is to go from battery hog to team player in this video.",
+ "url":"http://www.youtube.com/watch?v=-3ry8PxcJJA",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/-3ry8PxcJJA/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"The Performance Lifecycle",
+ "titleFriendly":"",
+ "summary":"Performance problems surface in your application at the least-wanted times (like right before you’re about to ship your first build). But don’t freak out: There’s a simple process that you can follow to help get your performance back under control.",
+ "url":"http://www.youtube.com/watch?v=_kKTGK-Cb_4",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/_kKTGK-Cb_4/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Introduction to Android Studio",
+ "titleFriendly":"",
+ "summary":"A high level introduction to Android Studio, the new IDE for Android application development. Learn why you should migrate your projects to Android Studio now and how it can help you be more productive as a developer. Rich layout editor, handy suggestions and fixes, new Android project view - these are just some of the things you can expect from the IDE, which is built on the successful IntelliJ IDEA.",
+ "url":"http://www.youtube.com/watch?v=K2dodTXARqc",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/K2dodTXARqc/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"DevBytes: Google Play Services 7.3",
+ "titleFriendly":"",
+ "summary":"Google Play Services 7.3 brings a ton of great new features to help you BUILD BETTER APPS! This update brings the ability to connect multiple wearables simultaneously to a single phone.",
+ "url":"http://www.youtube.com/watch?v=FOn64iqlphk",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/FOn64iqlphk/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Running a Successful Games Business with Google",
+ "titleFriendly":"",
+ "summary":"Sure, we all want to make the next great gaming masterpiece. But we also want to feed our families and/or dogs. Join Bob Meese from the Google Play team as he gives you some key pointers on how to make sure you're best taking advantage of Google Play and running a successful games business.",
+ "url":"http://www.youtube.com/watch?v=tDmnGNkTtlE",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/tDmnGNkTtlE/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Android TV: Introduction to Android TV",
+ "titleFriendly":"",
+ "summary":"Android TV brings the Android platform to the living room with rich content and entertaining app experiences. In this video, Timothy introduces the design philosophy and developer components that make building TV experiences easier than ever before.",
+ "url":"http://www.youtube.com/watch?v=6K_jxccHv5M",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/6K_jxccHv5M/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Under the Hood of Android Auto",
+ "titleFriendly":"",
+ "summary":"Your car contains some serious technology. Learn about the Android Auto architecture, which enables you to control Android apps and services running on your phone through your car. In this talk, we'll highlight the key characteristics of the Android Auto protocol, which enables your Android phone to talk to compatible cars. We'll also take a look at some of the details of the Android Auto rendering subsystem, which uses Binders and the Android VirtualDisplay API to composite UI from multiple Android apps. Finally, we'll discuss how we're enhancing the Google Maps app by integrating with the Android Auto platform.",
+ "url":"http://www.youtube.com/watch?v=KNKGM4ss5Sc",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ ],
+ "image":"http://i1.ytimg.com/vi/KNKGM4ss5Sc/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
"title":"Developer Registration",
"titleFriendly":"",
"summary":"Additional information about the registration process.",
@@ -1990,6 +2122,183 @@ DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([
"titleFriendly": ""
},
{
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/animation/",
+ "timestamp": null,
+ "image": "images/cards/material-animation_2x.png",
+ "title": "Animation",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/style/",
+ "timestamp": null,
+ "image": "images/cards/material-style_2x.jpg",
+ "title": "Style",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/layout/",
+ "timestamp": null,
+ "image": "images/cards/material-layout_2x.png",
+ "title": "Layout",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/components/",
+ "timestamp": null,
+ "image": "images/cards/material-components_2x.jpg",
+ "title": "Components",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/patterns/",
+ "timestamp": null,
+ "image": "images/cards/material-patterns_2x.png",
+ "title": "Patterns",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/usability/",
+ "timestamp": null,
+ "image": "images/cards/material-usability_2x.png",
+ "title": "Usability",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/resources/color-palettes.html",
+ "timestamp": null,
+ "image": "images/cards/material-color-palette_2x.jpg",
+ "title": "Color Palettes",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/resources/layout-templates.html",
+ "timestamp": null,
+ "image": "images/cards/material-layout-template_2x.jpg",
+ "title": "Layout Templates",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/resources/sticker-sheets-icons.html",
+ "timestamp": null,
+ "image": "images/cards/material-sticker-sheet_2x.jpg",
+ "title": "Sticker Sheets & Icons",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "lang": "en",
+ "group": "",
+ "tags": [],
+ "url": "https://www.google.com/design/spec/resources/roboto-noto-fonts.html",
+ "timestamp": null,
+ "image": "images/cards/material-typography_2x.jpg",
+ "title": "Typography: Roboto and Noto Sans fonts",
+ "summary": "",
+ "keywords": [],
+ "type": "design",
+ "titleFriendly": ""
+ },
+ {
+ "title":"Android Wear Materials",
+ "titleFriendly":"",
+ "summary":"You may use these materials without restriction to facilitate your app design and implementation. Drag and drop your way to beautifully designed Android apps. The stencils feature the rich typography, colors, interactive controls, and icons found throughout…",
+ "url":"design/downloads/index.html#Wear",
+ "group":"",
+ "keywords": ["icons","stencils","color swatches"],
+ "tags": ["icons","stencils","colorswatches"],
+ "image":"images/cards/android-wear-materials_2x.jpg",
+ "lang":"en",
+ "type":"design"
+ },
+ {
+ "tags": [
+ "android",
+ "developerstory",
+ "googleplay",
+ "featured"
+ ],
+ "title": "Android Developer Story: Jelly Button Games — Growing globally through data driven development",
+ "type": "youtube",
+ "url": "http://www.youtube.com/watch?v=Pd49vTkvu0U"
+ },
+ {
+ "title":"Scale with Google Cloud Platform",
+ "titleFriendly":"",
+ "summary":"With Google Cloud Platform, developers can build, test and deploy applications on Google's highly-scalable and reliable infrastructure for your web, mobile and backend solutions.",
+ "url":"https://cloud.google.com/docs/",
+ "group":"",
+ "keywords": [],
+ "tags": [],
+ "image":"images/cards/cloud-platform_2x.png",
+ "lang":"en",
+ "type":"distribute"
+ },
+ {
+ "title":"Opportunities & Programs",
+ "titleFriendly":"",
+ "summary":"This is a card body place holder text. This is a card body place holder text. This is a card body place holder text.",
+ "url":"distribute/googleplay/index.html#opportunities",
+ "group":"",
+ "keywords": [],
+ "tags": [],
+ "image":"images/cards/program-edu_2x.jpg",
+ "lang":"en",
+ "type":"distribute"
+ },
+ {
"lang": "ja",
"title": "Gaming Everywhere",
"titleFriendly": "",
@@ -2313,4 +2622,45 @@ DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([
"image": "distribute/images/advertising.jpg",
"type": "distribute"
}
-]); \ No newline at end of file
+]);
+
+var CAROUSEL_OVERRIDE = {
+ "about/versions/lollipop.html": {
+ "image": "images/home/hero-lollipop_2x.png",
+ "heroColor": "#263238",
+ "heroInvert": true,
+ "title": "Android 5.0 Lollipop",
+ "summary": "The Android 5.0 update adds a variety of new features for your apps, such as notifications on the lock screen, an all-new camera API, OpenGL ES 3.1, the new Material design interface, and much more."
+ },
+ "distribute/googleplay/families/about.html": {
+ "image": "images/distribute/hero-family.jpg",
+ "title": "Designed for Families",
+ "summary": "Introducing a new Google Play section to promote family friendly apps. Your apps in the program can benefit from enhanced discoverability in addition to maintaining their existing categories, rankings, and reviews elsewhere on the Google Play store."
+ },
+ "http://www.youtube.com/watch?v=Pd49vTkvu0U": {
+ "image": "images/distribute/hero-jelly-button.jpg",
+ "title": "How Jelly Button Games are growing globally through data",
+ "summary": "To really understand their users, Jelly Button Games analyses over 3 billion events each month using Google Analytics and Google BigQuery."
+ },
+ "http://www.youtube.com/watch?v=700gYRkhkLM": {
+ "image": "images/distribute/hero-outfit7.jpg",
+ "title": "Outfit7 — Building an entertainment company with Google",
+ "summary": "Outfit7, creators of My Talking Tom and My Talking Angela, offer a complete entertainment experience to users spanning mobile apps, user generated and original YouTube content, and a range of toys, clothing, and accessories...."
+ },
+ "http://www.youtube.com/watch?v=MPnH7h12h0U": {
+ "image": "images/distribute/hero-haystack.jpg",
+ "summary": "Haystack TV built a scalable business with six employees and Android TV. Two weeks was all it took for them to bring their mobile app to the big screen."
+ },
+ "http://www.youtube.com/watch?v=ekxABqJeRBc": {
+ "image": "images/distribute/hero-ginlemon.jpg",
+ "title": "How GinLemon is breaking through with Google Play",
+ "summary": "Meet Vincenzo Colucci, developer and founder of GinLemon, which started as a summer holiday joke and has now become a successful global app business on Google Play based in Manfredonia, southern Italy."
+ },
+ "distribute/googleplay/guide.html": {
+ "heroColor": "#fcb94e",
+ "image": "images/distribute/hero-g-play-guidebooks_2x.png",
+ "title": "Finding Success on Google Play",
+ "summary": "We’ve created a downloadable guide to help you find success with your app or game business on Google Play. In it, you’ll find features, tips, and best practices to help you build an effective strategy.",
+ "tags": []
+ }
+}; \ No newline at end of file
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
new file mode 100644
index 0000000..f72ffbb
--- /dev/null
+++ b/docs/html/preview/api-overview.jd
@@ -0,0 +1,120 @@
+page.title=API Overview
+excludeFromSuggestions=true
+sdk.platform.apiLevel=22
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document
+ <a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle">
+ <span class="more">show more</span>
+ <span class="less" style="display:none">show less</span></a></h2>
+
+<ol id="toc44" class="hide-nested">
+ <li><a href="#">Important Behavior Changes</a>
+ <ol>
+ <li><a href="#">change 1</a></li>
+ <li><a href="#">change 2</a></li>
+ </ol>
+ </li>
+ <li><a href="#">Feature Group 1</a>
+ <ol>
+ <li><a href="#">change 1</a></li>
+ <li><a href="#">change 2</a></li>
+ </ol>
+ </li>
+ <li><a href="#">Feature Group 2</a>
+ <ol>
+ <li><a href="#">change 1</a></li>
+ <li><a href="#">change 2</a></li>
+ </ol>
+ </li>
+</ol>
+
+</div>
+</div>
+
+<p>The M Developer Preview gives you an advance look at the upcoming release
+for the Android platform, which offers new features for users and app
+developers. This document provides an introduction to the most notable APIs.</p>
+
+<p>The M Developer Preview is intended for <strong>developer early
+adopters</strong> and <strong>testers</strong>. If you are interested in
+influencing the direction of the Android framework,
+<a href="{@docRoot}preview/setup-sdk.html">give the M Developer Preview a
+try</a> and send us your feedback!</p>
+
+<p class="caution"><strong>Caution:</strong> Do not not publish apps
+that use the M Developer Preview to the Google Play store.</p>
+
+<p class="note"><strong>Note:</strong> This document often refers to classes and
+methods that do not yet have reference material available on <a
+href="{@docRoot}">developer.android.com</a>. These API elements are
+formatted in {@code code style} in this document (without hyperlinks). For the
+preliminary API documentation for these elements, download the <a
+href="http://storage.googleapis.com/androiddevelopers/preview/l-developer-preview-reference.zip">preview
+reference</a>.</p>
+
+<h2 id="Behaviors">Important Behavior Changes</h2>
+
+<p>If you have previously published an app for Android, be aware that your app
+ might be affected by changes in the upcoming release.</p>
+
+<h3 id="id">Behavior Change 1</h3>
+
+<p>
+ Bacon ipsum dolor amet biltong picanha t-bone, jowl salami tri-tip jerky kielbasa sirloin boudin
+ porchetta fatback cow meatloaf capicola. Short ribs kielbasa pig drumstick rump boudin jowl chuck
+ beef ribs doner tenderloin biltong swine.
+</p>
+
+
+
+<h2 id="id">Feature Group 1</h2>
+
+<h3 id="id">Feature item 1</h3>
+
+<p>
+ Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
+ alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
+ jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
+ turducken. Tongue brisket ham shoulder:
+</p>
+
+<h3 id="id">Feature item 2</h3>
+
+<p>
+ Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
+ alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
+ jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
+ turducken. Tongue brisket ham shoulder:
+</p>
+
+<h2 id="id">Feature Group 2</h2>
+
+<h3 id="id">Feature item 1</h3>
+
+<p>
+ Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
+ alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
+ jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
+ turducken. Tongue brisket ham shoulder:
+</p>
+
+<h3 id="id">Feature item 2</h3>
+
+<p>
+ Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
+ alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
+ jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
+ turducken. Tongue brisket ham shoulder:
+</p>
+
+
+
+<p class="note">
+ For a detailed view of all API changes in the M Developer Preview, see the <a href=
+ "{@docRoot}preview/reference.html">API Differences Report</a>.
+</p> \ No newline at end of file
diff --git a/docs/html/preview/images/bugs.png b/docs/html/preview/images/bugs.png
new file mode 100644
index 0000000..46adf05
--- /dev/null
+++ b/docs/html/preview/images/bugs.png
Binary files differ
diff --git a/docs/html/preview/images/dev-prev.png b/docs/html/preview/images/dev-prev.png
new file mode 100644
index 0000000..eae6ede
--- /dev/null
+++ b/docs/html/preview/images/dev-prev.png
Binary files differ
diff --git a/docs/html/preview/images/updates.png b/docs/html/preview/images/updates.png
new file mode 100644
index 0000000..f165c5a
--- /dev/null
+++ b/docs/html/preview/images/updates.png
Binary files differ
diff --git a/docs/html/preview/index.html b/docs/html/preview/index.html
index 7cd029f..af99e2d 100644
--- a/docs/html/preview/index.html
+++ b/docs/html/preview/index.html
@@ -1,81 +1,23 @@
<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=970" />
-<meta name="Description" content="Test and build your apps against the next version of Android to ensure they're ready when the platform officially launches.">
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Android L Developer Preview | Android Developers</title>
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto+Condensed">
-<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold"
- title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-<script>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
- ga('create', 'UA-5831155-1', 'android.com');
- ga('create', 'UA-49880327-2', 'android.com', {'name': 'universal'}); // New tracker);
- ga('send', 'pageview');
- ga('universal.send', 'pageview'); // Send page view for new tracker.
-</script>
-</head>
-<body class="gc-documentation" itemscope="" itemtype="http://schema.org/Article">
-<a name="top"></a>
-<a name="download"></a>
-<div id="body-content">
-<div class="fullpage">
-<div id="jd-content">
- <div class="jd-descr" itemprop="articleBody">
-<style>
-body,html, #qv {background-color:#e9e9e9}
-#qv * { font-weight:bold;}
-.fullpage>#footer,
-#jd-content>.content-footer.wrap {
- display:none;
-}
-.content-footer {
- display: none;
-}
-</style>
- <div style="border-bottom: 1px solid #a5c43a; position: absolute; left: 0; right: 0; top: 0; z-index:99">
- <div class="wrap" style="position: relative; height: 45px; padding: 0 20px;">
- <a href="/index.html" style="position:absolute;top:8px">
- <img src="/assets/images/dac_logo.png" srcset="/assets/images/dac_logo@2x.png 2x" width="123" height="25" alt="Android Developers home page">
- </a>
- </div>
- </div>
@@ -89,7 +31,6 @@ body,html, #qv {background-color:#e9e9e9}
- <div class="landing-rest-of-page" style="position:relative;">
@@ -98,463 +39,299 @@ body,html, #qv {background-color:#e9e9e9}
- <div class="wrap" id="tos" style="display:none;padding-top:90px">
- <p class="sdk-terms-intro">Before downloading the Android Preview system image,
- you must agree to the following terms and conditions.</p>
- <h2 class="norule">Terms and Conditions</h2>
- <div class="sdk-terms" onfocus="this.blur()" style="width:100%">
-This is the Android SDK Preview License Agreement (the “License Agreement”).
-1. Introduction
-1.1 The Android SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the Preview.
-1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
-1.3 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
-2. Accepting the License Agreement
-2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement.
-2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement.
-2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview.
-2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the Preview on behalf of your employer or other entity.
-3. Preview License from Google
-3.1 Subject to the terms of the License Agreement, Google grants you a royalty-free, non-assignable, non-exclusive, non-sublicensable, limited, revocable license to use the Preview, personally or internally within your company or organization, solely to develop applications to run on the Android platform.
-3.2 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
-3.3 You may not use the Preview for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview.
-3.4 You agree that you will not take any actions that may cause or result in the fragmentation of Android, including but not limited to distributing, participating in the creation of, or promoting in any way a software development kit derived from the Preview.
-3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights.
-3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) to you or to users generally at Google's sole discretion, without prior notice to you.
-3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
-3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the Preview.
-4. Use of the Preview by You
-4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications.
-4.2 You agree to use the Preview and write applications only for purposes that are permitted by (a) the License Agreement, and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
-4.3 You agree that if you use the Preview to develop applications, you will protect the privacy and legal rights of users. If users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If users provide you with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, each user has given you permission to do so.
-4.4 You agree that you will not engage in any activity with the Preview, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of Google or any third party.
-4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
-4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
-4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released.
-5. Your Developer Credentials
-5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
-6. Privacy and Information
-6.1 In order to continually innovate and improve the Preview, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the Preview are being used and how they are being used. Before any of this information is collected, the Preview will notify you and seek your consent. If you withhold consent, the information will not be collected.
-6.2 The data collected is examined in the aggregate to improve the Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/.
-7. Third Party Applications
-7.1 If you use the Preview to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
-7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
-7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party.
-8. Using Google APIs
-8.1 Google APIs
-8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
-8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
-9. Terminating the License Agreement
-9.1 the License Agreement will continue to apply until terminated by either you or Google as set out below.
-9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the Preview and any relevant developer credentials.
-
-9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you.
-
-9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of:
-(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and
-(B) Google issues a final release version of the Android SDK.
-
-9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely.
-
-10. DISCLAIMERS
-
-10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
-
-10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE.
-
-10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-
-11. LIMITATION OF LIABILITY
-
-11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
-
-12. Indemnification
-
-12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys’ fees) arising out of or accruing from (a) your use of the Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement.
-
-13. Changes to the License Agreement
-
-13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available.
-
-14. General Legal Terms
-
-14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the Preview.
-
-14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+<html>
+<head>
-14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
-14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="viewport" content="width=970" />
-14.5 EXPORT RESTRICTIONS. THE PREVIEW IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+<meta name="Description" content="Test and build your apps against the next version of Android to ensure they're ready when the platform officially launches.">
+<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
+<title>Android M Developer Preview | Android Developers</title>
-14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google.
+<!-- STYLESHEETS -->
+<link rel="stylesheet"
+href="//fonts.googleapis.com/css?family=Roboto+Condensed">
+<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold"
+ title="roboto">
+<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
- </div><!-- sdk terms -->
+<!-- JAVASCRIPT -->
+<script src="//www.google.com/jsapi" type="text/javascript"></script>
+<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
+<script type="text/javascript">
+ var toRoot = "/";
+ var metaTags = [];
+ var devsite = false;
+</script>
+<script src="/assets/js/docs.js" type="text/javascript"></script>
- <div id="sdk-terms-form">
- <p>
- <input id="agree" type="checkbox" name="agree" value="1" onclick="onAgreeChecked()" />
- <label id="agreeLabel" for="agree">I have read and agree with the above terms and conditions</label>
- </p>
- <p><a href="" class="button disabled" id="downloadForRealz" onclick="return onDownloadForRealz(this);"></a></p>
- </div>
+<script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ ga('create', 'UA-5831155-1', 'android.com');
+ ga('create', 'UA-49880327-2', 'android.com', {'name': 'universal'}); // New tracker);
+ ga('send', 'pageview');
+ ga('universal.send', 'pageview'); // Send page view for new tracker.
+</script>
- </div><!-- end TOS -->
+</head>
+<body class="gc-documentation
+" itemscope itemtype="http://schema.org/Article">
+<a name="top"></a>
+<div id="body-content">
+<div class="fullpage" >
+<div id="jd-content">
+ <div class="jd-descr" itemprop="articleBody">
+ <style>
+.fullpage>#footer,
+#jd-content>.content-footer.wrap {
+ display:none;
+}
+</style>
+<style>
+#footer {
+ display: none;
+}
+.content-footer {
+ display: none;
+}
+</style>
+<!--
+<div style="height:20px"></div>
+<div id="butterbar-wrapper">
+ <div id="butterbar">
+ <a href="#" id="butterbar-message">
+ butterbar message
+ </a>
+ </div>
+</div>
+-->
+
+ <div class="landing-rest-of-page">
+ <div class="landing-section" style="padding-top:60px">
+ <div class="wrap">
+ <div class="landing-section-header">
+ <div class="landing-h1">Android M Developer Preview</div>
+ <div class="landing-subhead">
+ Get an early look at the next release and prepare your apps for the
+ official platform launch.
+ </div>
- <div class="landing-section" id="landing-wrapper" style="padding:55px 10px 0">
- <div class="landing-section-header" style="margin:0">
- <div class="landing-h1">Android L Developer Preview</div>
- <div class="landing-subhead" style="padding-bottom:40px">
- Final APIs now available!
+ <img src="/preview/images/dev-prev.png" style=" margin:0px 0 0 40px" width="860px"/>
+ <div class="col-6" style="margin-left:660px; margin-top:-105px">
+ <a href="/preview/setup-sdk.html" class="landing-button landing-primary"
+ style="position:absolute;z-index:100;float:right;margin-top: 0px;">
+ Get Started</a>
</div>
</div>
- <div class="wrap" style="padding:20px; position:relative">
-
- <img src="/images/home/l-hero_2x.png"
- srcset="/images/home/l-hero.png 1x, /images/home/l-hero_2x.png 2x"
- style=" margin:-5px -30px 0 0;float:right" alt="" width="510">
-
- <a href="/about/versions/android-5.0.html" class="landing-button landing-primary"
- style="position:absolute;z-index:100;right:215px;top:375px">Android 5.0 API Overview</a>
-
- <div style="width:440px">
-<p>Android 5.0 (Lollipop) is now out of preview and available to users.</p>
-
-<p>If you previously developed apps with the L Developer Preview, be aware that various APIs and
-behaviors have changed, so you should update your SDK now to test your apps and take advantage of
-new features in Android 5.0.</p>
-
-
- <p>To get the latest Android 5.0 SDK:</p>
- <ol>
- <li>Start the <a href="/tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
- <li>In the <b>Tools</b> section, select the latest <b>SDK Tools</b>,
- <b>SDK Platform-tools</b>, and <b>SDK Build-tools</b>.</li>
- <!-- Android L not yet showing up in Android SDK Manager... -->
- <li>Select everything under the <b>Android 5.0</b> section, then
- click <b>Install packages...</b></li>
- <li>Accept the licensing agreement for the packages, then click
- <b>Install</b>.</li>
- <li>If you previously installed the Android L Preview SDK, select all those
- packages in the SDK Manager and click <strong>Delete packages</strong>.
- </ol>
- <p>Now you're ready to develop and test on Android 5.0 with your normal workflow
- and begin publishing app updates to Google Play.
- </div>
-
- <h2 id="Start" class="norule" style="margin:60px 0 0 0">Get Started on Android 5.0</h2>
</div> <!-- end .wrap -->
+ </div> <!-- end .landing-section -->
- <div class="wrap" style="background-color:#fff;padding:20px;position:relative">
-
- <div id="qv-wrapper">
- <div id="qv">
- <h2>More about Android 5.0</h2>
- <ul>
- <li><a href="http://android-developers.blogspot.com/">Android 5.0 announcement</a></li>
- <li><a href="/about/versions/android-5.0.html">Android 5.0 API Overview</a></li>
- <li><a href="/sdk/api_diff/21/changes.html">Android 5.0 API Diff Report</a></li>
- <li><a href="/samples/new/index.html">Android 5.0 API Samples</a></li>
- </ul>
- </div>
+ <div class="landing-section landing-gray-background"
+ style="margin-top:-105px; padding-bottom:20px">
+ <div class="wrap">
+ <div class="cols">
+ <div class="landing-body" style="margin-top:-80px" >
+
+ <div class="landing-breakout cols">
+ <div class="col-4">
+ <p>This Feature</p>
+ <p class="landing-small">
+ Kevin ham hock pig cupim brisket picanha, doner pork tri-tip frankfurter
+ leberkas turkey.
+ </p>
+ <p class="landing-small">
+ <a href="/preview/api-overview.html">Learn about this feature</a>
+ </p>
+ </div>
+ <div class="col-4">
+ <p>That Feature</p>
+ <p class="landing-small">
+ Bacon ipsum dolor amet meatball tongue pork loin fatback, andouille shoulder
+ chicken picanha pig landjaeger kielbasa shankle pastrami flank meatloaf.
+ </p>
+ <p class="landing-small">
+ <a href="/preview/api-overview.html">Learn about that feature</a>
+ </p>
+ </div>
+ <div class="col-4">
+ <p style="width:230px">Another Feature</p>
+ <p class="landing-small">
+ Landjaeger tri-tip tenderloin pork loin jowl, meatloaf t-bone kielbasa sausage
+ swine spare ribs drumstick corned beef ham.
+ </p>
+ <p class="landing-small">
+ <a href="/preview/api-overview.html">Learn about notifications</a>
+ </p>
+ </div>
+ <div class="col-4">
+ <p>Moar Features</p>
+ <p class="landing-small">
+ <b>Feature Name</b> is our effort to meatloaf boudin meatball sausage strip
+ steak hamburger, chuck ham pork chop.
+ </p>
+ <p class="landing-small">
+ <a href="/preview/api-overview.html">Learn about moar feature</a>
+ </p>
+ </div>
+ </div>
+ <p style="margin-left:20px">See the <a href="/preview/api-overview.html">API
+ overview</a> for more information on the rest of the new and updated features.</p>
+ </div>
+ </div></div></div>
+ <div class="landing-section">
+ <div class="wrap">
+ <div class="cols">
+ <div class="landing-body">
+ <div class="col-3-wide">
+ <a target="_blank" href="https://code.google.com/p/android-developer-preview/">
+ <img class="landing-social-image" src="/preview/images/bugs.png" alt="">
+ </a>
+ <div class="landing-social-copy">
+ <p>Issue Tracker</p>
+ <p class="landing-small">
+ Let us know when you encounter problems, so we can fix them and make
+ the platform better for you and your users.
+ </p><p class="landing-small">
+ <a href="https://code.google.com/p/android-developer-preview/">
+ Report Issues</a>
+ </p>
+ <p></p>
+ </div>
+ </div>
+ <div class="col-3-wide">
+ <a target="_blank" href="http://g.co/androidldevpreview">
+ <img class="landing-social-image" src="//www.google.com/images/icons/product/gplus-128.png" alt="">
+ </a>
+ <div class="landing-social-copy">
+ <p>Google+ </p>
+ <p class="landing-small">
+ Join the community of Android developers testing out the M Developer Preview and
+ share your thoughts and experiences.
+ </p><p class="landing-small">
+ <a href="http://g.co/androidldevpreview">
+ Discuss on Google+</a>
+ </p>
+ </div>
+ </div>
+ <div class="col-3-wide">
+ <a target="_blank" href="/preview/support.html">
+ <img class="landing-social-image" src="/preview/images/updates.png" alt="">
+ </a>
+ <div class="landing-social-copy">
+ <p>Support and Updates</p>
+ <p class="landing-small">
+ Updates to the preview are delivered
+ in the Android SDK Manager. Check back periodically
+ for news about the changes.
+ </p>
+ <p class="landing-small">
+ <a href="/preview/support.html">Get Support</a>
+ </p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
- <p>Now that Android 5.0 APIs are final:</p>
- <ul>
- <li>The API level for Android 5.0 is 21, so be sure to update your
- app's manifest file to set <a href="/guide/topics/manifest/uses-sdk-element.html#target"
- ><code>targetSdkVersion</code></a> to
- <code>"21"</code> when you begin testing:
- <pre>&lt;uses-sdk android:targetSdkVersion="21" ... /></pre>
- </li>
- <li>Google Play now accepts APKs with <a
- href="/guide/topics/manifest/uses-sdk-element.html#min"><code>minSdkVersion</code></a> or
- <a href="/guide/topics/manifest/uses-sdk-element.html#target"
- ><code>targetSdkVersion</code></a> set
- to <code>"21"</code>, so you can upload your updated apps today.</li>
- </ul>
-
- <p>If you previously flashed your Nexus 5 or Nexus 7 with a preview system image, you should
- now update your device to the final factory system image.
- Download the appropriate image from
- <a href="http://developers.google.com/android/nexus/images">Factory Images for Nexus
- Devices</a> and follow the flashing instructions on that page.</p>
-
- </div> <!-- end .wrap -->
-
-
-
-
-
-
-
-
- <div class="wrap" style="padding:20px; position:relative">
- <h2 id="Material" class="norule" style="margin:40px 0 0 0">Design with Material</h2>
- </div>
-
- <div class="wrap" style="background-color:#fff;padding:20px;position:relative">
- <img src="images/material-layers.png" width="240"
- style="position:absolute;right:20px;top:-50px">
-
- <div id="qv-wrapper" style="margin-top:120px">
- <div id="qv">
-
- <h2>More about Material Design</h2>
- <ul>
- <li><a href="http://www.google.com/design/spec/material-design/introduction.html">Material
- Design Spec</a></li>
- <li><a href="/design/material/index.html">Android Material Design</a></li>
- <li><a href="/training/material/index.html">Creating Apps with Material Design</a>
- </ul>
+ <div class="content-footer wrap" itemscope="" itemtype="http://schema.org/SiteNavigationElement">
+ <div class="layout-content-col col-16" style="padding-top:4px">
+ <style>#___plusone_0 {float:right !important;}</style>
+ <div class="g-plusone" data-size="medium"></div>
</div>
- </div>
-
-
-<p>Material design is a complete design philosophy for visual, motion, and interaction design
-across platforms and devices. The <a href=
-"http://www.google.com/design/spec/material-design/introduction.html">material design specification
-(preview)</a> provides all the details for designers.</p>
-
-
- <p>To get started with Material design in your Android app, update
- your <a href="/guide/topics/manifest/uses-sdk-element.html#target"
- ><code>targetSdkVersion</code></a> to <code>"21"</code> and apply the new
- <a href="/reference/android/R.style.html#Theme_Material"
- ><code>Material</code></a> theme. For example, when creating
- a <a href="/guide/topics/ui/themes.html">custom theme</a>
- for your app, open your project's <code>res/values/styles.xml</code> file
- and extend the <a href="/reference/android/R.style.html#Theme_Material"
- ><code>Material</code></a> theme:</p>
-<pre>
-&lt;resources>
- &lt;style name="AppTheme" parent="android:Theme.Material">
- &lt;!-- Customize the Material elements here -->
- &lt;/style>
-&lt;/resources>
-</pre>
-<p>Then apply your custom theme to your application in the manifest file:</p>
-<pre>
-&lt;application android:theme="&#64;style/AppTheme">
-</pre>
-<p>Material design is more than just the UI theme, though. It's also about the way the app
- behaves&mdash;how elements move and transform when the user interacts with them. So Android 5.0
- and the <a href="/tools/support-library/features.html#v7">v7 support library</a> provide new
- widgets and animation APIs that allow you to
- build interaction patterns described in the
- <a href="http://www.google.com/design/spec/material-design/introduction.html">Material design
- specification</a>.</p>
-
-<p>All the Material design elements and interaction patterns provided by the UI styles and widgets
-are flexible, so you can adopt only what's appropriate for your app and retain a unique identity
-and experience for your product.</p>
-
-<p>And Material design on Android isn't just for Android 5.0. The
- <a href="/tools/support-library/features.html#v7">v7 support library</a> has been significantly
- updated in revision 21 to make many of the Material design elements available when
- running on older versions of the platform.</p>
-
-<p>For many more details about how to implement the Material look and feel,
- see <a href="/training/material/index.html">Creating Apps with Material
- Design</a>.</p>
-
-
- </div>
-
-
-
-
-
-
-
-
-
-
-
- <div class="wrap" style="padding:20px; position:relative">
- <h2 id="TV" class="norule" style="margin:40px 0 0 0">Build for Android TV</h2>
- </div>
-
- <div class="wrap" style="background-color:#fff;padding:20px;position:relative">
- <img src="/tv/images/components.png" width="240"
- style="position:absolute;right:20px;top:-50px">
-
- <div id="qv-wrapper" style="margin-top:120px">
- <div id="qv">
-
- <h2>More about Android TV</h2>
- <ul>
- <li><a href="/design/tv/index.html">Android TV Design</a></li>
- <li><a href="/training/tv/start/index.html">Building Apps for Android TV</a></li>
- <li><a href="/training/tv/games/index.html">Building TV Games</a></li>
- <li><a href="/training/tv/playback/index.html">Building TV Playback Apps</a></li>
- <li><a href="/distribute/essentials/quality/tv.html">TV App Quality</a></li>
- </ul>
- </div>
- </div>
-
-<p>Android 5.0 provides a new platform for users to experience your app on a big screen. The
-Android TV experience is centered around a simplified home screen that allows users to discover
-your app's content with personalized recommendations and voice search, or select your app to launch
-into your fullscreen experience.</p>
-
-
-<p>Making your app available on Android TV does not require that you build an entirely new app.
-Android TV is simply another form factor for the Android platform, so you can deliver the same APK
-that you provide for phones and tablets to TVs through Google Play. However, to make your app
-available on Android TV, you'll need to make some optimizations such as adding layouts
-for the big screen and adding support for remote control input. For more information about design
-guidelines, see <a href="/distribute/essentials/quality/tv.html">TV App Quality</a>.</p>
-
-<p class="note"><strong>Note:</strong> Google Play for Android TV will officially
-open for apps on November 3.</p>
-
-<p>Android TV is also great new opportunity for Android games. If you'd like to make your games
-available on Android TV, be sure to optimize the user experience for the big screen by following
-the recommendations in <a href="/training/tv/games/index.html">Building TV Games</a>.</p>
-
-
- <p>To get started on Android TV, you need:</p>
- <ul>
- <li>The Android 5.0 SDK packages from the
- <a href="/tools/help/sdk-manager.html">Android SDK Manager</a>,
- including the <strong>Android TV System Image</strong> so you can create an
- Android TV emulator.</li>
- <li>An activity that's launchable from the Android TV home screen. This requires that you
- add the <a href="/reference/android/content/Intent.html#CATEGORY_LEANBACK_LAUNCHER"
- ><code>LEANBACK_LAUNCHER</code></a> category to one of your activities. For example:
-<pre>
-&lt;activity ... >
- &lt;intent-filter>
- &lt;action android:name="android.intent.action.MAIN" />
- &lt;category android:name="android.intent.category.LEANBACK_LAUNCHER" />
- &lt;/intent-filter>
-&lt;/activity>
-</pre>
- </li>
-
- <li>For a set of default styles that optimize your UI for the TV's
- <em>leanback user experience</em>,
- you should also apply the <a
- href="/reference/android/support/v17/leanback/R.style.html#Theme_Leanback"
- ><code>Leanback</code></a> theme to your activity:
-<pre>
-&lt;activity android:theme="@style/Theme.Leanback" ... >
-</pre>
- </li>
-
- </ul>
- <p>You should also take advantage of the <a
- href="/tools/support-library/features.html#v17-leanback">v17 leanback library</a>, which
- provides the <a href="/reference/android/support/v17/leanback/R.style.html#Theme_Leanback"
- ><code>Leanback</code></a> theme shown above, plus several widgets designed to
- make your UI beautiful and easy to navigate on the big screen, such as a widget that creates
- a set of large horizontal card views.</p>
-
- <p>For more information about setting up a project for your TV app, building
- TV layouts, and handling controller input,
- see <a href="/training/tv/start/index.html">Building
- TV Apps</a>.</p>
- </div>
-
-
-
-
-
-
-
-
- </div> <!-- end .landing-section -->
-
-
-
-
-
-
-
-
- <!-- spacer -->
- <div class="wrap" style="padding:20px; position:relative">
- <p>&nbsp;</p>
</div>
-
-
-
- <div id="footer" class="wrap" style="width:940px;position:relative;">
+ <div id="footer" class="wrap" style="width:940px;position:relative;top:-35px;z-index:-1">
<div id="copyright">
Except as noted, this content is
licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="https://developer.android.com/license.html">Content
+ restrictions, see the <a href="/license.html">Content
License</a>.
</div>
</div>
</div> <!-- end landing-body-content -->
+ <script>
+ $("a.landing-down-arrow").on("click", function(e) {
+ $("body").animate({
+ scrollTop: $(".preview-hero").height() + 76
+ }, 1000, "easeOutQuint");
+ e.preventDefault();
+ });
+ </script>
</div>
- <div class="content-footer wrap" itemscope=""
- itemtype="http://schema.org/SiteNavigationElement">
+ <div class="content-footer wrap"
+ itemscope itemtype="http://schema.org/SiteNavigationElement">
<div class="paging-links layout-content-col col-10">
</div>
+ <div class="layout-content-col plus-container col-2" >
+ <style>#___plusone_0 {float:right !important;}</style>
+ <div class="g-plusone" data-size="medium"></div>
+
+ </div>
</div>
@@ -571,7 +348,7 @@ the recommendations in <a href="/training/tv/games/index.html">Building TV Games
Except as noted, this content is
licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="https://developer.android.com/license.html">Content
+ restrictions, see the <a href="/license.html">Content
License</a>.
</div>
@@ -582,50 +359,14 @@ the recommendations in <a href="/training/tv/games/index.html">Building TV Games
</div> <!-- end body-content -->
-<script>
- var urlRoot = "http://storage.googleapis.com/androiddevelopers/finalpreview/";
- function onDownload(link) {
-
- $("#downloadForRealz").html("Download " + $(link).text());
- $("#downloadForRealz").attr('href', urlRoot + $(link).text());
-
- $("#tos").show();
- $("#landing-wrapper").hide();
-
- return true;
- }
-
-
- function onAgreeChecked() {
- /* verify that the TOS is agreed */
- if ($("input#agree").is(":checked")) {
- /* reveal the download button */
- $("a#downloadForRealz").removeClass('disabled');
- } else {
- $("a#downloadForRealz").addClass('disabled');
- }
- }
-
- function onDownloadForRealz(link) {
- if ($("input#agree").is(':checked')) {
- $("#tos").fadeOut('fast');
- $("#landing-wrapper").fadeIn('fast');
- ga('send', 'event', 'L Preview', 'System Image', $("#downloadForRealz").html());
- location.hash = "";
- // reset the checkbox for future downloads
- $("#agree").trigger('click');
- $("a#downloadForRealz").addClass('disabled');
- return true;
- } else {
- $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200,
- function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)}
- );
- return false;
- }
- }
-</script>
+ <script src="https://developer.android.com/ytblogger_lists_unified.js" type="text/javascript"></script>
+ <script src="/jd_lists_unified.js" type="text/javascript"></script>
+ <script src="/jd_extras.js" type="text/javascript"></script>
+ <script src="/jd_collections.js" type="text/javascript"></script>
+ <script src="/jd_tag_helpers.js" type="text/javascript"></script>
+
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/html/preview/license.jd b/docs/html/preview/license.jd
new file mode 100644
index 0000000..5ff52ba
--- /dev/null
+++ b/docs/html/preview/license.jd
@@ -0,0 +1,143 @@
+page.title=License Agreement
+
+@jd:body
+
+<p>
+To get started with the Android SDK Preview, you must agree to the following terms and conditions.
+As described below, please note that this is a preview version of the Android SDK, subject to change, that you use at your own risk. The Android SDK Preview is not a stable release, and may contain errors and defects that can result in serious damage to your computer systems, devices and data.
+</p>
+
+<p>
+This is the Android SDK Preview License Agreement (the “License Agreement”).
+</p>
+<div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
+1. Introduction
+
+1.1 The Android SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the Preview.
+
+1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
+
+1.3 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
+
+2. Accepting the License Agreement
+
+2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement.
+
+2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement.
+
+2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview.
+
+2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the Preview on behalf of your employer or other entity.
+
+3. Preview License from Google
+
+3.1 Subject to the terms of the License Agreement, Google grants you a royalty-free, non-assignable, non-exclusive, non-sublicensable, limited, revocable license to use the Preview, personally or internally within your company or organization, solely to develop applications to run on the Android platform.
+
+3.2 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+
+3.3 You may not use the Preview for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview.
+
+3.4 You agree that you will not take any actions that may cause or result in the fragmentation of Android, including but not limited to distributing, participating in the creation of, or promoting in any way a software development kit derived from the Preview.
+
+3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights.
+
+3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) to you or to users generally at Google's sole discretion, without prior notice to you.
+
+3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
+
+3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the Preview.
+
+4. Use of the Preview by You
+
+4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications.
+
+4.2 You agree to use the Preview and write applications only for purposes that are permitted by (a) the License Agreement, and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
+
+4.3 You agree that if you use the Preview to develop applications, you will protect the privacy and legal rights of users. If users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If users provide you with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, each user has given you permission to do so.
+
+4.4 You agree that you will not engage in any activity with the Preview, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of Google or any third party.
+
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
+
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
+
+4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released.
+
+5. Your Developer Credentials
+
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
+
+6. Privacy and Information
+
+6.1 In order to continually innovate and improve the Preview, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the Preview are being used and how they are being used. Before any of this information is collected, the Preview will notify you and seek your consent. If you withhold consent, the information will not be collected.
+
+6.2 The data collected is examined in the aggregate to improve the Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/.
+
+7. Third Party Applications
+
+7.1 If you use the Preview to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
+
+7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
+
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party.
+
+8. Using Google APIs
+
+8.1 Google APIs
+
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
+
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
+
+9. Terminating the License Agreement
+
+9.1 the License Agreement will continue to apply until terminated by either you or Google as set out below.
+
+9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the Preview and any relevant developer credentials.
+
+9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you.
+
+9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of:
+(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and
+(B) Google issues a final release version of the Android SDK.
+
+9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely.
+
+10. DISCLAIMERS
+
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+
+10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE.
+
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+
+11. LIMITATION OF LIABILITY
+
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+
+12. Indemnification
+
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys’ fees) arising out of or accruing from (a) your use of the Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement.
+
+13. Changes to the License Agreement
+
+13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available.
+
+14. General Legal Terms
+
+14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the Preview.
+
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
+
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
+
+14.5 EXPORT RESTRICTIONS. THE PREVIEW IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+
+14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google.
+
+14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+
+
+</div> \ No newline at end of file
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
new file mode 100644
index 0000000..bea4914
--- /dev/null
+++ b/docs/html/preview/preview_toc.cs
@@ -0,0 +1,37 @@
+<ul id="nav">
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/setup-sdk.html">
+ Set up the SDK</a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/api-overview.html">
+ API Overview</a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/samples.html">
+ Samples</a></div>
+ </li>
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/reference.html">
+ Reference</a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/support.html">
+ Support</a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/license.html">
+ License Agreement</a></div>
+ </li>
+
+ <li class="nav-section" style="margin: 20px 0 0 -10px;">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>index.html" class="back-link">
+ Developer Home</a></div>
+ </li>
+
+</ul>
diff --git a/docs/html/preview/reference.jd b/docs/html/preview/reference.jd
new file mode 100644
index 0000000..ee1f24d
--- /dev/null
+++ b/docs/html/preview/reference.jd
@@ -0,0 +1,15 @@
+page.title=Reference
+
+@jd:body
+
+<p>
+ The reference documentation and API difference report for the Developer Preview are available in
+ this downloadable package.
+</p>
+
+<ul>
+ <li>
+ <a href="http://storage.googleapis.com/androiddevelopers/preview/l-developer-preview-reference.zip">
+ M Developer Preview reference</a>
+ </li>
+</ul> \ No newline at end of file
diff --git a/docs/html/preview/samples.jd b/docs/html/preview/samples.jd
new file mode 100644
index 0000000..fb80e30
--- /dev/null
+++ b/docs/html/preview/samples.jd
@@ -0,0 +1,37 @@
+page.title=Samples
+
+@jd:body
+
+<p>
+ The following code samples are provided for the M Developer Preview. You can download them in the
+ Android SDK Manager under the <b>SDK Samples</b> component for the M Developer Preview.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> These downloadable projects are designed
+ for use with Gradle and Android Studio.
+</p>
+
+
+<h3 id="id">Sample 1</h3>
+
+<p>
+ This sample demonstrates how to turducken frankfurter boudin, ham brisket alcatra kielbasa pork
+ loin pork. Jowl kielbasa kevin, sausage landjaeger corned beef cow spare ribs pastrami leberkas
+ drumstick.
+</p>
+
+<p><a href="#">Get it on GitHub</a></p>
+
+
+<h3 id="id">Sample 2</h3>
+
+<p>
+ This sample demonstrates how to turducken frankfurter boudin, ham brisket alcatra kielbasa pork
+ loin pork. Jowl kielbasa kevin, sausage landjaeger corned beef cow spare ribs pastrami leberkas
+ drumstick.
+</p>
+
+<p><a href="#">Get it on GitHub</a></p>
+
+
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
new file mode 100644
index 0000000..11b009e
--- /dev/null
+++ b/docs/html/preview/setup-sdk.jd
@@ -0,0 +1,361 @@
+page.title=Setting Up the Preview SDK
+@jd:body
+
+
+
+
+
+
+
+<div style="position:relative; min-height:600px">
+
+ <div class="wrap" id="tos" style="position:absolute;display:none;width:inherit;">
+
+ <p class="sdk-terms-intro">Before installing the Android SDK, you must agree to the following terms and conditions.</p>
+
+ <h2 class="norule">Terms and Conditions</h2>
+ <div class="sdk-terms" onfocus="this.blur()" style="width:678px">
+This is the Android SDK Preview License Agreement (the “License Agreement”).
+
+1. Introduction
+
+1.1 The Android SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the Preview.
+
+1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
+
+1.3 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
+
+2. Accepting the License Agreement
+
+2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement.
+
+2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement.
+
+2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview.
+
+2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the Preview on behalf of your employer or other entity.
+
+3. Preview License from Google
+
+3.1 Subject to the terms of the License Agreement, Google grants you a royalty-free, non-assignable, non-exclusive, non-sublicensable, limited, revocable license to use the Preview, personally or internally within your company or organization, solely to develop applications to run on the Android platform.
+
+3.2 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+
+3.3 You may not use the Preview for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview.
+
+3.4 You agree that you will not take any actions that may cause or result in the fragmentation of Android, including but not limited to distributing, participating in the creation of, or promoting in any way a software development kit derived from the Preview.
+
+3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights.
+
+3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) to you or to users generally at Google's sole discretion, without prior notice to you.
+
+3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
+
+3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the Preview.
+
+4. Use of the Preview by You
+
+4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications.
+
+4.2 You agree to use the Preview and write applications only for purposes that are permitted by (a) the License Agreement, and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
+
+4.3 You agree that if you use the Preview to develop applications, you will protect the privacy and legal rights of users. If users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If users provide you with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, each user has given you permission to do so.
+
+4.4 You agree that you will not engage in any activity with the Preview, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of Google or any third party.
+
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
+
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
+
+4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released.
+
+5. Your Developer Credentials
+
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
+
+6. Privacy and Information
+
+6.1 In order to continually innovate and improve the Preview, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the Preview are being used and how they are being used. Before any of this information is collected, the Preview will notify you and seek your consent. If you withhold consent, the information will not be collected.
+
+6.2 The data collected is examined in the aggregate to improve the Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/.
+
+7. Third Party Applications
+
+7.1 If you use the Preview to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
+
+7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
+
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party.
+
+8. Using Google APIs
+
+8.1 Google APIs
+
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
+
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
+
+9. Terminating the License Agreement
+
+9.1 the License Agreement will continue to apply until terminated by either you or Google as set out below.
+
+9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the Preview and any relevant developer credentials.
+
+9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you.
+
+9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of:
+(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and
+(B) Google issues a final release version of the Android SDK.
+
+9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely.
+
+10. DISCLAIMERS
+
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+
+10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE.
+
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+
+11. LIMITATION OF LIABILITY
+
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+
+12. Indemnification
+
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys’ fees) arising out of or accruing from (a) your use of the Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement.
+
+13. Changes to the License Agreement
+
+13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available.
+
+14. General Legal Terms
+
+14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the Preview.
+
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
+
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
+
+14.5 EXPORT RESTRICTIONS. THE PREVIEW IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+
+14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google.
+
+14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+ </div><!-- sdk terms -->
+
+
+
+ <div id="sdk-terms-form">
+ <p>
+ <input id="agree" type="checkbox" name="agree" value="1" onclick="onAgreeChecked()" />
+ <label id="agreeLabel" for="agree">I have read and agree with the above terms and conditions</label>
+ </p>
+ <p><a href="" class="button disabled" id="downloadForRealz" onclick="return onDownloadForRealz(this);"></a></p>
+ </div>
+
+
+ </div><!-- end TOS -->
+
+
+
+
+
+
+
+
+
+ <div id="landing">
+
+<p>The Preview SDK is available from the Android SDK Manager.
+This document assumes that you are familiar with Android app development, such
+as using the Android SDK Manager and creating projects. If you're new to
+Android, see <a href="{@docRoot}training/basics/firstapp/index.html">Building Your First
+App</a> training lesson first.</a></p>
+
+<h2 id="downloadSdk">Download the SDK</h2>
+
+<ol>
+ <li>Start the <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
+ <li>In the <b>Tools</b> section, select the latest Android <b>SDK Tools</b>,
+ <b>Platform-tools</b>, and <b>Build-tools</b>.</li>
+ <li>Select everything under the <b>Android M Developer Preview</b> section and
+ click <b>Install packages...</b></li>
+ <li>Accept the Licensing Agreement for all of the packages and click
+ <b>Install</b>.</li>
+</ol>
+
+<p class="note"><strong>Note:</strong> The Eclipse ADT plug-in requires Java 7
+ if your compilation target is the M Developer Preview.</p>
+
+<h2 id="setupHardware">Set Up Hardware and AVDs</h2>
+
+<p>The Android M Developer Preview provides you with 32-bit system images
+to flash the following devices:
+</p>
+
+<ul>
+ <li>Nexus 5</li>
+ <li>Nexus 7 Wi-Fi (version 2, released in 2013)</li>
+</ul>
+
+<p>In addition, you also get the emulator system images, which includes
+experimental 64-bit system images along with standard 32-bit system images.
+</p>
+
+<p class="note"><strong>Note:</strong> The 64-bit system images require the
+Intel x86 Emulator Accelerator (HAXM) Rev.5 which can be downloaded from the
+<a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> <em>Extras</em>
+folder.</p>
+
+
+<h3 id="installImage">Install the M Preview System Image</h3>
+
+<p class="warning"><b>Warning:</b> This is a preview version of the Android
+system image, and is subject to change. Your use of this system image is
+governed by the Android SDK Preview License Agreement. The Android preview
+system image is not a stable release, and may contain errors and defects that
+can result in damage to your computer systems, devices, and data. The preview
+Android system image is not subject to the same testing as the factory OS and
+can cause your phone and installed services and applications to stop working.
+</p>
+
+
+<ol>
+ <li>Download and uncompress the Android Developer Preview package.
+ <table style="width:860px">
+ <tr>
+ <th scope="col">Device</th>
+ <th scope="col">Download</th>
+ <th scope="col">Checksum</th>
+ </tr>
+ <tr id="hammerhead">
+ <td>Nexus 5 (GSM/LTE) <br>"hammerhead"</td>
+ <td><a href="#top" onclick="onDownload(this)"
+ >hammerhead-lpv79-preview-ac1d8a8e.tgz</a></td>
+ <td>MD5: <code>5a6ae77217978cb7b958a240c2e80b57</code>
+ <br>SHA-1: <code>ac1d8a8e4f4a1dca5864dc733caa940bffc28616</code></td>
+ </tr>
+ <tr id="razor">
+ <td>Nexus 7 (Wifi) <br>"razor"</td>
+ <td><a href="#top" onclick="onDownload(this)"
+ >razor-lpv79-preview-d0ddf8ce.tgz</a></td>
+ <td>MD5: <code>b293a5d3a4e07beabebcc0be85ad68a2</code>
+ <br><nobr>SHA-1: <code>d0ddf8ce733ba2a34279cdff8827fd604762c2342d</nobr></td>
+ </tr>
+ </table>
+ </li>
+
+ <li>Follow the instructions at
+ <a href="https://developers.google.com/android/nexus/images#instructions">developers.google.com/android</a>
+ to flash the image onto your device.</li>
+</ol>
+
+
+<h3 id="revertDevice">Revert a Device to Factory Specifications</h3>
+
+ <p>If you want to uninstall the Preview and revert the device to factory
+specifications, go to <a href="http://developers.google.com/android
+/nexus/images">developers.google.com/android</a> and download the image you want
+to flash to for your device. Follow the instructions on that page to flash the
+image to your device.</p>
+
+
+<h3 id="setupAVD">Set up an AVD</h3>
+
+<p>You can set up <a href="{@docRoot}tools/devices/">Android Virtual Devices
+(AVD)</a> and use the emulator to build and test apps with the M Preview.</p>
+
+<p>To create an AVD with the AVD Manager:</p>
+
+<ol>
+ <li>Install the M Preview SDK in your development environment, as described
+ in <a href="{@docRoot}preview/setup-sdk.html">Setting Up the Preview
+ SDK.</a></li>
+ <li>Follow the steps in
+ <a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD
+ Manager</a>. Use the following settings:
+ <ul>
+ <li><b>Device:</b> Either Nexus 5 or Nexus 7</li>
+ <li><b>Target:</b> <!-- Confirm exact text when we have final distro -->
+ Android M (Preview) - API Level M</li>
+ </ul>
+ <!-- Confirm this works when you can download image through SDK manager! -->
+ </li>
+</ol>
+
+
+<h2 id="createProject">Create a Project</h2>
+
+<p>Android Studio makes it easy to create a project for the M Developer Preview. Follow
+the steps described in <a href="{@docRoot}sdk/installing/create-project.html">Creating a
+Project</a>. In the <strong>Form Factors</strong> screen:</p>
+
+<ul>
+ <li>Check <strong>Phone and Tablet</strong>.</li>
+ <li>Select <strong>API 22+: Android M (Preview)</strong> in <strong>Minimum SDK</strong>.</li>
+</ul>
+
+<p>On the development environment, open the <code>build.gradle</code> file for your module
+and make sure that:</p>
+
+<ul>
+ <li><code>compileSdkVersion</code> is set to <code>'android-M'</code></li>
+ <li><code>minSdkVersion</code> is set to <code>'M'</code></li>
+ <li><code>targetSdkVersion</code> is set to <code>'M'</code></li>
+</ul>
+
+ </div><!-- landing -->
+
+</div><!-- relative wrapper -->
+
+
+
+<script>
+ var urlRoot = "http://storage.googleapis.com/androiddevelopers/preview/";
+ function onDownload(link) {
+
+ $("#downloadForRealz").html("Download " + $(link).text());
+ $("#downloadForRealz").attr('href', urlRoot + $(link).text());
+
+ $("#tos").fadeIn('fast');
+ $("#landing").fadeOut('fast');
+
+ return true;
+ }
+
+
+ function onAgreeChecked() {
+ /* verify that the TOS is agreed */
+ if ($("input#agree").is(":checked")) {
+ /* reveal the download button */
+ $("a#downloadForRealz").removeClass('disabled');
+ } else {
+ $("a#downloadForRealz").addClass('disabled');
+ }
+ }
+
+ function onDownloadForRealz(link) {
+ if ($("input#agree").is(':checked')) {
+ $("#tos").fadeOut('fast');
+ $("#landing").fadeIn('fast');
+ ga('send', 'event', 'M Preview', 'System Image', $("#downloadForRealz").html());
+ location.hash = "";
+ return true;
+ } else {
+ $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200,
+ function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)}
+ );
+ return false;
+ }
+ }
+
+ $(window).hashchange( function(){
+ if (location.hash == "") {
+ location.reload();
+ }
+ });
+
+</script>
diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd
new file mode 100644
index 0000000..4be6dd7
--- /dev/null
+++ b/docs/html/preview/support.jd
@@ -0,0 +1,67 @@
+page.title=Support
+
+@jd:body
+
+<p>
+ If you've encountered bugs or have feedback about the M Developer Preview,
+ <a href="https://code.google.com/p/android-developer-preview/">create an issue</a>
+ on our issue tracker.
+</p>
+
+<p>
+ For more support, join the
+ <a href="https://plus.google.com/communities/101985907812750684586">M Developer
+ Preview Google+ community</a> to discuss your development experiences.
+</p>
+
+<h2 id="release-notes">Release Notes</h2>
+
+<!--
+<div class="toggle-content opened">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>M Developer Preview, Revision 2</a> <em>(Month 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+
+ <dt>Fix Category 1</dt>
+ <dd>
+ <ul>
+ <li>Fixed issue X.</li>
+ <li>Fixed issue Y.</li>
+ <li>Fixed issue Z.</li>
+ </ul>
+ </dd>
+
+ <dt>Fix Category 2</dt>
+ <dd>
+ <ul>
+ <li>Fixed issue X.</li>
+ <li>Fixed issue Y.</li>
+ <li>Fixed issue Z.</li>
+ </ul>
+ </dd>
+
+ </dl>
+ </div>
+</div>
+-->
+
+<div class="toggle-content opened">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>M Developer Preview, Revision 1</a> <em>(May 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Initial release.</dt>
+ </dl>
+ </div>
+</div>
+
+
diff --git a/docs/html/samples/new/index.jd b/docs/html/samples/new/index.jd
index 279b910..80765c7 100644
--- a/docs/html/samples/new/index.jd
+++ b/docs/html/samples/new/index.jd
@@ -1,4 +1,5 @@
page.title=What's New
+page.image=images/cards/samples-new_2x.png
@jd:body
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 118f4b8..7cdf72f 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,6 +1,7 @@
page.title=Download Android Studio and SDK Tools
page.tags=sdk, android studio
page.template=sdk
+page.image=images/cards/android-studio_2x.png
header.hide=1
page.metaDescription=Download the official Android IDE and developer tools to build apps for Android phones, tablets, wearables, TVs, and more.
@@ -30,21 +31,21 @@ studio.win_notools_exe_checksum=760d45212bea42f52adb1cbeab2390156d49c74d
-sdk.linux_download=android-sdk_r24.1.2-linux.tgz
-sdk.linux_bytes=168121693
-sdk.linux_checksum=68980e4a26cca0182abb1032abffbb72a1240c51
+sdk.linux_download=android-sdk_r24.2-linux.tgz
+sdk.linux_bytes=168119905
+sdk.linux_checksum=1a29f9827ef395a96db629209b0e38d5e2dd8089
-sdk.mac_download=android-sdk_r24.1.2-macosx.zip
-sdk.mac_bytes=89151287
-sdk.mac_checksum=00e43ff1557e8cba7da53e4f64f3a34498048256
+sdk.mac_download=android-sdk_r24.2-macosx.zip
+sdk.mac_bytes=88949635
+sdk.mac_checksum=256c9bf642f56242d963c090d147de7402733451
-sdk.win_download=android-sdk_r24.1.2-windows.zip
-sdk.win_bytes=159778618
-sdk.win_checksum=704f6c874373b98e061fe2e7eb34f9fcb907a341
+sdk.win_download=android-sdk_r24.2-windows.zip
+sdk.win_bytes=155944165
+sdk.win_checksum=2611ed9a6080f4838f1d4e55172801714a8a169b
-sdk.win_installer=installer_r24.1.2-windows.exe
-sdk.win_installer_bytes=111364285
-sdk.win_installer_checksum=e0ec864efa0e7449db2d7ed069c03b1f4d36f0cd
+sdk.win_installer=installer_r24.2-windows.exe
+sdk.win_installer_bytes=107849819
+sdk.win_installer_checksum=e764ea93aa72766737f9be3b9fb3e42d879ab599
@@ -63,7 +64,7 @@ sdk.win_installer_checksum=e0ec864efa0e7449db2d7ed069c03b1f4d36f0cd
}
.feature-blurb {
margin:0px; font-size:16px; font-weight:300;
- padding:40px 0 0 0;
+ padding-top:40px;
}
.landing-button.green {
@@ -284,7 +285,7 @@ This is the Android Software Development Kit License Agreement
<img src="{@docRoot}images/tools/studio-hero.png"
srcset="{@docRoot}images/tools/studio-hero_2x.png 2x, {@docRoot}images/tools/studio-hero.png 1x"
-width="760" height="400" alt="" style="margin-bottom:80px" />
+width="760" height="400" alt="" style="margin-bottom:100px" />
<div style="color: #fff; width:226px; height:0; overflow:visible; position:absolute; top:40px; left:25px">
@@ -293,7 +294,7 @@ width="760" height="400" alt="" style="margin-bottom:80px" />
<p style="font-size: 16px; color:#bbb; position: absolute;left: 297px; top: 5px; display: block;
width: 400px;text-align: center;">The official Android IDE</p>
-<ul style="font-size:12px">
+<ul style="font-size:12px;line-height:19px;">
<li>Android Studio IDE</li>
<li>Android SDK tools</li>
<li>Android 5.0 (Lollipop) Platform</li>
@@ -321,10 +322,10 @@ target="_blank">Take a Survey</a></li>
+<div class="cols">
+<h2 class="feature norule col-13">Intelligent code editor</h2>
-<h2 class="feature norule" >Intelligent code editor</h2>
-
-<div class="col-9" style="margin:0 20px 0 0">
+<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-code.png"
srcset="{@docRoot}images/tools/studio-hero-code_2x.png 2x, {@docRoot}images/tools/studio-hero-code.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
@@ -339,9 +340,9 @@ srcset="{@docRoot}images/tools/studio-hero-code_2x.png 2x, {@docRoot}images/tool
-<h2 class="feature norule">Code templates and GitHub integration</h2>
+<h2 class="feature norule col-13">Code templates and GitHub integration</h2>
-<div class="col-9" style="margin:0 20px 0 0">
+<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-import.png"
srcset="{@docRoot}images/tools/studio-hero-import_2x.png 2x, {@docRoot}images/tools/studio-hero-import.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
@@ -356,9 +357,9 @@ srcset="{@docRoot}images/tools/studio-hero-import_2x.png 2x, {@docRoot}images/to
-<h2 class="feature norule">Multi-screen app development</h2>
+<h2 class="feature norule col-13">Multi-screen app development</h2>
-<div class="col-9" style="margin:0 20px 0 0">
+<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-screens.png"
srcset="{@docRoot}images/tools/studio-hero-screens_2x.png 2x, {@docRoot}images/tools/studio-hero-screens.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
@@ -373,9 +374,9 @@ srcset="{@docRoot}images/tools/studio-hero-screens_2x.png 2x, {@docRoot}images/t
-<h2 class="feature norule">Virtual devices for all shapes and sizes</h2>
+<h2 class="feature norule col-13">Virtual devices for all shapes and sizes</h2>
-<div class="col-9" style="margin:0 20px 0 0">
+<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-avds.png"
srcset="{@docRoot}images/tools/studio-hero-avds_2x.png 2x, {@docRoot}images/tools/studio-hero-avds.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
@@ -389,10 +390,10 @@ srcset="{@docRoot}images/tools/studio-hero-avds_2x.png 2x, {@docRoot}images/tool
-<h2 class="feature norule">
+<h2 class="feature norule col-13">
Android builds evolved, with Gradle</h2>
-<div class="col-9" style="margin:0 20px 0 0">
+<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-gradle.png"
srcset="{@docRoot}images/tools/studio-hero-gradle_2x.png 2x, {@docRoot}images/tools/studio-hero-gradle.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
diff --git a/docs/html/sdk/installing/migrate.jd b/docs/html/sdk/installing/migrate.jd
index 3c04cb4..345e89a 100644
--- a/docs/html/sdk/installing/migrate.jd
+++ b/docs/html/sdk/installing/migrate.jd
@@ -24,17 +24,31 @@ Android, so you should migrate to Android Studio to receive all the latest IDE u
<p>To migrate existing Android projects, simply import them using Android Studio:</p>
<ol>
- <li>In Android Studio, close any projects currently open. You should see the
- <strong>Welcome to Android Studio</strong> window.</li>
- <li>Click <strong>Import Non-Android Studio project</strong>.</li>
- <li>Locate the project you exported from Eclipse, expand it, select the
- <strong>build.gradle</strong> file and click <strong>OK</strong>.</li>
- <li>In the following dialog, leave <strong>Use gradle wrapper</strong> selected and click
- <strong>OK</strong>. (You do not need to specify the Gradle home.)</li>
+ <li>In Android Studio, from the main menu or the <strong>Welcome to Android Studio</strong> page,
+ choose <strong>File &gt; Import Project</strong>.</li>
+ <li> Select the Eclipse root project directory</strong> and click <strong>OK</strong>.
+ <p class="note"><strong>Note:</strong> The Eclipse root directory must contain the
+ <code>AndroidManifest.xml</code> file. Also, the root directory must contain either the
+ <code>.project</code> and <strong>.classpath</strong> files from Eclipse or the
+ <code>res/</code> and <code>src/</code> directories.</p>
+ </li>
+ <li>Follow the steps in the import wizard. </li>
</ol>
-<p>Android Studio properly updates the project structure and creates the appropriate
-Gradle build file.</p>
+<p>Android Studio imports the current dependencies, downloads libraries, and
+creates an Android Studio project with the imported Eclipse project as the main module. Android
+Studio also creates the required Gradle build files. </p>
+
+<p>The import process replaces any JAR files and libraries with Gradle dependencies, and replaces
+source libraries and binary libraries with Maven dependencies, so you no longer need to maintain
+these files manually.</p>
+
+ <p class="note"><strong>Note:</strong> If there are references to Eclipse workspace library files,
+ comment them out in the <code>project.properties</code> or <code>.classpath</code> files
+ that you imported from the Eclipse project. You can then add these files in the
+ <code>build.gradle</code> file. See
+ <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>. </p>
+
<p>For more help getting started with Android Studio and the IntelliJ user experience,
<a href="{@docRoot}tools/studio/index.html">learn more about Android Studio</a> and
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 47b603a..434dc44 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -24,6 +24,33 @@ href="http://tools.android.com/knownissues">http://tools.android.com/knownissues
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 24.2.0</a> <em>(May 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 19 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed several minor emulator issues.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 24.1.2</a> <em>(February 2015)</em>
</p>
diff --git a/docs/html/tools/support-library/index.jd b/docs/html/tools/support-library/index.jd
index 1aef0c1..98c9ad5 100644
--- a/docs/html/tools/support-library/index.jd
+++ b/docs/html/tools/support-library/index.jd
@@ -1322,3 +1322,4 @@ Android 3.2 and higher (all other APIs in the v4 library are already available w
<p>Initial release with the v4 library.</p>
</div>
</div>
+
diff --git a/docs/html/training/building-wearables.jd b/docs/html/training/building-wearables.jd
index 8015d0c..c9e1856 100644
--- a/docs/html/training/building-wearables.jd
+++ b/docs/html/training/building-wearables.jd
@@ -1,6 +1,6 @@
page.title=Building Apps for Wearables
page.trainingcourse=true
-page.image=wear/images/notifications.png
+page.image=images/cards/android-wear-apps_2x.jpg
page.metaDescription=Learn how to build notifications, send and sync data, and use voice actions.
@jd:body
@@ -11,4 +11,4 @@ synced to wearables as well as how to build apps that run on wearables.</p>
<p class="note"><strong>Note:</strong> For more information about the APIs used in these training
classes, see the <a href="{@docRoot}reference/packages-wearable-support.html">Wear API reference
-documentation</a>.</p> \ No newline at end of file
+documentation</a>.</p>
diff --git a/docs/html/training/material/index.jd b/docs/html/training/material/index.jd
index 4eb7911..6071fb1 100644
--- a/docs/html/training/material/index.jd
+++ b/docs/html/training/material/index.jd
@@ -1,6 +1,6 @@
-page.title=Creating Apps with Material Design
+page.title=Material Design for Developers
page.type=design
-page.image=images/material.png
+page.image=images/cards/material_2x.png
page.metaDescription=Learn how to apply material design to your apps.
diff --git a/docs/html/training/swipe/add-swipe-interface.jd b/docs/html/training/swipe/add-swipe-interface.jd
new file mode 100644
index 0000000..ac15caf
--- /dev/null
+++ b/docs/html/training/swipe/add-swipe-interface.jd
@@ -0,0 +1,135 @@
+page.title=Adding Swipe-to-Refresh To Your App
+trainingnavtop=true
+@jd:body
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#AddSwipeWidget">Add the SwipeRefreshLayout Widget</a>
+ <li><a href="#AddRefreshAction">Add a Refresh Action to the Action Bar</a>
+</ol>
+
+<!-- other docs (NOT javadocs) -->
+<h2>You should also read</h2>
+<ul>
+ <li>
+ <a href=
+ "{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
+ </li>
+
+ <li>
+ <a href="{@docRoot}training/basics/actionbar/index.html">Adding the Action
+ Bar</a>
+ </li>
+</ul>
+
+<h2>Sample Apps</h2>
+
+<ul>
+ <li><a href="{@docRoot}samples/SwipeRefreshLayoutBasic/index.html">
+ SwipeRefreshLayoutBasic</a></li>
+ <li><a href="{@docRoot}samples/SwipeRefreshListFragment/index.html">
+ SwipeRefreshListFragment</a></li>
+</ul>
+
+</div>
+</div>
+
+
+<p>
+ The swipe-to-refresh user interface pattern is implemented entirely within
+ the {@link android.support.v4.widget.SwipeRefreshLayout} widget, which
+ detects the vertical swipe, displays a distinctive progress bar, and triggers
+ callback methods in your app. You enable this behavior
+ by adding the widget to your layout file as the parent of a {@link
+ android.widget.ListView} or {@link android.widget.GridView}, and implementing
+ the refresh behavior that gets invoked when the user swipes.
+</p>
+
+<p>
+ This lesson shows you how to add the widget to an existing layout. It also
+ shows you how to add a refresh action to the action bar overflow area, so
+ that users who may be unable to use the swipe gesture can trigger a manual
+ update with an external device.
+</p>
+
+<h2 id="AddSwipeWidget">Add the SwipeRefreshLayout Widget</h2>
+<p>
+ To add the swipe to refresh widget to an existing app, add {@link
+ android.support.v4.widget.SwipeRefreshLayout} as the parent
+ of a single {@link android.widget.ListView} or {@link
+ android.widget.GridView}. Remember that {@link
+ android.support.v4.widget.SwipeRefreshLayout} only supports a single {@link
+ android.widget.ListView} or {@link android.widget.GridView} child.
+</p>
+
+<p>
+ The following example demonstrates how to add the {@link
+ android.support.v4.widget.SwipeRefreshLayout} widget to an existing layout
+ file containing a {@link android.widget.ListView}:
+</p>
+
+<pre>&lt;android.support.v4.widget.SwipeRefreshLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="&#64;+id/swiperefresh"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"&gt;
+
+ &lt;ListView
+ android:id="&#64;android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" /&gt;
+
+&lt;/android.support.v4.widget.SwipeRefreshLayout&gt;</pre>
+
+<p>
+ You can also use the {@link android.support.v4.widget.SwipeRefreshLayout}
+ widget with a {@link android.support.v4.app.ListFragment}. If the layout
+ contains a {@link android.widget.ListView} with the ID
+ <code>"@android:id/list"</code>, the swipe-to-refresh functionality is
+ automatically supported. However, explicitly declaring the {@link
+ android.widget.ListView} in this way supersedes the default {@link
+ android.support.v4.app.ListFragment} view structure. If you want to use the
+ default view structure, you will have to override parts of the {@link
+ android.support.v4.widget.SwipeRefreshLayout} and {@link
+ android.support.v4.app.ListFragment} behavior. For an example of how to do
+ this, see the <a href=
+ "{@docRoot}samples/SwipeRefreshListFragment/index.html">SwipeRefreshListFragment</a>
+ sample app.
+</p>
+
+<h2 id="AddRefreshAction">Add a Refresh Action to the Action Bar</h2>
+
+<p>
+ You should add a refresh action to your app's action bar to ensure that
+ users who may not be able to perform a swipe gesture can still trigger a
+ manual update. For example, users with accessibility issues can trigger
+ action bar actions using external devices, such as keyboards and D-pads.
+</p>
+
+<p>
+ You should add the refresh action as a menu item,
+ rather than as a button, by setting the attribute
+ <code>android:showAsAction=never</code>. If you display the action as a
+ button, users may assume that the refresh button action is different from the
+ swipe-to-refresh action. By making the refresh action less conspicuous in the
+ action bar, you can encourage users to perform manual updates with the swipe
+ gesture while still maintaining the accessible option in a place where D-pad
+ users would look for it.
+</p>
+
+<p>
+ The following code demonstrates how to add the swipe-to-refresh action to the
+ overflow area:
+</p>
+
+<pre>&lt;menu xmlns:android="http://schemas.android.com/apk/res/android" &gt;
+ &lt;item
+ android:id="&#64;+id/menu_refresh"
+ android:showAsAction="never"
+ android:title="&#64;string/menu_refresh"/&gt;
+&lt;/menu&gt;</pre>
diff --git a/docs/html/training/swipe/images/swipe.mp4 b/docs/html/training/swipe/images/swipe.mp4
new file mode 100644
index 0000000..cd5c511
--- /dev/null
+++ b/docs/html/training/swipe/images/swipe.mp4
Binary files differ
diff --git a/docs/html/training/swipe/images/swipe_original.mp4 b/docs/html/training/swipe/images/swipe_original.mp4
new file mode 100644
index 0000000..abdf08f
--- /dev/null
+++ b/docs/html/training/swipe/images/swipe_original.mp4
Binary files differ
diff --git a/docs/html/training/swipe/index.jd b/docs/html/training/swipe/index.jd
new file mode 100644
index 0000000..17b4cf7
--- /dev/null
+++ b/docs/html/training/swipe/index.jd
@@ -0,0 +1,91 @@
+page.title=Supporting Swipe-to-Refresh
+trainingnavtop=true
+startpage=true
+
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+<ul>
+ <li>Android 1.6 (API level 4) or later
+ </li>
+
+ <li>Latest version of the Android v4 <a href=
+ "{@docRoot}tools/support-library/index.html">Support Library</a>
+ </li>
+</ul>
+
+<h2>Sample Apps</h2>
+
+<ul>
+ <li><a href="{@docRoot}samples/SwipeRefreshLayoutBasic/index.html">
+ SwipeRefreshLayoutBasic</a></li>
+ <li><a href="{@docRoot}samples/SwipeRefreshListFragment/index.html">
+ SwipeRefreshListFragment</a></li>
+ <li><a href="{@docRoot}samples/SwipeRefreshMultipleViews/index.html">
+ SwipeRefreshMultipleViews</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>
+ Even if your app automatically updates its content on a regular basis, you
+ can allow users to request manual updates as well. For example, a weather
+ forecasting app can allow users get the latest forecasts on demand. To
+ provide a standard user experience for requesting updates, the Android
+ platform includes the swipe-to-refresh design pattern, which allows users
+ to trigger an update with a vertical swipe.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> This class requires the latest version of the Android
+ v4 Support Library APIs. If you have not used the Support Library before,
+ follow the instructions in the <a href=
+ "{@docRoot}tools/support-library/setup.html">Support Library Setup</a>
+ document.
+</p>
+
+<h2>Lessons</h2>
+
+<dl>
+ <dt>
+ <b><a href="add-swipe-interface.html">Adding Swipe-to-Refresh To Your
+ App</a></b>
+ </dt>
+
+ <dd>
+ <div style="width:290px;margin-right:35px;float:right">
+ <div class="framed-nexus5-port-span-5">
+ <video class="play-on-hover" autoplay alt=
+ "When the user performs a swipe gesture, the SwipeRefreshLayout widget displays a progress indicator until your app finishes updating its data.">
+ <!-- Preferred video size 216x384 (portrait) -->
+ <source src="images/swipe.mp4">
+ </video>
+ </div>
+
+ <div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
+ <em>To replay the movie, click on the device screen</em>
+ </div>
+ </div>
+ </dd>
+
+ <dd>
+ Learn how to provide swipe-to-refresh support in a {@link
+ android.widget.ListView} or {@link android.widget.GridView}, and how to
+ provide an accessible refresh option using the action bar.
+ </dd>
+
+ <dt>
+ <b><a href="respond-refresh-request.html">Responding to a Refresh
+ Request</a></b>
+ </dt>
+
+ <dd>
+ Learn how to respond to the swipe-to-refresh gesture, and how to perform the
+ same update from an action bar action.
+ </dd>
+</dl>
diff --git a/docs/html/training/swipe/respond-refresh-request.jd b/docs/html/training/swipe/respond-refresh-request.jd
new file mode 100644
index 0000000..243b4a3
--- /dev/null
+++ b/docs/html/training/swipe/respond-refresh-request.jd
@@ -0,0 +1,158 @@
+page.title=Responding to a Refresh Request
+
+trainingnavtop=true
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#RespondRefresh">Respond to the Refresh Gesture</a></li>
+ <li><a href="#RespondAction">Respond to the Refresh Action</a>
+</ol>
+
+<h2>Sample App</h2>
+
+<ul>
+ <li><a href="{@docRoot}samples/SwipeRefreshLayoutBasic/index.html">
+ SwipeRefreshLayoutBasic</a></li>
+</ul>
+
+
+</div>
+</div>
+
+<p>
+ This lesson shows you how to update your app when the user requests a manual
+ refresh, whether the user triggers the refresh with a swipe gesture or by
+ using the action bar refresh action.
+</p>
+
+<h2 id="RespondRefresh">Respond to the Refresh Gesture</h2>
+
+<p>
+ When the user makes a swipe gesture, the system displays the progress
+ indicator and calls your app's callback method. Your callback method is
+ responsible for actually updating the app's data.
+</p>
+
+<p>
+ To respond to the refresh gesture in your app, implement the {@link
+ android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener} interface and
+ its {@link
+ android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener#onRefresh
+ onRefresh()} method. The {@link
+ android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener#onRefresh
+ onRefresh()} method is invoked when the user performs a swipe gesture.
+</p>
+
+<p>
+ You should put the code for the actual update
+ operation in a separate method, and call that update method from your {@link
+ android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener#onRefresh
+ onRefresh()} implementation. That way, you can use the same update method to
+ perform the update when the user triggers a refresh from the action bar.
+</p>
+
+<p>
+ Your update method calls {@link
+ android.support.v4.widget.SwipeRefreshLayout#setRefreshing
+ setRefreshing(false)} when it has finished updating the data. Calling this
+ method instructs the {@link android.support.v4.widget.SwipeRefreshLayout} to
+ remove the progress indicator and update the view contents.
+</p>
+
+<p>
+ For example, the following code implements {@link
+ android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener#onRefresh
+ onRefresh()} and invokes the method {@code myUpdateOperation()} to update the
+ data displayed by the {@link android.widget.ListView}:
+</p>
+
+<pre>/*
+ * Sets up a SwipeRefreshLayout.OnRefreshListener that is invoked when the user
+ * performs a swipe-to-refresh gesture.
+ */
+mySwipeRefreshLayout.setOnRefreshListener(
+ new SwipeRefreshLayout.OnRefreshListener() {
+ &#64;Override
+ public void onRefresh() {
+ Log.i(LOG_TAG, "onRefresh called from SwipeRefreshLayout");
+
+ // This method performs the actual data-refresh operation.
+ // The method calls setRefreshing(false) when it's finished.
+ myUpdateOperation();
+ }
+ }
+);</pre>
+
+<h2 id="RespondAction">Respond to the Refresh Action</h2>
+
+<p>
+ If the user requests a refresh by using the action bar, the system calls the
+ {@link android.support.v4.app.Fragment#onOptionsItemSelected
+ onOptionsItemSelected()} method. Your app should respond to this call by
+ displaying the progress indicator and refreshing the app's data.
+</p>
+
+<p>
+ To respond to the refresh action, override {@link
+ android.support.v4.app.Fragment#onOptionsItemSelected
+ onOptionsItemSelected()}. In your override method, trigger the {@link
+ android.support.v4.widget.SwipeRefreshLayout} progress indicator by calling
+ {@link android.support.v4.widget.SwipeRefreshLayout#setRefreshing
+ setRefreshing()} with the value {@code true}, then perform the update
+ operation. Once again, you should be doing the actual update in a separate
+ method, so the same method can be called whether the user triggers the update
+ with a swipe or by using the action bar. When the update has finished, call
+ {@link android.support.v4.widget.SwipeRefreshLayout#setRefreshing
+ setRefreshing(false)} to remove the refresh progress indicator.
+</p>
+
+<p>The following code shows how to respond to the request action:
+</p>
+
+<pre>/*
+ * Listen for option item selections so that we receive a notification
+ * when the user requests a refresh by selecting the refresh action bar item.
+ */
+&#64;Override
+public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+
+ // Check if user triggered a refresh:
+ case R.id.menu_refresh:
+ Log.i(LOG_TAG, "Refresh menu item selected");
+
+ // Signal SwipeRefreshLayout to start the progress indicator
+ mySwipeRefreshLayout.setRefreshing(true);
+
+ // Start the refresh background task.
+ // This method calls setRefreshing(false) when it's finished.
+ myUpdateOperation();
+
+ return true;
+ }
+
+ // User didn't trigger a refresh, let the superclass handle this action
+ return super.onOptionsItemSelected(item);
+
+}</pre>
+
+<p class="note">
+ <strong>Note:</strong> When the user triggers a refresh with a swipe action as
+ described in <a href="#RespondRefresh">Respond to the Refresh Gesture</a>,
+ you do not need to call {@link
+ android.support.v4.widget.SwipeRefreshLayout#setRefreshing setRefreshing()}.
+ The {@link
+ android.support.v4.widget.SwipeRefreshLayout} widget takes care of displaying
+ the progress indicator and removing it when the update has finished. However,
+ if the update is triggered by any means <em>other than</em> a swipe gesture,
+ you need to explicitly turn the progress indicator on with {@link
+ android.support.v4.widget.SwipeRefreshLayout#setRefreshing setRefreshing()}.
+ The method which actually refreshes the data calls {@link
+ android.support.v4.widget.SwipeRefreshLayout#setRefreshing
+ setRefreshing(false)} to signal that the update is finished.
+</p>
diff --git a/docs/html/training/sync-adapters/creating-stub-provider.jd b/docs/html/training/sync-adapters/creating-stub-provider.jd
index b8190d1..e9e18ef 100644
--- a/docs/html/training/sync-adapters/creating-stub-provider.jd
+++ b/docs/html/training/sync-adapters/creating-stub-provider.jd
@@ -85,11 +85,11 @@ public class StubProvider extends ContentProvider {
return true;
}
/*
- * Return an empty String for MIME type
+ * Return no type for MIME type
*/
&#64;Override
- public String getType() {
- return new String();
+ public String getType(Uri uri) {
+ return null;
}
/*
* query() always returns no results
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 3ee7ab7..862663e 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -1195,7 +1195,24 @@ include the action bar on devices running Android 2.1 or higher."
</li>
</ul>
</li>
-
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>training/swipe/index.html"
+ description=
+ "How to modify your app's layout to support manual content updates triggered by the
+ swipe-to-refresh gesture."
+ >Supporting Swipe-to-Refresh</a>
+ </div>
+ <ul>
+ <li>
+ <a href="<?cs var:toroot ?>training/swipe/add-swipe-interface.html"
+ >Adding Swipe-to-Refresh To Your App</a></li>
+ <li>
+ <a href="<?cs var:toroot ?>training/swipe/respond-refresh-request.html"
+ >Responding to a Refresh Gesture</a>
+ </li>
+ </ul>
+ </li>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/search/index.html"
diff --git a/docs/html/training/tv/start/start.jd b/docs/html/training/tv/start/start.jd
index 0f5871f..e55e202 100644
--- a/docs/html/training/tv/start/start.jd
+++ b/docs/html/training/tv/start/start.jd
@@ -1,4 +1,4 @@
-page.title=Getting Started with TV Apps
+page.title=Get Started with TV Apps
page.tags="leanback","recyclerview","launcher"
trainingnavtop=true
diff --git a/docs/html/tv/index.jd b/docs/html/tv/index.jd
index e4d7f7a..7a0cdcc 100644
--- a/docs/html/tv/index.jd
+++ b/docs/html/tv/index.jd
@@ -1,6 +1,6 @@
page.title=About Android TV
page.type=about
-page.image=tv/images/hero.jpg
+page.image=images/cards/android-tv_2x.png
page.viewport_width=970
page.tags="tv", "leanback"
page.metaDescription=Bring your apps, games, and content to the biggest screen in the house.
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index 316f5ca..74e4939 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -3,7 +3,7 @@ page.viewport_width=970
fullpage=true
no_footer_links=true
page.type=about
-
+page.image=images/cards/android-wear_2x.png
@jd:body
<style>
@@ -74,7 +74,7 @@ page.type=about
</div> <!-- end .landing-section .landing-hero -->
- <div class="landing-rest-of-page" style="margin-top:80px">
+ <div class="landing-rest-of-page">
<div class="landing-section" id="extending-android-to-wearables">
<div class="wrap">
<div class="landing-section-header">
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index be5c52b..c850b07 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -41,13 +41,13 @@ public final class Bitmap implements Parcelable {
*/
public static final int DENSITY_NONE = 0;
- private final long mSkBitmapPtr;
-
/**
* Backing buffer for the Bitmap.
*/
private byte[] mBuffer;
+ // Convenience for JNI access
+ private final long mNativePtr;
private final BitmapFinalizer mFinalizer;
private final boolean mIsMutable;
@@ -115,17 +115,16 @@ public final class Bitmap implements Parcelable {
mRequestPremultiplied = requestPremultiplied;
mBuffer = buffer;
- // we delete this in our finalizer
- mSkBitmapPtr = nativeBitmap;
-
mNinePatchChunk = ninePatchChunk;
mNinePatchInsets = ninePatchInsets;
if (density >= 0) {
mDensity = density;
}
- int nativeAllocationByteCount = buffer == null ? getByteCount() : 0;
- mFinalizer = new BitmapFinalizer(nativeBitmap, nativeAllocationByteCount);
+ mNativePtr = nativeBitmap;
+ mFinalizer = new BitmapFinalizer(nativeBitmap);
+ int nativeAllocationByteCount = (buffer == null ? getByteCount() : 0);
+ mFinalizer.setNativeAllocationByteCount(nativeAllocationByteCount);
}
/**
@@ -223,8 +222,8 @@ public final class Bitmap implements Parcelable {
throw new IllegalStateException("native-backed bitmaps may not be reconfigured");
}
- nativeReconfigure(mSkBitmapPtr, width, height, config.nativeInt, mBuffer.length,
- mRequestPremultiplied);
+ nativeReconfigure(mFinalizer.mNativeBitmap, width, height, config.nativeInt,
+ mBuffer.length, mRequestPremultiplied);
mWidth = width;
mHeight = height;
}
@@ -301,7 +300,7 @@ public final class Bitmap implements Parcelable {
*/
public void recycle() {
if (!mRecycled && mFinalizer.mNativeBitmap != 0) {
- if (nativeRecycle(mSkBitmapPtr)) {
+ if (nativeRecycle(mFinalizer.mNativeBitmap)) {
// return value indicates whether native pixel object was actually recycled.
// false indicates that it is still in use at the native level and these
// objects should not be collected now. They will be collected later when the
@@ -331,7 +330,7 @@ public final class Bitmap implements Parcelable {
* @return The current generation ID for this bitmap.
*/
public int getGenerationId() {
- return nativeGenerationId(mSkBitmapPtr);
+ return nativeGenerationId(mFinalizer.mNativeBitmap);
}
/**
@@ -487,7 +486,7 @@ public final class Bitmap implements Parcelable {
throw new RuntimeException("Buffer not large enough for pixels");
}
- nativeCopyPixelsToBuffer(mSkBitmapPtr, dst);
+ nativeCopyPixelsToBuffer(mFinalizer.mNativeBitmap, dst);
// now update the buffer's position
int position = dst.position();
@@ -527,7 +526,7 @@ public final class Bitmap implements Parcelable {
throw new RuntimeException("Buffer not large enough for pixels");
}
- nativeCopyPixelsFromBuffer(mSkBitmapPtr, src);
+ nativeCopyPixelsFromBuffer(mFinalizer.mNativeBitmap, src);
// now update the buffer's position
int position = src.position();
@@ -549,7 +548,7 @@ public final class Bitmap implements Parcelable {
*/
public Bitmap copy(Config config, boolean isMutable) {
checkRecycled("Can't copy a recycled bitmap");
- Bitmap b = nativeCopy(mSkBitmapPtr, config.nativeInt, isMutable);
+ Bitmap b = nativeCopy(mFinalizer.mNativeBitmap, config.nativeInt, isMutable);
if (b != null) {
b.setPremultiplied(mRequestPremultiplied);
b.mDensity = mDensity;
@@ -810,7 +809,7 @@ public final class Bitmap implements Parcelable {
}
bm.setHasAlpha(hasAlpha);
if (config == Config.ARGB_8888 && !hasAlpha) {
- nativeErase(bm.mSkBitmapPtr, 0xff000000);
+ nativeErase(bm.mFinalizer.mNativeBitmap, 0xff000000);
}
// No need to initialize the bitmap to zeroes with other configs;
// it is backed by a VM byte array which is by definition preinitialized
@@ -1000,8 +999,8 @@ public final class Bitmap implements Parcelable {
throw new IllegalArgumentException("quality must be 0..100");
}
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
- boolean result = nativeCompress(mSkBitmapPtr, format.nativeInt, quality,
- stream, new byte[WORKING_COMPRESS_STORAGE]);
+ boolean result = nativeCompress(mFinalizer.mNativeBitmap, format.nativeInt,
+ quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
return result;
}
@@ -1041,7 +1040,7 @@ public final class Bitmap implements Parcelable {
* @see BitmapFactory.Options#inPremultiplied
*/
public final boolean isPremultiplied() {
- return nativeIsPremultiplied(mSkBitmapPtr);
+ return nativeIsPremultiplied(mFinalizer.mNativeBitmap);
}
/**
@@ -1066,7 +1065,7 @@ public final class Bitmap implements Parcelable {
*/
public final void setPremultiplied(boolean premultiplied) {
mRequestPremultiplied = premultiplied;
- nativeSetPremultiplied(mSkBitmapPtr, premultiplied);
+ nativeSetPremultiplied(mFinalizer.mNativeBitmap, premultiplied);
}
/** Returns the bitmap's width */
@@ -1158,7 +1157,7 @@ public final class Bitmap implements Parcelable {
* @return number of bytes between rows of the native bitmap pixels.
*/
public final int getRowBytes() {
- return nativeRowBytes(mSkBitmapPtr);
+ return nativeRowBytes(mFinalizer.mNativeBitmap);
}
/**
@@ -1201,7 +1200,7 @@ public final class Bitmap implements Parcelable {
* that config, otherwise return null.
*/
public final Config getConfig() {
- return Config.nativeToConfig(nativeConfig(mSkBitmapPtr));
+ return Config.nativeToConfig(nativeConfig(mFinalizer.mNativeBitmap));
}
/** Returns true if the bitmap's config supports per-pixel alpha, and
@@ -1213,7 +1212,7 @@ public final class Bitmap implements Parcelable {
* it will return true by default.
*/
public final boolean hasAlpha() {
- return nativeHasAlpha(mSkBitmapPtr);
+ return nativeHasAlpha(mFinalizer.mNativeBitmap);
}
/**
@@ -1227,7 +1226,7 @@ public final class Bitmap implements Parcelable {
* non-opaque per-pixel alpha values.
*/
public void setHasAlpha(boolean hasAlpha) {
- nativeSetHasAlpha(mSkBitmapPtr, hasAlpha, mRequestPremultiplied);
+ nativeSetHasAlpha(mFinalizer.mNativeBitmap, hasAlpha, mRequestPremultiplied);
}
/**
@@ -1248,7 +1247,7 @@ public final class Bitmap implements Parcelable {
* @see #setHasMipMap(boolean)
*/
public final boolean hasMipMap() {
- return nativeHasMipMap(mSkBitmapPtr);
+ return nativeHasMipMap(mFinalizer.mNativeBitmap);
}
/**
@@ -1272,7 +1271,7 @@ public final class Bitmap implements Parcelable {
* @see #hasMipMap()
*/
public final void setHasMipMap(boolean hasMipMap) {
- nativeSetHasMipMap(mSkBitmapPtr, hasMipMap);
+ nativeSetHasMipMap(mFinalizer.mNativeBitmap, hasMipMap);
}
/**
@@ -1285,7 +1284,7 @@ public final class Bitmap implements Parcelable {
if (!isMutable()) {
throw new IllegalStateException("cannot erase immutable bitmaps");
}
- nativeErase(mSkBitmapPtr, c);
+ nativeErase(mFinalizer.mNativeBitmap, c);
}
/**
@@ -1302,7 +1301,7 @@ public final class Bitmap implements Parcelable {
public int getPixel(int x, int y) {
checkRecycled("Can't call getPixel() on a recycled bitmap");
checkPixelAccess(x, y);
- return nativeGetPixel(mSkBitmapPtr, x, y);
+ return nativeGetPixel(mFinalizer.mNativeBitmap, x, y);
}
/**
@@ -1335,7 +1334,7 @@ public final class Bitmap implements Parcelable {
return; // nothing to do
}
checkPixelsAccess(x, y, width, height, offset, stride, pixels);
- nativeGetPixels(mSkBitmapPtr, pixels, offset, stride,
+ nativeGetPixels(mFinalizer.mNativeBitmap, pixels, offset, stride,
x, y, width, height);
}
@@ -1416,7 +1415,7 @@ public final class Bitmap implements Parcelable {
throw new IllegalStateException();
}
checkPixelAccess(x, y);
- nativeSetPixel(mSkBitmapPtr, x, y, color);
+ nativeSetPixel(mFinalizer.mNativeBitmap, x, y, color);
}
/**
@@ -1452,7 +1451,7 @@ public final class Bitmap implements Parcelable {
return; // nothing to do
}
checkPixelsAccess(x, y, width, height, offset, stride, pixels);
- nativeSetPixels(mSkBitmapPtr, pixels, offset, stride,
+ nativeSetPixels(mFinalizer.mNativeBitmap, pixels, offset, stride,
x, y, width, height);
}
@@ -1490,7 +1489,7 @@ public final class Bitmap implements Parcelable {
*/
public void writeToParcel(Parcel p, int flags) {
checkRecycled("Can't parcel a recycled bitmap");
- if (!nativeWriteToParcel(mSkBitmapPtr, mIsMutable, mDensity, p)) {
+ if (!nativeWriteToParcel(mFinalizer.mNativeBitmap, mIsMutable, mDensity, p)) {
throw new RuntimeException("native writeToParcel failed");
}
}
@@ -1536,7 +1535,7 @@ public final class Bitmap implements Parcelable {
public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
checkRecycled("Can't extractAlpha on a recycled bitmap");
long nativePaint = paint != null ? paint.getNativeInstance() : 0;
- Bitmap bm = nativeExtractAlpha(mSkBitmapPtr, nativePaint, offsetXY);
+ Bitmap bm = nativeExtractAlpha(mFinalizer.mNativeBitmap, nativePaint, offsetXY);
if (bm == null) {
throw new RuntimeException("Failed to extractAlpha on Bitmap");
}
@@ -1550,7 +1549,8 @@ public final class Bitmap implements Parcelable {
* If other is null, return false.
*/
public boolean sameAs(Bitmap other) {
- return this == other || (other != null && nativeSameAs(mSkBitmapPtr, other.mSkBitmapPtr));
+ return this == other || (other != null
+ && nativeSameAs(mFinalizer.mNativeBitmap, other.mFinalizer.mNativeBitmap));
}
/**
@@ -1565,7 +1565,9 @@ public final class Bitmap implements Parcelable {
* and therefore is harmless.
*/
public void prepareToDraw() {
- nativePrepareToDraw(mSkBitmapPtr);
+ // TODO: Consider having this start an async upload?
+ // With inPurgeable no-op'd there's currently no use for this
+ // method, but it could have interesting future uses.
}
/**
@@ -1574,7 +1576,7 @@ public final class Bitmap implements Parcelable {
* @hide
* */
public final long refSkPixelRef() {
- return nativeRefPixelRef(mSkBitmapPtr);
+ return nativeRefPixelRef(mNativePtr);
}
private static class BitmapFinalizer {
@@ -1582,12 +1584,17 @@ public final class Bitmap implements Parcelable {
// Native memory allocated for the duration of the Bitmap,
// if pixel data allocated into native memory, instead of java byte[]
- private final int mNativeAllocationByteCount;
+ private int mNativeAllocationByteCount;
- BitmapFinalizer(long nativeBitmap, int nativeAllocationByteCount) {
+ BitmapFinalizer(long nativeBitmap) {
mNativeBitmap = nativeBitmap;
- mNativeAllocationByteCount = nativeAllocationByteCount;
+ }
+ public void setNativeAllocationByteCount(int nativeByteCount) {
+ if (mNativeAllocationByteCount != 0) {
+ VMRuntime.getRuntime().registerNativeFree(mNativeAllocationByteCount);
+ }
+ mNativeAllocationByteCount = nativeByteCount;
if (mNativeAllocationByteCount != 0) {
VMRuntime.getRuntime().registerNativeAllocation(mNativeAllocationByteCount);
}
@@ -1600,9 +1607,7 @@ public final class Bitmap implements Parcelable {
} catch (Throwable t) {
// Ignore
} finally {
- if (mNativeAllocationByteCount != 0) {
- VMRuntime.getRuntime().registerNativeFree(mNativeAllocationByteCount);
- }
+ setNativeAllocationByteCount(0);
nativeDestructor(mNativeBitmap);
mNativeBitmap = 0;
}
@@ -1654,7 +1659,6 @@ public final class Bitmap implements Parcelable {
long nativePaint,
int[] offsetXY);
- private static native void nativePrepareToDraw(long nativeBitmap);
private static native boolean nativeHasAlpha(long nativeBitmap);
private static native boolean nativeIsPremultiplied(long nativeBitmap);
private static native void nativeSetPremultiplied(long nativeBitmap,
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index f67dcb3..efc171c 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -53,8 +53,11 @@ import java.util.Arrays;
* attribute identifier.
* <p>
* A touch feedback drawable may contain multiple child layers, including a
- * special mask layer that is not drawn to the screen. A single layer may be set
- * as the mask by specifying its android:id value as {@link android.R.id#mask}.
+ * special mask layer that is not drawn to the screen. A single layer may be
+ * set as the mask from XML by specifying its {@code android:id} value as
+ * {@link android.R.id#mask}. At run time, a single layer may be set as the
+ * mask using {@code setId(..., android.R.id.mask)} or an existing mask layer
+ * may be replaced using {@code setDrawableByLayerId(android.R.id.mask, ...)}.
* <pre>
* <code>&lt!-- A red ripple masked against an opaque rectangle. --/>
* &ltripple android:color="#ffff0000">
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 461160a..2f28700 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -64,7 +64,7 @@ LOCAL_SRC_FILES:= $(deviceSources)
LOCAL_C_INCLUDES := \
external/zlib \
system/core/include
-LOCAL_STATIC_LIBRARIES := libziparchive
+LOCAL_STATIC_LIBRARIES := libziparchive libbase
LOCAL_SHARED_LIBRARIES := \
libbinder \
liblog \
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 0eb4fdc..a3d04d9 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -18,6 +18,7 @@ package android.location;
import com.android.internal.location.ProviderProperties;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
@@ -34,6 +35,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.ACCESS_MOCK_LOCATION;
+
/**
* This class provides access to the system location services. These
* services allow applications to obtain periodic updates of the
@@ -449,6 +454,7 @@ public class LocationManager {
* @throws RuntimeException if the calling thread has no Looper
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(String provider, long minTime, float minDistance,
LocationListener listener) {
checkProvider(provider);
@@ -480,6 +486,7 @@ public class LocationManager {
* @throws IllegalArgumentException if listener is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(String provider, long minTime, float minDistance,
LocationListener listener, Looper looper) {
checkProvider(provider);
@@ -512,6 +519,7 @@ public class LocationManager {
* @throws IllegalArgumentException if listener is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
LocationListener listener, Looper looper) {
checkCriteria(criteria);
@@ -539,6 +547,7 @@ public class LocationManager {
* @throws IllegalArgumentException if intent is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(String provider, long minTime, float minDistance,
PendingIntent intent) {
checkProvider(provider);
@@ -640,6 +649,7 @@ public class LocationManager {
* @throws IllegalArgumentException if intent is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
PendingIntent intent) {
checkCriteria(criteria);
@@ -669,6 +679,7 @@ public class LocationManager {
* @throws IllegalArgumentException if listener is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) {
checkProvider(provider);
checkListener(listener);
@@ -698,6 +709,7 @@ public class LocationManager {
* @throws IllegalArgumentException if listener is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) {
checkCriteria(criteria);
checkListener(listener);
@@ -720,6 +732,7 @@ public class LocationManager {
* @throws IllegalArgumentException if intent is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(String provider, PendingIntent intent) {
checkProvider(provider);
checkPendingIntent(intent);
@@ -743,6 +756,7 @@ public class LocationManager {
* @throws IllegalArgumentException if intent is null
* @throws SecurityException if no suitable permission is present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(Criteria criteria, PendingIntent intent) {
checkCriteria(criteria);
checkPendingIntent(intent);
@@ -879,6 +893,7 @@ public class LocationManager {
* @param listener listener object that no longer needs location updates
* @throws IllegalArgumentException if listener is null
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeUpdates(LocationListener listener) {
checkListener(listener);
String packageName = mContext.getPackageName();
@@ -962,6 +977,7 @@ public class LocationManager {
* @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
* permission is not present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
PendingIntent intent) {
checkPendingIntent(intent);
@@ -1012,6 +1028,7 @@ public class LocationManager {
*
* @hide
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void addGeofence(LocationRequest request, Geofence fence, PendingIntent intent) {
checkPendingIntent(intent);
checkGeofence(fence);
@@ -1039,6 +1056,7 @@ public class LocationManager {
* @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
* permission is not present
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeProximityAlert(PendingIntent intent) {
checkPendingIntent(intent);
String packageName = mContext.getPackageName();
@@ -1066,6 +1084,7 @@ public class LocationManager {
*
* @hide
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeGeofence(Geofence fence, PendingIntent intent) {
checkPendingIntent(intent);
checkGeofence(fence);
@@ -1089,6 +1108,7 @@ public class LocationManager {
*
* @hide
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeAllGeofences(PendingIntent intent) {
checkPendingIntent(intent);
String packageName = mContext.getPackageName();
@@ -1174,6 +1194,7 @@ public class LocationManager {
* @throws SecurityException if no suitable permission is present
* @throws IllegalArgumentException if provider is null or doesn't exist
*/
+ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public Location getLastKnownLocation(String provider) {
checkProvider(provider);
String packageName = mContext.getPackageName();
@@ -1202,6 +1223,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled
* @throws IllegalArgumentException if a provider with the given name already exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
@@ -1229,6 +1251,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void removeTestProvider(String provider) {
try {
mService.removeTestProvider(provider);
@@ -1253,6 +1276,7 @@ public class LocationManager {
* @throws IllegalArgumentException if no provider with the given name exists
* @throws IllegalArgumentException if the location is incomplete
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void setTestProviderLocation(String provider, Location loc) {
if (!loc.isComplete()) {
IllegalArgumentException e = new IllegalArgumentException(
@@ -1284,6 +1308,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void clearTestProviderLocation(String provider) {
try {
mService.clearTestProviderLocation(provider);
@@ -1304,6 +1329,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void setTestProviderEnabled(String provider, boolean enabled) {
try {
mService.setTestProviderEnabled(provider, enabled);
@@ -1322,6 +1348,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void clearTestProviderEnabled(String provider) {
try {
mService.clearTestProviderEnabled(provider);
@@ -1344,6 +1371,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
try {
mService.setTestProviderStatus(provider, status, extras, updateTime);
@@ -1362,6 +1390,7 @@ public class LocationManager {
* Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
* @throws IllegalArgumentException if no provider with the given name exists
*/
+ @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true)
public void clearTestProviderStatus(String provider) {
try {
mService.clearTestProviderStatus(provider);
@@ -1492,6 +1521,7 @@ public class LocationManager {
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
*/
+ @RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addGpsStatusListener(GpsStatus.Listener listener) {
boolean result;
@@ -1538,6 +1568,7 @@ public class LocationManager {
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
*/
+ @RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
boolean result;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index eeac69a..6eaf812 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -57,7 +57,8 @@ import java.util.Iterator;
*/
public class AudioManager {
- private final Context mApplicationContext;
+ private Context mOriginalContext;
+ private Context mApplicationContext;
private long mVolumeKeyUpTime;
private final boolean mUseVolumeKeySounds;
private final boolean mUseFixedVolume;
@@ -621,14 +622,33 @@ public class AudioManager {
* @hide
*/
public AudioManager(Context context) {
- mApplicationContext = context;
- mUseVolumeKeySounds = mApplicationContext.getResources().getBoolean(
+ setContext(context);
+ mUseVolumeKeySounds = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_useVolumeKeySounds);
- mUseFixedVolume = mApplicationContext.getResources().getBoolean(
+ mUseFixedVolume = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
sAudioPortEventHandler.init();
}
+ private Context getContext() {
+ if (mApplicationContext == null) {
+ setContext(mOriginalContext);
+ }
+ if (mApplicationContext != null) {
+ return mApplicationContext;
+ }
+ return mOriginalContext;
+ }
+
+ private void setContext(Context context) {
+ mApplicationContext = context.getApplicationContext();
+ if (mApplicationContext != null) {
+ mOriginalContext = null;
+ } else {
+ mOriginalContext = context;
+ }
+ }
+
private static IAudioService getService()
{
if (sService != null) {
@@ -663,7 +683,7 @@ public class AudioManager {
* or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}.
*/
public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
helper.sendMediaButtonEvent(keyEvent, false);
}
@@ -709,7 +729,7 @@ public class AudioManager {
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (event.getRepeatCount() == 0) {
- MediaSessionLegacyHelper.getHelper(mApplicationContext)
+ MediaSessionLegacyHelper.getHelper(getContext())
.sendVolumeKeyEvent(event, false);
}
break;
@@ -737,7 +757,7 @@ public class AudioManager {
mVolumeKeyUpTime = SystemClock.uptimeMillis();
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
- MediaSessionLegacyHelper.getHelper(mApplicationContext)
+ MediaSessionLegacyHelper.getHelper(getContext())
.sendVolumeKeyEvent(event, false);
break;
}
@@ -783,7 +803,7 @@ public class AudioManager {
IAudioService service = getService();
try {
service.adjustStreamVolume(streamType, direction, flags,
- mApplicationContext.getOpPackageName());
+ getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustStreamVolume", e);
}
@@ -813,7 +833,7 @@ public class AudioManager {
* @see #isVolumeFixed()
*/
public void adjustVolume(int direction, int flags) {
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
}
@@ -842,7 +862,7 @@ public class AudioManager {
* @see #isVolumeFixed()
*/
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
}
@@ -850,7 +870,7 @@ public class AudioManager {
public void setMasterMute(boolean mute, int flags) {
IAudioService service = getService();
try {
- service.setMasterMute(mute, flags, mApplicationContext.getOpPackageName());
+ service.setMasterMute(mute, flags, getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setMasterMute", e);
}
@@ -997,7 +1017,7 @@ public class AudioManager {
}
IAudioService service = getService();
try {
- service.setRingerModeExternal(ringerMode, mApplicationContext.getOpPackageName());
+ service.setRingerModeExternal(ringerMode, getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setRingerMode", e);
}
@@ -1018,7 +1038,7 @@ public class AudioManager {
public void setStreamVolume(int streamType, int index, int flags) {
IAudioService service = getService();
try {
- service.setStreamVolume(streamType, index, flags, mApplicationContext.getOpPackageName());
+ service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setStreamVolume", e);
}
@@ -1331,7 +1351,7 @@ public class AudioManager {
* @see #startBluetoothSco()
*/
public boolean isBluetoothScoAvailableOffCall() {
- return mApplicationContext.getResources().getBoolean(
+ return getContext().getResources().getBoolean(
com.android.internal.R.bool.config_bluetooth_sco_off_call);
}
@@ -1384,7 +1404,7 @@ public class AudioManager {
IAudioService service = getService();
try {
service.startBluetoothSco(mICallBack,
- mApplicationContext.getApplicationInfo().targetSdkVersion);
+ getContext().getApplicationInfo().targetSdkVersion);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in startBluetoothSco", e);
}
@@ -1532,7 +1552,7 @@ public class AudioManager {
public void setMicrophoneMute(boolean on){
IAudioService service = getService();
try {
- service.setMicrophoneMute(on, mApplicationContext.getOpPackageName());
+ service.setMicrophoneMute(on, getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setMicrophoneMute", e);
}
@@ -1963,7 +1983,7 @@ public class AudioManager {
* Settings has an in memory cache, so this is fast.
*/
private boolean querySoundEffectsEnabled(int user) {
- return Settings.System.getIntForUser(mApplicationContext.getContentResolver(),
+ return Settings.System.getIntForUser(getContext().getContentResolver(),
Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0;
}
@@ -2375,7 +2395,7 @@ public class AudioManager {
try {
status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
mAudioFocusDispatcher, getIdForAudioFocusListener(l),
- mApplicationContext.getOpPackageName() /* package name */, flags,
+ getContext().getOpPackageName() /* package name */, flags,
ap != null ? ap.cb() : null);
} catch (RemoteException e) {
Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
@@ -2400,7 +2420,7 @@ public class AudioManager {
.setInternalLegacyStreamType(streamType).build(),
durationHint, mICallBack, null,
AudioSystem.IN_VOICE_COMM_FOCUS_ID,
- mApplicationContext.getOpPackageName(),
+ getContext().getOpPackageName(),
AUDIOFOCUS_FLAG_LOCK,
null /* policy token */);
} catch (RemoteException e) {
@@ -2469,7 +2489,7 @@ public class AudioManager {
if (eventReceiver == null) {
return;
}
- if (!eventReceiver.getPackageName().equals(mApplicationContext.getPackageName())) {
+ if (!eventReceiver.getPackageName().equals(getContext().getPackageName())) {
Log.e(TAG, "registerMediaButtonEventReceiver() error: " +
"receiver and context package names don't match");
return;
@@ -2478,7 +2498,7 @@ public class AudioManager {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
// the associated intent will be handled by the component being registered
mediaButtonIntent.setComponent(eventReceiver);
- PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext,
+ PendingIntent pi = PendingIntent.getBroadcast(getContext(),
0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
registerMediaButtonIntent(pi, eventReceiver);
}
@@ -2512,8 +2532,8 @@ public class AudioManager {
Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
return;
}
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
- helper.addMediaButtonListener(pi, eventReceiver, mApplicationContext);
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
+ helper.addMediaButtonListener(pi, eventReceiver, getContext());
}
/**
@@ -2531,7 +2551,7 @@ public class AudioManager {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
// the associated intent will be handled by the component being registered
mediaButtonIntent.setComponent(eventReceiver);
- PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext,
+ PendingIntent pi = PendingIntent.getBroadcast(getContext(),
0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
unregisterMediaButtonIntent(pi);
}
@@ -2554,7 +2574,7 @@ public class AudioManager {
* @hide
*/
public void unregisterMediaButtonIntent(PendingIntent pi) {
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
helper.removeMediaButtonListener(pi);
}
@@ -2571,7 +2591,7 @@ public class AudioManager {
if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
return;
}
- rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mApplicationContext));
+ rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(getContext()));
}
/**
@@ -2586,7 +2606,7 @@ public class AudioManager {
if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
return;
}
- rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mApplicationContext));
+ rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(getContext()));
}
/**
@@ -3280,7 +3300,7 @@ public class AudioManager {
*/
public void setRingerModeInternal(int ringerMode) {
try {
- getService().setRingerModeInternal(ringerMode, mApplicationContext.getOpPackageName());
+ getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName());
} catch (RemoteException e) {
Log.w(TAG, "Error calling setRingerModeInternal", e);
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 77adb39..6ec10c7 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -42,6 +42,7 @@ import android.system.OsConstants;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
+import android.widget.VideoView;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaFormat;
@@ -2121,6 +2122,43 @@ public class MediaPlayer implements SubtitleController.Listener
mSubtitleController.setAnchor(anchor);
}
+ /**
+ * The private version of setSubtitleAnchor is used internally to set mSubtitleController if
+ * necessary when clients don't provide their own SubtitleControllers using the public version
+ * {@link #setSubtitleAnchor(SubtitleController, Anchor)} (e.g. {@link VideoView} provides one).
+ */
+ private synchronized void setSubtitleAnchor() {
+ if (mSubtitleController == null) {
+ final HandlerThread thread = new HandlerThread("SetSubtitleAnchorThread");
+ thread.start();
+ Handler handler = new Handler(thread.getLooper());
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ Context context = ActivityThread.currentApplication();
+ mSubtitleController = new SubtitleController(context, mTimeProvider, MediaPlayer.this);
+ mSubtitleController.setAnchor(new Anchor() {
+ @Override
+ public void setSubtitleWidget(RenderingWidget subtitleWidget) {
+ }
+
+ @Override
+ public Looper getSubtitleLooper() {
+ return Looper.getMainLooper();
+ }
+ });
+ thread.getLooper().quitSafely();
+ }
+ });
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Log.w(TAG, "failed to join SetSubtitleAnchorThread");
+ }
+ }
+ }
+
private final Object mInbandSubtitleLock = new Object();
private SubtitleTrack[] mInbandSubtitleTracks;
private int mSelectedSubtitleTrackIndex = -1;
@@ -2381,24 +2419,14 @@ public class MediaPlayer implements SubtitleController.Listener
fFormat.setString(MediaFormat.KEY_MIME, mime);
fFormat.setInteger(MediaFormat.KEY_IS_TIMED_TEXT, 1);
- Context context = ActivityThread.currentApplication();
// A MediaPlayer created by a VideoView should already have its mSubtitleController set.
if (mSubtitleController == null) {
- mSubtitleController = new SubtitleController(context, mTimeProvider, this);
- mSubtitleController.setAnchor(new Anchor() {
- @Override
- public void setSubtitleWidget(RenderingWidget subtitleWidget) {
- }
-
- @Override
- public Looper getSubtitleLooper() {
- return Looper.getMainLooper();
- }
- });
+ setSubtitleAnchor();
}
if (!mSubtitleController.hasRendererFor(fFormat)) {
// test and add not atomic
+ Context context = ActivityThread.currentApplication();
mSubtitleController.registerRenderer(new SRTRenderer(context, mEventHandler));
}
final SubtitleTrack track = mSubtitleController.addTrack(fFormat);
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index ecc87e7..a5b0d39 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -312,13 +312,13 @@ final public class MediaSync {
* @throws IllegalArgumentException if the surface has been released, is invalid,
* or can not be connected.
* @throws IllegalStateException if setting the surface is not supported, e.g.
- * not in the Initialized state, or another surface has already been configured.
+ * not in the Initialized state, or another surface has already been set.
*/
public void setSurface(@Nullable Surface surface) {
- native_configureSurface(surface);
+ native_setSurface(surface);
}
- private native final void native_configureSurface(@Nullable Surface surface);
+ private native final void native_setSurface(@Nullable Surface surface);
/**
* Sets the audio track for MediaSync.
@@ -328,21 +328,17 @@ final public class MediaSync {
* @param audioTrack Specify an AudioTrack through which to render the audio data.
* @throws IllegalArgumentException if the audioTrack has been released, or is invalid.
* @throws IllegalStateException if setting the audio track is not supported, e.g.
- * not in the Initialized state, or another audio track has already been configured.
+ * not in the Initialized state, or another audio track has already been set.
*/
public void setAudioTrack(@Nullable AudioTrack audioTrack) {
- // AudioTrack has sanity check for configured sample rate.
- int nativeSampleRateInHz = (audioTrack == null ? 0 : audioTrack.getSampleRate());
-
- native_configureAudioTrack(audioTrack, nativeSampleRateInHz);
+ native_setAudioTrack(audioTrack);
mAudioTrack = audioTrack;
if (audioTrack != null && mAudioThread == null) {
createAudioThread();
}
}
- private native final void native_configureAudioTrack(
- @Nullable AudioTrack audioTrack, int nativeSampleRateInHz);
+ private native final void native_setAudioTrack(@Nullable AudioTrack audioTrack);
/**
* Requests a Surface to use as the input. This may only be called after
@@ -350,7 +346,7 @@ final public class MediaSync {
* <p>
* The application is responsible for calling release() on the Surface when
* done.
- * @throws IllegalStateException if not configured, or another input surface has
+ * @throws IllegalStateException if not set, or another input surface has
* already been created.
*/
@NonNull
@@ -574,7 +570,7 @@ final public class MediaSync {
* @param sizeInBytes number of bytes to queue.
* @param presentationTimeUs the presentation timestamp in microseconds for the first frame
* in the buffer.
- * @throws IllegalStateException if audio track is not configured or internal configureation
+ * @throws IllegalStateException if audio track is not set or internal configureation
* has not been done correctly.
*/
public void queueAudio(
@@ -582,7 +578,7 @@ final public class MediaSync {
long presentationTimeUs) {
if (mAudioTrack == null || mAudioThread == null) {
throw new IllegalStateException(
- "AudioTrack is NOT configured or audio thread is not created");
+ "AudioTrack is NOT set or audio thread is not created");
}
synchronized(mAudioLock) {
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 966e41a..daeb1cc 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -171,6 +171,14 @@ import java.util.Objects;
* <td>TV content rating system for Brazil</td>
* </tr>
* <tr>
+ * <td>CA_TV_EN</td>
+ * <td>TV content rating system for Canada (English)</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_FR</td>
+ * <td>TV content rating system for Canada (French)</td>
+ * </tr>
+ * <tr>
* <td>DVB</td>
* <td>DVB content rating system</td>
* </tr>
@@ -195,6 +203,10 @@ import java.util.Objects;
* <td>TV content rating system for Singapore</td>
* </tr>
* <tr>
+ * <td>US_MV</td>
+ * <td>Movie content rating system for the United States</td>
+ * </tr>
+ * <tr>
* <td>US_TV</td>
* <td>TV content rating system for the United States</td>
* </tr>
@@ -290,6 +302,60 @@ import java.util.Objects;
* <td>Content suitable for viewers over the age of 18</td>
* </tr>
* <tr>
+ * <td valign="top" rowspan="7">CA_TV_EN</td>
+ * <td>CA_TV_EN_EXEMPT</td>
+ * <td>Exempt from ratings</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_EN_C</td>
+ * <td>Suitable for children ages 2&#8211;7</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_EN_C8</td>
+ * <td>Suitable for children ages 8 and older</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_EN_G</td>
+ * <td>Suitable for the entire family</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_EN_PG</td>
+ * <td>May contain moderate violence, profanity, nudity, and sexual references</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_EN_14</td>
+ * <td>Intended for viewers ages 14 and older</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_EN_18</td>
+ * <td>Intended for viewers ages 18 and older</td>
+ * </tr>
+ * <tr>
+ * <td valign="top" rowspan="6">CA_TV_FR</td>
+ * <td>CA_TV_FR_E</td>
+ * <td>Exempt from ratings</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_FR_G</td>
+ * <td>Appropriate for all ages</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_FR_8</td>
+ * <td>Appropriate for children 8</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_FR_13</td>
+ * <td>Suitable for children 13</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_FR_16</td>
+ * <td>Recommended for children over the age of 16</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_FR_18</td>
+ * <td>Only to be viewed by adults</td>
+ * </tr>
+ * <tr>
* <td valign="top" rowspan="15">DVB</td>
* <td>DVB_4</td>
* <td>Recommended for ages 4 and over</td>
@@ -608,6 +674,27 @@ import java.util.Objects;
* <td>Suitable for adults aged 21 and above</td>
* </tr>
* <tr>
+ * <td valign="top" rowspan="5">US_MV</td>
+ * <td>US_MV_G</td>
+ * <td>General audiences</td>
+ * </tr>
+ * <tr>
+ * <td>US_MV_PG</td>
+ * <td>Parental guidance suggested</td>
+ * </tr>
+ * <tr>
+ * <td>US_MV_PG13</td>
+ * <td>Parents strongly cautioned</td>
+ * </tr>
+ * <tr>
+ * <td>US_MV_R</td>
+ * <td>Restricted, under 17 requires accompanying parent or adult guardian</td>
+ * </tr>
+ * <tr>
+ * <td>US_MV_NC17</td>
+ * <td>No one 17 and under admitted</td>
+ * </tr>
+ * <tr>
* <td valign="top" rowspan="6">US_TV</td>
* <td>US_TV_Y</td>
* <td>This program is designed to be appropriate for all children</td>
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
index 8ad4b71..5c18901 100644
--- a/media/jni/android_media_MediaSync.cpp
+++ b/media/jni/android_media_MediaSync.cpp
@@ -61,12 +61,12 @@ JMediaSync::JMediaSync() {
JMediaSync::~JMediaSync() {
}
-status_t JMediaSync::configureSurface(const sp<IGraphicBufferProducer> &bufferProducer) {
- return mSync->configureSurface(bufferProducer);
+status_t JMediaSync::setSurface(const sp<IGraphicBufferProducer> &bufferProducer) {
+ return mSync->setSurface(bufferProducer);
}
-status_t JMediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) {
- return mSync->configureAudioTrack(audioTrack);
+status_t JMediaSync::setAudioTrack(const sp<AudioTrack> &audioTrack) {
+ return mSync->setAudioTrack(audioTrack);
}
status_t JMediaSync::createInputSurface(
@@ -163,9 +163,9 @@ static void throwExceptionAsNecessary(
}
}
-static void android_media_MediaSync_native_configureSurface(
+static void android_media_MediaSync_native_setSurface(
JNIEnv *env, jobject thiz, jobject jsurface) {
- ALOGV("android_media_MediaSync_configureSurface");
+ ALOGV("android_media_MediaSync_setSurface");
sp<JMediaSync> sync = getMediaSync(env, thiz);
if (sync == NULL) {
@@ -184,7 +184,7 @@ static void android_media_MediaSync_native_configureSurface(
}
}
- status_t err = sync->configureSurface(bufferProducer);
+ status_t err = sync->setSurface(bufferProducer);
if (err == INVALID_OPERATION) {
throwExceptionAsNecessary(
@@ -196,9 +196,9 @@ static void android_media_MediaSync_native_configureSurface(
}
}
-static void android_media_MediaSync_native_configureAudioTrack(
+static void android_media_MediaSync_native_setAudioTrack(
JNIEnv *env, jobject thiz, jobject jaudioTrack) {
- ALOGV("android_media_MediaSync_configureAudioTrack");
+ ALOGV("android_media_MediaSync_setAudioTrack");
sp<JMediaSync> sync = getMediaSync(env, thiz);
if (sync == NULL) {
@@ -215,7 +215,7 @@ static void android_media_MediaSync_native_configureAudioTrack(
}
}
- status_t err = sync->configureAudioTrack(audioTrack);
+ status_t err = sync->setAudioTrack(audioTrack);
if (err == INVALID_OPERATION) {
throwExceptionAsNecessary(
@@ -501,13 +501,13 @@ static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) {
}
static JNINativeMethod gMethods[] = {
- { "native_configureSurface",
+ { "native_setSurface",
"(Landroid/view/Surface;)V",
- (void *)android_media_MediaSync_native_configureSurface },
+ (void *)android_media_MediaSync_native_setSurface },
- { "native_configureAudioTrack",
- "(Landroid/media/AudioTrack;I)V",
- (void *)android_media_MediaSync_native_configureAudioTrack },
+ { "native_setAudioTrack",
+ "(Landroid/media/AudioTrack;)V",
+ (void *)android_media_MediaSync_native_setAudioTrack },
{ "createInputSurface", "()Landroid/view/Surface;",
(void *)android_media_MediaSync_createInputSurface },
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
index 80f5d63..fa5e5e0 100644
--- a/media/jni/android_media_MediaSync.h
+++ b/media/jni/android_media_MediaSync.h
@@ -33,8 +33,8 @@ class MediaSync;
struct JMediaSync : public RefBase {
JMediaSync();
- status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer);
- status_t configureAudioTrack(const sp<AudioTrack> &audioTrack);
+ status_t setSurface(const sp<IGraphicBufferProducer> &bufferProducer);
+ status_t setAudioTrack(const sp<AudioTrack> &audioTrack);
status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 41bd168..cac6021 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -65,9 +65,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી રહ્યાં છે.</item>
</plurals>
<string name="copy_preparing" msgid="3896202461003039386">"કૉપિ માટે તૈયારી કરી રહ્યું છે…"</string>
- <!-- no translation found for copy_error_notification_title (5267616889076217261) -->
+ <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી શકાઈ નથી</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી શકાઈ નથી</item>
+ </plurals>
<string name="notification_touch_for_details" msgid="4483108577842961665">"વિગતો જોવા માટે ટચ કરો"</string>
<string name="retry" msgid="7564024179122207376">"ફરી પ્રયાસ કરો"</string>
- <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
- <skip />
+ <string name="copy_failure_alert_content" msgid="3715575000297709082">"આ ફાઇલો કૉપિ કરી નહોતી: <xliff:g id="LIST">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 978ea5a..56e4aa8 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -65,9 +65,11 @@
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ।</item>
</plurals>
<string name="copy_preparing" msgid="3896202461003039386">"ਕਾਪੀ ਲਈ ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ…"</string>
- <!-- no translation found for copy_error_notification_title (5267616889076217261) -->
+ <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261">
+ <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾ ਸਕਿਆ</item>
+ <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾ ਸਕਿਆ</item>
+ </plurals>
<string name="notification_touch_for_details" msgid="4483108577842961665">"ਵੇਰਵੇ ਵੇਖਣ ਲਈ ਸਪਰਸ਼ ਕਰੋ"</string>
<string name="retry" msgid="7564024179122207376">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
- <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
- <skip />
+ <string name="copy_failure_alert_content" msgid="3715575000297709082">"ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾਈ ਗਈ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 0e10e5d..37c063f 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -65,9 +65,11 @@
<item quantity="one">Po kopjon <xliff:g id="COUNT_0">%1$d</xliff:g> skedar.</item>
</plurals>
<string name="copy_preparing" msgid="3896202461003039386">"Po përgatitet për kopjimin…"</string>
- <!-- no translation found for copy_error_notification_title (5267616889076217261) -->
+ <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> skedarë nuk mund të kopjoheshin</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> skedar nuk mund të kopjohej</item>
+ </plurals>
<string name="notification_touch_for_details" msgid="4483108577842961665">"Prek për të parë detajet"</string>
<string name="retry" msgid="7564024179122207376">"Provo përsëri"</string>
- <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
- <skip />
+ <string name="copy_failure_alert_content" msgid="3715575000297709082">"Këta skedarë nuk u kopjuan: <xliff:g id="LIST">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml
index d356588..f3943ea 100644
--- a/packages/Keyguard/res/values-sq-rAL/strings.xml
+++ b/packages/Keyguard/res/values-sq-rAL/strings.xml
@@ -108,6 +108,6 @@
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodi u pranua!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nuk ka shërbim."</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butoni i metodës së ndërrimit të hyrjeve."</string>
- <string name="airplane_mode" msgid="3122107900897202805">"Modaliteti i aeroplanit"</string>
+ <string name="airplane_mode" msgid="3122107900897202805">"Modaliteti \"në aeroplan\""</string>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nuk njihet"</string>
</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 25b1875..1cabcdf 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -104,6 +105,12 @@ public class EmergencyButton extends Button {
updateEmergencyCallButton();
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateEmergencyCallButton();
+ }
+
/**
* Shows the emergency dialer or returns the user to the existing call.
*/
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index ae4baad..4d89a8d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -260,7 +260,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
SecurityMode mode = mSecurityModel.getSecurityMode();
- final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
final int failedAttemptsBeforeWipe =
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b8d9053..c7b7628 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -65,6 +65,7 @@ import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import com.google.android.collect.Lists;
@@ -139,7 +140,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private BatteryStatus mBatteryStatus;
// Password attempts
- private int mFailedAttempts = 0;
+ private SparseIntArray mFailedAttempts = new SparseIntArray();
private boolean mClockVisible;
@@ -1260,28 +1261,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
return mDeviceProvisioned;
}
- public int getFailedUnlockAttempts() {
- return mFailedAttempts;
- }
-
public void clearFailedUnlockAttempts() {
- mFailedAttempts = 0;
+ mFailedAttempts.delete(sCurrentUser);
}
- public void clearFingerprintRecognized() {
- mUserFingerprintAuthenticated.clear();
+ public int getFailedUnlockAttempts() {
+ return mFailedAttempts.get(sCurrentUser, 0);
}
public void reportFailedUnlockAttempt() {
- mFailedAttempts++;
- }
-
- public boolean isClockVisible() {
- return mClockVisible;
+ mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1);
}
- public int getPhoneState() {
- return mPhoneState;
+ public void clearFingerprintRecognized() {
+ mUserFingerprintAuthenticated.clear();
}
public boolean isSimPinVoiceSecure() {
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index 01eb719..0fbde0e 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -66,8 +66,8 @@
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri ndeshi në gabim gjatë punës: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeri bllokoi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> punë printimi</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> punë printimi</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> punë për printim</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> punë për printim</item>
</plurals>
<string name="cancel" msgid="4373674107267141885">"Anulo"</string>
<string name="restart" msgid="2472034227037808749">"Rifillo"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 6876222..b2c9cd0 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -72,6 +72,9 @@
<!-- Status message of Wi-Fi when network has matching passpoint credentials. [CHAR LIMIT=NONE] -->
<string name="available_via_passpoint">Available via %1$s</string>
+ <!-- Summary for Connected wifi network without internet -->
+ <string name="wifi_connected_no_internet">Connected, no Internet</string>
+
<!-- Bluetooth settings. Message when a device is disconnected -->
<string name="bluetooth_disconnected">Disconnected</string>
<!-- Bluetooth settings. Message when disconnecting from a device -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 2fde4f9..53e69e3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -17,9 +17,13 @@
package com.android.settingslib.wifi;
import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
+import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -27,6 +31,8 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.TextUtils;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
import android.util.LruCache;
@@ -700,6 +706,25 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
}
+ // Case when there is wifi connected without internet connectivity.
+ final ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (state == DetailedState.CONNECTED) {
+ IWifiManager wifiManager = IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ Network nw;
+
+ try {
+ nw = wifiManager.getCurrentNetwork();
+ } catch (RemoteException e) {
+ nw = null;
+ }
+ NetworkCapabilities nc = cm.getNetworkCapabilities(nw);
+ if (nc != null && !nc.hasCapability(nc.NET_CAPABILITY_VALIDATED)) {
+ return context.getString(R.string.wifi_connected_no_internet);
+ }
+ }
+
String[] formats = context.getResources().getStringArray((ssid == null)
? R.array.wifi_status : R.array.wifi_status_with_ssid);
int index = state.ordinal();
diff --git a/packages/SettingsProvider/res/values-sq-rAL/defaults.xml b/packages/SettingsProvider/res/values-sq-rAL/defaults.xml
new file mode 100644
index 0000000..22443a5
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sq-rAL/defaults.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
+ <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index fee2593..723a4d4 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -362,20 +362,13 @@
<string name="monitoring_title" msgid="169206259253048106">"ਨੈਟਵਰਕ ਨਿਰੀਖਣ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="disable_vpn" msgid="4435534311510272506">"VPN ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"VPN ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
- <!-- no translation found for monitoring_description_device_owned (5780988291898461883) -->
- <skip />
- <!-- no translation found for monitoring_description_profile_owned (8110044290898637925) -->
- <skip />
- <!-- no translation found for monitoring_description_device_and_profile_owned (1664428184778531249) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn (912328761766161919) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_owned (3090670777499161246) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_profile_owned (2224494839524715272) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_and_profile_owned (2198546817407897093) -->
- <skip />
+ <string name="monitoring_description_device_owned" msgid="5780988291898461883">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਸ, ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਡਾਟਾ ਅਤੇ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਜਾਣਕਾਰੀ ਦਾ ਨਿਰੀਖਣ ਅਤੇ ਉਸਨੂੰ ਵਿਵਸਥਿਤ ਕਰ ਸਕਦਾ ਹੈ। ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_profile_owned" msgid="8110044290898637925">"ਤੁਹਾਡੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ <xliff:g id="ORGANIZATION">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣਾ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="1664428184778531249">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਇਸ ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>.\nਤੁਹਾਡੀ ਕੰਮਪ੍ਰੋਫਾਈਲ ਇਸ ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਅਤੇ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ ਜਿਸ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_vpn" msgid="912328761766161919">"ਤੁਸੀਂ ਇੱਕ ਐਪ ਨੂੰ ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈਟ ਅਪ ਕਰਨ ਦੀ ਅਨੁਮਤੀ ਦਿੱਤੀ ਹੈ।\n\nਇਹ ਐਪ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਅਤੇ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।"</string>
+ <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ <xliff:g id="ORGANIZATION">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਪ੍ਰਬੰਧਕ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਸ, ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਡਾਟਾ ਅਤੇ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਜਾਣਕਾਰੀ ਦਾ ਨਿਰੀਖਣ ਅਤੇ ਉਸਨੂੰ ਵਿਵਸਥਿਤ ਕਰ ਸਕਦਾ ਹੈ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਕੀਤਾ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="2224494839524715272">"ਤੁਹਾਡੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ <xliff:g id="ORGANIZATION">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣਾ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਕੀਤਾ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="2198546817407897093">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ <xliff:g id="ORGANIZATION_0">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\nਤੁਹਾਡੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਇਸ ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੈ ਜਿਸ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ। \n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਕੀਤਾ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ਡਿਵਾਈਸ ਲੌਕ ਰਹੇਗੀ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"ਤੇਜ਼ੀ ਨਾਲ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ਅਨਲੌਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਹਨਾਂ ਨੂੰ ਦੇਖੋ"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index e70254c..38fdcfd 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -179,12 +179,12 @@
<string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Modaliteti \"në aeroplan\" është i aktivizuar."</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Modaliteti \"në aeroplan\" është i çaktivizuar."</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modaliteti \"në aeroplan\" është i aktivizuar."</string>
- <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Mos shqetëso\" i aktivizuar, vetëm me prioritet."</string>
- <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Mos shqetëso\" i aktivizuar, asnjë ndërprerje."</string>
- <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"\"Mos shqetëso\" i aktivizuar, vetëm alarmet."</string>
- <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Mos shqetëso\" i çaktivizuar."</string>
- <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Mos shqetëso\" i çaktivizuar."</string>
- <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Mos shqetëso\" i aktivizuar."</string>
+ <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Mos shqetëso\" është i aktivizuar, vetëm me prioritet."</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Mos shqetëso\" është i aktivizuar, asnjë ndërprerje."</string>
+ <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"\"Mos shqetëso\" është i aktivizuar, vetëm alarmet."</string>
+ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Mos shqetëso\" është i çaktivizuar."</string>
+ <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Mos shqetëso\" është i çaktivizuar."</string>
+ <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Mos shqetëso\" është i aktivizuar."</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"\"Bluetooth-i\" është i çaktivizuar."</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"\"Bluetooth-i\" është i aktivizuar."</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"\"Bluetooth-i\" po lidhet."</string>
@@ -362,20 +362,13 @@
<string name="monitoring_title" msgid="169206259253048106">"Monitorimi i rrjetit"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Çaktivizo VPN-në"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Shkëput VPN-në"</string>
- <!-- no translation found for monitoring_description_device_owned (5780988291898461883) -->
- <skip />
- <!-- no translation found for monitoring_description_profile_owned (8110044290898637925) -->
- <skip />
- <!-- no translation found for monitoring_description_device_and_profile_owned (1664428184778531249) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn (912328761766161919) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_owned (3090670777499161246) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_profile_owned (2224494839524715272) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_and_profile_owned (2198546817407897093) -->
- <skip />
+ <string name="monitoring_description_device_owned" msgid="5780988291898461883">"Pajisja jote menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë dhe të menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde. Për më shumë informacione, kontakto me administratorin tënd."</string>
+ <string name="monitoring_description_profile_owned" msgid="8110044290898637925">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin e rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd."</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="1664428184778531249">"Pajisja jote menaxhohet nga:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>.\nProfili yt i punës menaxhohet nga:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nAdministratori yt mund të monitorojë pajisjen tënde dhe aktivitetin e rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin."</string>
+ <string name="monitoring_description_vpn" msgid="912328761766161919">"I dhe leje një aplikacioni që të konfigurojë një lidhje VPN.\n\nKy aplikacion mund të monitorojë pajisjen tënde dhe aktivitetin e rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit."</string>
+ <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"Pajisja jote menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë dhe të menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen dhe informacionet e vendndodhjes së pajisjes.\n\nJe i lidhur me një rrjet VPN që mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e uebit.\n\nPër më shumë informacione, kontakto me administratorin."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="2224494839524715272">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd.\n\nJe i lidhur po ashtu me një rrjet VPN që mund të monitorojë aktivitetin tënd të rrjetit."</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="2198546817407897093">"Pajisja jote menaxhohet nga <xliff:g id="ORGANIZATION_0">%1$s</xliff:g>.\nProfili yt i punës menaxhohet nga:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd.\n\nJe i lidhur po ashtu me një rrjet VPN që mund të monitorojë aktivitetin e rrjetit tënd personal"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Pajisje do të qëndrojë e kyçur derisa ta shkyçësh manualisht"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Merr njoftime më shpejt"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Shikoji para se t\'i shkyçësh"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 26c3b4e..588ec26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -238,6 +238,8 @@ public abstract class BaseStatusBar extends SystemUI implements
protected DismissView mDismissView;
protected EmptyShadeView mEmptyShadeView;
+ private NotificationClicker mNotificationClicker = new NotificationClicker();
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -1292,13 +1294,7 @@ public abstract class BaseStatusBar extends SystemUI implements
row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}
- PendingIntent contentIntent = sbn.getNotification().contentIntent;
- if (contentIntent != null) {
- final View.OnClickListener listener = makeClicker(contentIntent, sbn.getKey());
- row.setOnClickListener(listener);
- } else {
- row.setOnClickListener(null);
- }
+ mNotificationClicker.register(row, sbn);
// set up the adaptive layout
View contentViewLocal = null;
@@ -1559,35 +1555,38 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
- public NotificationClicker makeClicker(PendingIntent intent, String notificationKey) {
- return new NotificationClicker(intent, notificationKey);
- }
+ private final class NotificationClicker implements View.OnClickListener {
+ public void onClick(final View v) {
+ if (!(v instanceof ExpandableNotificationRow)) {
+ Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
+ return;
+ }
- protected class NotificationClicker implements View.OnClickListener {
- private PendingIntent mIntent;
- private final String mNotificationKey;
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ final StatusBarNotification sbn = row.getStatusBarNotification();
+ if (sbn == null) {
+ Log.e(TAG, "NotificationClicker called on an unclickable notification,");
+ return;
+ }
- public NotificationClicker(PendingIntent intent, String notificationKey) {
- mIntent = intent;
- mNotificationKey = notificationKey;
- }
+ final PendingIntent intent = sbn.getNotification().contentIntent;
+ final String notificationKey = sbn.getKey();
- public void onClick(final View v) {
if (NOTIFICATION_CLICK_DEBUG) {
- Log.d(TAG, "Clicked on content of " + mNotificationKey);
+ Log.d(TAG, "Clicked on content of " + notificationKey);
}
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
- final boolean afterKeyguardGone = mIntent.isActivity()
- && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
+ final boolean afterKeyguardGone = intent.isActivity()
+ && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
public boolean onDismiss() {
- if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(mNotificationKey)) {
+ if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
// Release the HUN notification to the shade.
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
- mHeadsUpManager.releaseImmediately(mNotificationKey);
+ mHeadsUpManager.releaseImmediately(notificationKey);
}
new Thread() {
@Override
@@ -1606,9 +1605,9 @@ public abstract class BaseStatusBar extends SystemUI implements
} catch (RemoteException e) {
}
- if (mIntent != null) {
+ if (intent != null) {
try {
- mIntent.send();
+ intent.send();
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
@@ -1616,14 +1615,14 @@ public abstract class BaseStatusBar extends SystemUI implements
// TODO: Dismiss Keyguard.
}
- if (mIntent.isActivity()) {
+ if (intent.isActivity()) {
overrideActivityPendingAppTransition(keyguardShowing
&& !afterKeyguardGone);
}
}
try {
- mBarService.onNotificationClick(mNotificationKey);
+ mBarService.onNotificationClick(notificationKey);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
@@ -1635,10 +1634,19 @@ public abstract class BaseStatusBar extends SystemUI implements
true /* force */, true /* delayed */);
visibilityChanged(false);
- return mIntent != null && mIntent.isActivity();
+ return intent != null && intent.isActivity();
}
}, afterKeyguardGone);
}
+
+ public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
+ final PendingIntent contentIntent = sbn.getNotification().contentIntent;
+ if (contentIntent != null) {
+ row.setOnClickListener(this);
+ } else {
+ row.setOnClickListener(null);
+ }
+ }
}
public void animateCollapsePanels(int flags, boolean force) {
@@ -2037,13 +2045,8 @@ public abstract class BaseStatusBar extends SystemUI implements
publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
}
// update the contentIntent
- final PendingIntent contentIntent = notification.getNotification().contentIntent;
- if (contentIntent != null) {
- final View.OnClickListener listener = makeClicker(contentIntent, notification.getKey());
- entry.row.setOnClickListener(listener);
- } else {
- entry.row.setOnClickListener(null);
- }
+ mNotificationClicker.register(entry.row, notification);
+
entry.row.setStatusBarNotification(notification);
entry.row.notifyContentUpdated();
entry.row.resetHeight();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1a75b8a..8d1d124 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1141,7 +1141,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
if (nai != null) {
synchronized (nai) {
- return new NetworkCapabilities(nai.networkCapabilities);
+ NetworkCapabilities nc = new NetworkCapabilities(nai.networkCapabilities);
+ if (nai.lastValidated) {
+ nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ } else {
+ nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ }
+ return nc;
}
}
return null;
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4fda370..45909db 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -145,10 +145,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private static final char INPUT_METHOD_SEPARATOR = ':';
private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';';
- static final int MSG_SHOW_IM_PICKER = 1;
- static final int MSG_SHOW_IM_SUBTYPE_PICKER = 2;
- static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 3;
- static final int MSG_SHOW_IM_CONFIG = 4;
+ static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1;
+ static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2;
+ static final int MSG_SHOW_IM_CONFIG = 3;
static final int MSG_UNBIND_INPUT = 1000;
static final int MSG_BIND_INPUT = 1010;
@@ -2597,12 +2596,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public boolean handleMessage(Message msg) {
SomeArgs args;
switch (msg.what) {
- case MSG_SHOW_IM_PICKER:
- showInputMethodMenu();
- return true;
-
case MSG_SHOW_IM_SUBTYPE_PICKER:
- showInputMethodSubtypeMenu();
+ showInputMethodMenu();
return true;
case MSG_SHOW_IM_SUBTYPE_ENABLER:
@@ -2861,14 +2856,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// ----------------------------------------------------------------------
- private void showInputMethodMenu() {
- showInputMethodMenuInternal(false);
- }
-
- private void showInputMethodSubtypeMenu() {
- showInputMethodMenuInternal(true);
- }
-
private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -2893,7 +2880,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
&& mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
}
- private void showInputMethodMenuInternal(boolean showSubtypes) {
+ private void showInputMethodMenu() {
if (DEBUG) Slog.v(TAG, "Show switching menu");
final Context context = mContext;
@@ -2915,7 +2902,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final List<ImeSubtypeListItem> imList =
mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
- showSubtypes, mInputShown, isScreenLocked);
+ true /* showSubtypes */, mInputShown, isScreenLocked);
if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
@@ -3016,7 +3003,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
};
mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener);
- if (showSubtypes && !isScreenLocked) {
+ if (!isScreenLocked) {
final OnClickListener positiveListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8c6e290..bc93268 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -678,7 +678,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
handleRemoveListLocked();
}
broadcastCallStateChanged(state, incomingNumber,
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
public void notifyCallStateForSubscriber(int subId, int state, String incomingNumber) {
@@ -1374,6 +1374,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ /**
+ * Broadcasts an intent notifying apps of a phone state change. {@code subId} can be
+ * a valid subId, in which case this function fires a subId-specific intent, or it
+ * can be {@code SubscriptionManager.INVALID_SUBSCRIPTION_ID}, in which case we send
+ * a global state change broadcast ({@code TelephonyManager.ACTION_PHONE_STATE_CHANGED}).
+ */
private void broadcastCallStateChanged(int state, String incomingNumber, int subId) {
long ident = Binder.clearCallingIdentity();
try {
@@ -1394,7 +1400,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (!TextUtils.isEmpty(incomingNumber)) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
}
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+
+ // If a valid subId was specified, we should fire off a subId-specific state
+ // change intent and include the subId.
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ intent.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
+ intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ }
+
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
android.Manifest.permission.READ_PHONE_STATE,
AppOpsManager.OP_READ_PHONE_STATE);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index eea6234..82dbfee 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -414,6 +414,11 @@ public final class ActivityManagerService extends ActivityManagerNative
ActivityRecord mFocusedActivity = null;
/**
+ * User id of the last activity mFocusedActivity was set to.
+ */
+ private int mLastFocusedUserId;
+
+ /**
* List of intents that were used to start the most recent tasks.
*/
private final RecentTasks mRecentTasks;
@@ -2561,19 +2566,32 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.setFocusedApp(r.appToken, true);
}
applyUpdateLockStateLocked(r);
- if (last != null && last.userId != mFocusedActivity.userId) {
+ if (mFocusedActivity.userId != mLastFocusedUserId) {
mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
mHandler.sendMessage(mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG,
mFocusedActivity.userId, 0));
+ mLastFocusedUserId = mFocusedActivity.userId;
}
}
- EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY, mCurrentUserId,
+ EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY,
+ mFocusedActivity == null ? -1 : mFocusedActivity.userId,
mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName);
}
final void clearFocusedActivity(ActivityRecord r) {
if (mFocusedActivity == r) {
+ ActivityStack stack = mStackSupervisor.getFocusedStack();
+ if (stack != null) {
+ ActivityRecord top = stack.topActivity();
+ if (top != null && top.userId != mLastFocusedUserId) {
+ mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
+ mHandler.sendMessage(mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG,
+ top.userId, 0));
+ mLastFocusedUserId = top.userId;
+ }
+ }
mFocusedActivity = null;
+ EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY, -1, "NULL");
}
}
@@ -10754,9 +10772,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void killUid(int uid, String reason) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("killUid only available to the system");
- }
+ enforceCallingPermission(Manifest.permission.KILL_UID, "killUid");
synchronized (this) {
killPackageProcessesLocked(null, UserHandle.getAppId(uid), UserHandle.getUserId(uid),
ProcessList.FOREGROUND_APP_ADJ-1, false, true, true, false,
diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/services/core/java/com/android/server/net/DelayedDiskWrite.java
index 6ed277d..8f09eb7 100644
--- a/services/core/java/com/android/server/net/DelayedDiskWrite.java
+++ b/services/core/java/com/android/server/net/DelayedDiskWrite.java
@@ -38,6 +38,10 @@ public class DelayedDiskWrite {
}
public void write(final String filePath, final Writer w) {
+ write(filePath, w, true);
+ }
+
+ public void write(final String filePath, final Writer w, final boolean open) {
if (TextUtils.isEmpty(filePath)) {
throw new IllegalArgumentException("empty file path");
}
@@ -54,16 +58,18 @@ public class DelayedDiskWrite {
mDiskWriteHandler.post(new Runnable() {
@Override
public void run() {
- doWrite(filePath, w);
+ doWrite(filePath, w, open);
}
});
}
- private void doWrite(String filePath, Writer w) {
+ private void doWrite(String filePath, Writer w, boolean open) {
DataOutputStream out = null;
try {
- out = new DataOutputStream(new BufferedOutputStream(
+ if (open) {
+ out = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream(filePath)));
+ }
w.onWriteCalled(out);
} catch (IOException e) {
loge("Error writing data file " + filePath);
diff --git a/services/core/java/com/android/server/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java
index 8734d97..c82df48 100644
--- a/services/core/java/com/android/server/notification/CalendarTracker.java
+++ b/services/core/java/com/android/server/notification/CalendarTracker.java
@@ -55,7 +55,6 @@ public class CalendarTracker {
Attendees.EVENT_ID,
Attendees.ATTENDEE_EMAIL,
Attendees.ATTENDEE_STATUS,
- Attendees.ATTENDEE_TYPE,
};
private static final String ATTENDEE_SELECTION = Attendees.EVENT_ID + " = ? AND "
@@ -191,16 +190,13 @@ public class CalendarTracker {
final long rowEventId = cursor.getLong(0);
final String rowEmail = cursor.getString(1);
final int status = cursor.getInt(2);
- final int type = cursor.getInt(3);
final boolean meetsReply = meetsReply(filter.reply, status);
- final boolean meetsAttendance = meetsAttendance(filter.attendance, type);
if (DEBUG) Log.d(TAG, (DEBUG_ATTENDEES ? String.format(
"rowEventId=%s, rowEmail=%s, ", rowEventId, rowEmail) : "") +
- String.format("status=%s, type=%s, meetsReply=%s, meetsAttendance=%s",
- attendeeStatusToString(status), attendeeTypeToString(type), meetsReply,
- meetsAttendance));
+ String.format("status=%s, meetsReply=%s",
+ attendeeStatusToString(status), meetsReply));
final boolean eventMeets = rowEventId == eventId && Objects.equals(rowEmail, email)
- && meetsReply && meetsAttendance;
+ && meetsReply;
rt |= eventMeets;
}
return rt;
@@ -232,35 +228,17 @@ public class CalendarTracker {
}
}
- private static String attendeeTypeToString(int type) {
- switch (type) {
- case Attendees.TYPE_NONE: return "TYPE_NONE";
- case Attendees.TYPE_REQUIRED: return "TYPE_REQUIRED";
- case Attendees.TYPE_OPTIONAL: return "TYPE_OPTIONAL";
- case Attendees.TYPE_RESOURCE: return "TYPE_RESOURCE";
- default: return "TYPE_" + type;
- }
- }
-
- private static boolean meetsAttendance(int attendance, int attendeeType) {
- switch (attendance) {
- case EventInfo.ATTENDANCE_OPTIONAL:
- return attendeeType == Attendees.TYPE_OPTIONAL;
- case EventInfo.ATTENDANCE_REQUIRED:
- return attendeeType == Attendees.TYPE_REQUIRED;
- default: // EventInfo.ATTENDANCE_REQUIRED_OR_OPTIONAL
- return true;
- }
- }
-
private static boolean meetsReply(int reply, int attendeeStatus) {
switch (reply) {
case EventInfo.REPLY_YES:
return attendeeStatus == Attendees.ATTENDEE_STATUS_ACCEPTED;
+ case EventInfo.REPLY_YES_OR_MAYBE:
+ return attendeeStatus == Attendees.ATTENDEE_STATUS_ACCEPTED
+ || attendeeStatus == Attendees.ATTENDEE_STATUS_TENTATIVE;
case EventInfo.REPLY_ANY_EXCEPT_NO:
return attendeeStatus != Attendees.ATTENDEE_STATUS_DECLINED;
- default: // EventInfo.REPLY_ANY
- return true;
+ default:
+ return false;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 66dd8f1..f30a5674 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -277,8 +277,6 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
- static final boolean RUNTIME_PERMISSIONS_ENABLED = true;
-
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
@@ -2131,13 +2129,6 @@ public class PackageManagerService extends IPackageManager.Stub {
+ "; regranting permissions for internal storage");
mSettings.mInternalSdkPlatform = mSdkVersion;
- // For now runtime permissions are toggled via a system property.
- if (!RUNTIME_PERMISSIONS_ENABLED) {
- // Remove the runtime permissions state if the feature
- // was disabled by flipping the system property.
- mSettings.deleteRuntimePermissionsFiles();
- }
-
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
| (regrantPermissions
? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
@@ -2162,6 +2153,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
primeDomainVerificationsLPw(false);
+ checkDefaultBrowser();
// All the changes are done during package scanning.
mSettings.updateInternalDatabaseVersion();
@@ -2331,6 +2323,17 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.d(TAG, "End priming domain verifications");
}
+ private void checkDefaultBrowser() {
+ final int myUserId = UserHandle.myUserId();
+ final String packageName = getDefaultBrowserPackageName(myUserId);
+ PackageInfo info = getPackageInfo(packageName, 0, myUserId);
+ if (info == null) {
+ Slog.w(TAG, "Clearing default Browser as its package is no more installed: " +
+ packageName);
+ setDefaultBrowserPackageName(null, myUserId);
+ }
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -3137,13 +3140,9 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- public boolean grantPermission(String packageName, String name, int userId) {
- if (!RUNTIME_PERMISSIONS_ENABLED) {
- return false;
- }
-
+ public void grantPermission(String packageName, String name, int userId) {
if (!sUserManager.exists(userId)) {
- return false;
+ return;
}
mContext.enforceCallingOrSelfPermission(
@@ -3179,12 +3178,13 @@ public class PackageManagerService extends IPackageManager.Stub {
final int result = permissionsState.grantRuntimePermission(bp, userId);
switch (result) {
case PermissionsState.PERMISSION_OPERATION_FAILURE: {
- return false;
+ return;
}
case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
gidsChanged = true;
- } break;
+ }
+ break;
}
// Not critical if that is lost - app has to request again.
@@ -3194,18 +3194,12 @@ public class PackageManagerService extends IPackageManager.Stub {
if (gidsChanged) {
killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
}
-
- return true;
}
@Override
- public boolean revokePermission(String packageName, String name, int userId) {
- if (!RUNTIME_PERMISSIONS_ENABLED) {
- return false;
- }
-
+ public void revokePermission(String packageName, String name, int userId) {
if (!sUserManager.exists(userId)) {
- return false;
+ return;
}
mContext.enforceCallingOrSelfPermission(
@@ -3239,7 +3233,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (permissionsState.revokeRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_FAILURE) {
- return false;
+ return;
}
// Critical, after this call all should never have the permission.
@@ -3247,8 +3241,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
killSettingPackagesForUser(sb, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
-
- return true;
}
@Override
@@ -7592,9 +7584,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} break;
case PermissionInfo.PROTECTION_DANGEROUS: {
- if (!RUNTIME_PERMISSIONS_ENABLED
- || pkg.applicationInfo.targetSdkVersion
- <= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL;
} else if (ps.isSystem()) {
@@ -7733,10 +7723,8 @@ public class PackageManagerService extends IPackageManager.Stub {
ps.setPermissionsUpdatedForUserIds(currentUserIds);
// Persist the runtime permissions state for users with changes.
- if (RUNTIME_PERMISSIONS_ENABLED) {
- for (int userId : changedRuntimePermissionUserIds) {
- mSettings.writeRuntimePermissionsForUserLPr(userId, true);
- }
+ for (int userId : changedRuntimePermissionUserIds) {
+ mSettings.writeRuntimePermissionsForUserLPr(userId, true);
}
}
@@ -9149,7 +9137,11 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public boolean setDefaultBrowserPackageName(String packageName, int userId) {
synchronized (mPackages) {
- return mSettings.setDefaultBrowserPackageNameLPr(packageName, userId);
+ boolean result = mSettings.setDefaultBrowserPackageNameLPr(packageName, userId);
+ result |= updateIntentVerificationStatus(packageName,
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
+ UserHandle.myUserId());
+ return result;
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d3bfdeb..d476bfde 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4165,19 +4165,11 @@ final class Settings {
}
public void writePermissionsForUserSyncLPr(int userId) {
- if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
- return;
- }
-
mHandler.removeMessages(userId);
writePermissionsSync(userId);
}
public void writePermissionsForUserAsyncLPr(int userId) {
- if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
- return;
- }
-
final long currentTimeMillis = SystemClock.uptimeMillis();
if (mWriteScheduled.get(userId)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index adc3a7d..51503ec 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2673,6 +2673,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
return -1;
+ } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
+ if (down) {
+ IStatusBarService service = getStatusBarService();
+ if (service != null) {
+ try {
+ service.expandNotificationsPanel();
+ } catch (RemoteException e) {
+ // do nothing.
+ }
+ }
+ }
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
if (down) {
if (repeatCount == 0) {
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 1e0185d..84eab42 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -390,7 +390,7 @@ public final class ShutdownThread extends Thread {
}
}
- rebootOrShutdown(mReboot, mRebootReason);
+ rebootOrShutdown(mContext, mReboot, mRebootReason);
}
private void shutdownRadios(int timeout) {
@@ -507,17 +507,18 @@ public final class ShutdownThread extends Thread {
* Do not call this directly. Use {@link #reboot(Context, String, boolean)}
* or {@link #shutdown(Context, boolean)} instead.
*
+ * @param context Context used to vibrate or null without vibration
* @param reboot true to reboot or false to shutdown
* @param reason reason for reboot
*/
- public static void rebootOrShutdown(boolean reboot, String reason) {
+ public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
PowerManagerService.lowLevelReboot(reason);
Log.e(TAG, "Reboot failed, will attempt shutdown instead");
- } else if (SHUTDOWN_VIBRATE_MS > 0) {
+ } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
// vibrate before shutting down
- Vibrator vibrator = new SystemVibrator();
+ Vibrator vibrator = new SystemVibrator(context);
try {
vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
} catch (Exception e) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c1153b6..2d265e2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -284,7 +284,7 @@ public final class SystemServer {
reason = null;
}
- ShutdownThread.rebootOrShutdown(reboot, reason);
+ ShutdownThread.rebootOrShutdown(null, reboot, reason);
}
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index cd10050..3060f40 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -339,6 +339,7 @@ public abstract class Connection implements Conferenceable {
public void onConferenceParticipantsChanged(Connection c,
List<ConferenceParticipant> participants) {}
public void onConferenceStarted() {}
+ public void onConferenceMergeFailed(Connection c) {}
}
public static abstract class VideoProvider {
@@ -1544,6 +1545,17 @@ public abstract class Connection implements Conferenceable {
}
/**
+ * Notifies listeners that the merge request failed.
+ *
+ * @hide
+ */
+ protected final void notifyConferenceMergeFailed() {
+ for (Listener l : mListeners) {
+ l.onConferenceMergeFailed(this);
+ }
+ }
+
+ /**
* Notifies listeners of a change to conference participant(s).
*
* @param conferenceParticipants The participants.
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index c039acf..4185651 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -562,6 +562,14 @@ public abstract class ConnectionService extends Service {
mAdapter.setIsConferenced(id, conferenceId);
}
}
+
+ @Override
+ public void onConferenceMergeFailed(Connection connection) {
+ String id = mIdByConnection.get(connection);
+ if (id != null) {
+ mAdapter.onConferenceMergeFailed(id);
+ }
+ }
};
/** {@inheritDoc} */
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index d026a28..a87dbe7 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -203,6 +203,21 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
/**
+ * Indicates that the merge request on this call has failed.
+ *
+ * @param callId The unique ID of the call being conferenced.
+ */
+ void onConferenceMergeFailed(String callId) {
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ Log.d(this, "merge failed for call %s", callId);
+ adapter.setConferenceMergeFailed(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ /**
* Indicates that the call no longer exists. Can be used with either a call or a conference
* call.
*
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 429f296..db815ba 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -59,6 +59,7 @@ final class ConnectionServiceAdapterServant {
private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
private static final int MSG_ADD_EXISTING_CONNECTION = 21;
private static final int MSG_ON_POST_DIAL_CHAR = 22;
+ private static final int MSG_SET_CONFERENCE_MERGE_FAILED = 23;
private final IConnectionServiceAdapter mDelegate;
@@ -220,6 +221,15 @@ final class ConnectionServiceAdapterServant {
}
break;
}
+ case MSG_SET_CONFERENCE_MERGE_FAILED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.setConferenceMergeFailed((String) args.arg1);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
}
}
};
@@ -280,6 +290,13 @@ final class ConnectionServiceAdapterServant {
}
@Override
+ public void setConferenceMergeFailed(String callId) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ mHandler.obtainMessage(MSG_SET_CONFERENCE_MERGE_FAILED, args).sendToTarget();
+ }
+
+ @Override
public void setIsConferenced(String callId, String conferenceCallId) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index e54e79d..3d0c558 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -121,11 +121,10 @@ public final class ParcelableConference implements Parcelable {
List<String> connectionIds = new ArrayList<>(2);
source.readList(connectionIds, classLoader);
long connectTimeMillis = source.readLong();
- StatusHints statusHints = source.readParcelable(classLoader);
-
IVideoProvider videoCallProvider =
IVideoProvider.Stub.asInterface(source.readStrongBinder());
int videoState = source.readInt();
+ StatusHints statusHints = source.readParcelable(classLoader);
return new ParcelableConference(phoneAccount, state, capabilities, connectionIds,
videoCallProvider, videoState, connectTimeMillis, statusHints);
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index a9b725b..0208744 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -176,6 +176,13 @@ final class RemoteConnectionService {
}
@Override
+ public void setConferenceMergeFailed(String callId) {
+ // Nothing to do here.
+ // The event has already been handled and there is no state to update
+ // in the underlying connection or conference objects
+ }
+
+ @Override
public void addConferenceCall(
final String callId,
ParcelableConference parcel) {
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 2fd438a..902fddb 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -144,6 +144,17 @@ public class VideoProfile implements Parcelable {
dest.writeInt(mQuality);
}
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[VideoProfile videoState = ");
+ sb.append(VideoState.videoStateToString(mVideoState));
+ sb.append(" videoQuality = ");
+ sb.append(mQuality);
+ sb.append("]");
+ return sb.toString();
+ }
+
/**
* The video state of the call, stored as a bit-field describing whether video transmission and
* receipt it enabled, as well as whether the video is currently muted.
@@ -241,5 +252,30 @@ public class VideoProfile implements Parcelable {
private static boolean hasState(int videoState, int state) {
return (videoState & state) == state;
}
+
+ /**
+ * Generates a string representation of a {@link VideoState}.
+ *
+ * @param videoState The video state.
+ * @return String representation of the {@link VideoState}.
+ */
+ public static String videoStateToString(int videoState) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Audio");
+
+ if (VideoProfile.VideoState.isTransmissionEnabled(videoState)) {
+ sb.append(" Tx");
+ }
+
+ if (VideoProfile.VideoState.isReceptionEnabled(videoState)) {
+ sb.append(" Rx");
+ }
+
+ if (VideoProfile.VideoState.isPaused(videoState)) {
+ sb.append(" Pause");
+ }
+
+ return sb.toString();
+ }
}
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 7e7e9cc..67e2edb 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -56,6 +56,8 @@ oneway interface IConnectionServiceAdapter {
void setIsConferenced(String callId, String conferenceCallId);
+ void setConferenceMergeFailed(String callId);
+
void addConferenceCall(String callId, in ParcelableConference conference);
void removeCall(String callId);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index e4c003a..33e52bf 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1129,5 +1129,19 @@ public class SubscriptionManager {
logd("getSimStateForSubscriber: simState=" + simState + " subId=" + subId);
return simState;
}
+
+ /**
+ * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription
+ * and the SIM providing the subscription is present in a slot and in "LOADED" state.
+ * @hide
+ */
+ public boolean isActiveSubId(int subId) {
+ try {
+ ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ return iSub.isActiveSubId(subId);
+ } catch (RemoteException ex) {
+ }
+ return false;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 24bdb7a..21c94c2 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -37,13 +37,6 @@ import com.android.internal.telephony.SmsRawData;
interface ISms {
/**
* Retrieves all messages currently stored on ICC.
- *
- * @return list of SmsRawData of all sms on ICC
- */
- List<SmsRawData> getAllMessagesFromIccEf(String callingPkg);
-
- /**
- * Retrieves all messages currently stored on ICC.
* @param subId the subId id.
* @return list of SmsRawData of all sms on ICC
*/
@@ -57,20 +50,6 @@ interface ISms {
* STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
* STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
* @param pdu the raw PDU to store
- * @return success or not
- *
- */
- boolean updateMessageOnIccEf(String callingPkg, int messageIndex, int newStatus,
- in byte[] pdu);
-
- /**
- * Update the specified message on the ICC.
- *
- * @param messageIndex record index of message to update
- * @param newStatus new message status (STATUS_ON_ICC_READ,
- * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
- * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
- * @param pdu the raw PDU to store
* @param subId the subId id.
* @return success or not
*
@@ -84,17 +63,6 @@ interface ISms {
* @param pdu the raw PDU to store
* @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
* STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
- * @return success or not
- *
- */
- boolean copyMessageToIccEf(String callingPkg, int status, in byte[] pdu, in byte[] smsc);
-
- /**
- * Copy a raw SMS PDU to the ICC.
- *
- * @param pdu the raw PDU to store
- * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
- * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
* @param subId the subId id.
* @return success or not
*
@@ -124,32 +92,6 @@ interface ISms {
* @param deliveryIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
- */
- void sendData(String callingPkg, in String destAddr, in String scAddr, in int destPort,
- in byte[] data, in PendingIntent sentIntent, in PendingIntent deliveryIntent);
-
- /**
- * Send a data SMS.
- *
- * @param smsc the SMSC to send the message through, or NULL for the
- * default SMSC
- * @param data the body of the message to send
- * @param sentIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is sucessfully sent, or failed.
- * The result code will be <code>Activity.RESULT_OK<code> for success,
- * or one of these errors:<br>
- * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
- * <code>RESULT_ERROR_RADIO_OFF</code><br>
- * <code>RESULT_ERROR_NULL_PDU</code><br>
- * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
- * the extra "errorCode" containing a radio technology specific value,
- * generally only useful for troubleshooting.<br>
- * The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applicaitons,
- * which cause smaller number of SMS to be sent in checking period.
- * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is delivered to the recipient. The
- * raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId id.
*/
void sendDataForSubscriber(int subId, String callingPkg, in String destAddr,
@@ -206,32 +148,6 @@ interface ISms {
* @param deliveryIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
- */
- void sendText(String callingPkg, in String destAddr, in String scAddr, in String text,
- in PendingIntent sentIntent, in PendingIntent deliveryIntent);
-
- /**
- * Send an SMS.
- *
- * @param smsc the SMSC to send the message through, or NULL for the
- * default SMSC
- * @param text the body of the message to send
- * @param sentIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is sucessfully sent, or failed.
- * The result code will be <code>Activity.RESULT_OK<code> for success,
- * or one of these errors:<br>
- * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
- * <code>RESULT_ERROR_RADIO_OFF</code><br>
- * <code>RESULT_ERROR_NULL_PDU</code><br>
- * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
- * the extra "errorCode" containing a radio technology specific value,
- * generally only useful for troubleshooting.<br>
- * The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applications,
- * which cause smaller number of SMS to be sent in checking period.
- * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is delivered to the recipient. The
- * raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId on which the SMS has to be sent.
*/
void sendTextForSubscriber(in int subId, String callingPkg, in String destAddr,
@@ -269,6 +185,7 @@ interface ISms {
/**
* Inject an SMS PDU into the android platform.
*
+ * @param subId the subId on which the SMS has to be injected.
* @param pdu is the byte array of pdu to be injected into android application framework
* @param format is the format of SMS pdu (android.telephony.SmsMessage.FORMAT_3GPP or
* android.telephony.SmsMessage.FORMAT_3GPP2)
@@ -277,33 +194,8 @@ interface ISms {
* android application framework. This intent is broadcasted at
* the same time an SMS received from radio is acknowledged back.
*/
- void injectSmsPdu(in byte[] pdu, String format, in PendingIntent receivedIntent);
-
- /**
- * Send a multi-part text based SMS.
- *
- * @param destinationAddress the address to send the message to
- * @param scAddress is the service center address or null to use
- * the current default SMSC
- * @param parts an <code>ArrayList</code> of strings that, in order,
- * comprise the original message
- * @param sentIntents if not null, an <code>ArrayList</code> of
- * <code>PendingIntent</code>s (one for each message part) that is
- * broadcast when the corresponding message part has been sent.
- * The result code will be <code>Activity.RESULT_OK<code> for success,
- * or one of these errors:
- * <code>RESULT_ERROR_GENERIC_FAILURE</code>
- * <code>RESULT_ERROR_RADIO_OFF</code>
- * <code>RESULT_ERROR_NULL_PDU</code>.
- * @param deliveryIntents if not null, an <code>ArrayList</code> of
- * <code>PendingIntent</code>s (one for each message part) that is
- * broadcast when the corresponding message part has been delivered
- * to the recipient. The raw pdu of the status report is in the
- * extended data ("pdu").
- */
- void sendMultipartText(String callingPkg, in String destinationAddress, in String scAddress,
- in List<String> parts, in List<PendingIntent> sentIntents,
- in List<PendingIntent> deliveryIntents);
+ void injectSmsPduForSubscriber(
+ int subId, in byte[] pdu, String format, in PendingIntent receivedIntent);
/**
* Send a multi-part text based SMS.
@@ -342,31 +234,13 @@ interface ISms {
*
* @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) or
* C.R1001-G (3GPP2)
- * @param ranType as defined in class SmsManager, the value can be one of these:
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
- * @return true if successful, false otherwise
- *
- * @see #disableCellBroadcast(int, int)
- */
- boolean enableCellBroadcast(int messageIdentifier, int ranType);
-
- /**
- * Enable reception of cell broadcast (SMS-CB) messages with the given
- * message identifier and RAN type. The RAN type specify this message ID
- * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients
- * enable the same message identifier, they must both disable it for the
- * device to stop receiving those messages.
- *
- * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) or
- * C.R1001-G (3GPP2)
* @param subId for which the broadcast has to be enabled
* @param ranType as defined in class SmsManager, the value can be one of these:
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
* @return true if successful, false otherwise
*
- * @see #disableCellBroadcast(int, int)
+ * @see #disableCellBroadcastForSubscriber(int, int, int)
*/
boolean enableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType);
@@ -379,56 +253,18 @@ interface ISms {
*
* @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) or
* C.R1001-G (3GPP2)
- * @param ranType as defined in class SmsManager, the value can be one of these:
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
- * @return true if successful, false otherwise
- *
- * @see #enableCellBroadcast(int, int)
- */
- boolean disableCellBroadcast(int messageIdentifier, int ranType);
-
- /**
- * Disable reception of cell broadcast (SMS-CB) messages with the given
- * message identifier and RAN type. The RAN type specify this message ID
- * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients
- * enable the same message identifier, they must both disable it for the
- * device to stop receiving those messages.
- *
- * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) or
- * C.R1001-G (3GPP2)
* @param subId for which the broadcast has to be disabled
* @param ranType as defined in class SmsManager, the value can be one of these:
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
* @return true if successful, false otherwise
*
- * @see #enableCellBroadcast(int, int)
+ * @see #enableCellBroadcastForSubscriber(int, int, int)
*/
boolean disableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType);
/*
* Enable reception of cell broadcast (SMS-CB) messages with the given
- * message identifier range and RAN type. The RAN type specify this message
- * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different
- * clients enable a message identifier range, they must both disable it for
- * the device to stop receiving those messages.
- *
- * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) or
- * C.R1001-G (3GPP2)
- * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) or
- * C.R1001-G (3GPP2)
- * @param ranType as defined in class SmsManager, the value can be one of these:
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
- * @return true if successful, false otherwise
- *
- * @see #disableCellBroadcastRange(int, int, int)
- */
- boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType);
-
- /*
- * Enable reception of cell broadcast (SMS-CB) messages with the given
* message identifier range and RAN type. The RAN type specify this message ID range
* belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable
* a message identifier range, they must both disable it for the device
@@ -444,7 +280,7 @@ interface ISms {
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
* @return true if successful, false otherwise
*
- * @see #disableCellBroadcastRange(int, int, int)
+ * @see #disableCellBroadcastRangeForSubscriber(int, int, int, int)
*/
boolean enableCellBroadcastRangeForSubscriber(int subId, int startMessageId, int endMessageId,
int ranType);
@@ -460,33 +296,13 @@ interface ISms {
* C.R1001-G (3GPP2)
* @param endMessageId last message identifier as specified in TS 23.041 (3GPP) or
* C.R1001-G (3GPP2)
- * @param ranType as defined in class SmsManager, the value can be one of these:
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
- * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
- * @return true if successful, false otherwise
- *
- * @see #enableCellBroadcastRange(int, int, int)
- */
- boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType);
-
- /**
- * Disable reception of cell broadcast (SMS-CB) messages with the given
- * message identifier range and RAN type. The RAN type specify this message ID range
- * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable
- * a message identifier range, they must both disable it for the device
- * to stop receiving those messages.
- *
- * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) or
- * C.R1001-G (3GPP2)
- * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) or
- * C.R1001-G (3GPP2)
* @param subId for which the broadcast has to be disabled
* @param ranType as defined in class SmsManager, the value can be one of these:
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
* android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
* @return true if successful, false otherwise
*
- * @see #enableCellBroadcastRange(int, int, int, int)
+ * @see #enableCellBroadcastRangeForSubscriber(int, int, int, int)
*/
boolean disableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
int endMessageId, int ranType);
@@ -518,20 +334,10 @@ interface ISms {
/**
* SMS over IMS is supported if IMS is registered and SMS is supported
* on IMS.
- *
- * @return true if SMS over IMS is supported, false otherwise
- *
- * @see #getImsSmsFormat()
- */
- boolean isImsSmsSupported();
-
- /**
- * SMS over IMS is supported if IMS is registered and SMS is supported
- * on IMS.
* @param subId for subId which isImsSmsSupported is queried
* @return true if SMS over IMS is supported, false otherwise
*
- * @see #getImsSmsFormat()
+ * @see #getImsSmsFormatForSubscriber(int)
*/
boolean isImsSmsSupportedForSubscriber(int subId);
@@ -552,24 +358,12 @@ interface ISms {
/**
* Gets SMS format supported on IMS. SMS over IMS format is
* either 3GPP or 3GPP2.
- *
- * @return android.telephony.SmsMessage.FORMAT_3GPP,
- * android.telephony.SmsMessage.FORMAT_3GPP2
- * or android.telephony.SmsMessage.FORMAT_UNKNOWN
- *
- * @see #isImsSmsSupported()
- */
- String getImsSmsFormat();
-
- /**
- * Gets SMS format supported on IMS. SMS over IMS format is
- * either 3GPP or 3GPP2.
* @param subId for subId which getImsSmsFormat is queried
* @return android.telephony.SmsMessage.FORMAT_3GPP,
* android.telephony.SmsMessage.FORMAT_3GPP2
* or android.telephony.SmsMessage.FORMAT_UNKNOWN
*
- * @see #isImsSmsSupported()
+ * @see #isImsSmsSupportedForSubscriber(int)
*/
String getImsSmsFormatForSubscriber(int subId);
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 3f8aca0..1037f2d 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -185,4 +185,5 @@ interface ISub {
*/
int getSimStateForSubscriber(int subId);
+ boolean isActiveSubId(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 0ebd719..2a4032c 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -150,6 +150,10 @@ public class PhoneConstants {
public static final String SLOT_KEY = "slot";
+ /** Fired when a subscriptions phone state changes. */
+ public static final String ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED =
+ "android.intent.action.SUBSCRIPTION_PHONE_STATE";
+
// FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
// FIXME: extensive, and see if this should be an array of all active subId's or ...?
public static final String SUBSCRIPTION_KEY = "subscription";
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 9956bd7..dc3ad25 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -64,7 +64,8 @@ aaptHostStaticLibs := \
libutils \
libcutils \
libexpat \
- libziparchive-host
+ libziparchive-host \
+ libbase
aaptCFlags := -DAAPT_VERSION=\"$(BUILD_NUMBER)\"
aaptCFlags += -Wall -Werror
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 05034c3..5ef4311 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -40,10 +40,10 @@ sources := \
ManifestValidator.cpp \
Png.cpp \
ResChunkPullParser.cpp \
- Resolver.cpp \
Resource.cpp \
ResourceParser.cpp \
ResourceTable.cpp \
+ ResourceTableResolver.cpp \
ResourceValues.cpp \
SdkConstants.cpp \
StringPool.cpp \
@@ -90,7 +90,8 @@ hostStaticLibs := \
libcutils \
libexpat \
libziparchive-host \
- libpng
+ libpng \
+ libbase
ifneq ($(strip $(USE_MINGW)),)
hostStaticLibs += libz
diff --git a/tools/aapt2/BinaryResourceParser.cpp b/tools/aapt2/BinaryResourceParser.cpp
index 326a2ac..d16f63b 100644
--- a/tools/aapt2/BinaryResourceParser.cpp
+++ b/tools/aapt2/BinaryResourceParser.cpp
@@ -39,7 +39,7 @@ using namespace android;
* given a mapping from resource ID to resource name.
*/
struct ReferenceIdToNameVisitor : ValueVisitor {
- ReferenceIdToNameVisitor(const std::shared_ptr<Resolver>& resolver,
+ ReferenceIdToNameVisitor(const std::shared_ptr<IResolver>& resolver,
std::map<ResourceId, ResourceName>* cache) :
mResolver(resolver), mCache(cache) {
}
@@ -96,30 +96,25 @@ private:
reference.name = cacheIter->second;
reference.id = 0;
} else {
- const android::ResTable& table = mResolver->getResTable();
- android::ResTable::resource_name resourceName;
- if (table.getResourceName(reference.id.id, false, &resourceName)) {
- const ResourceType* type = parseResourceType(StringPiece16(resourceName.type,
- resourceName.typeLen));
- assert(type);
- reference.name.package.assign(resourceName.package, resourceName.packageLen);
- reference.name.type = *type;
- reference.name.entry.assign(resourceName.name, resourceName.nameLen);
- reference.id = 0;
+ Maybe<ResourceName> result = mResolver->findName(reference.id);
+ if (result) {
+ reference.name = result.value();
// Add to cache.
mCache->insert({reference.id, reference.name});
+
+ reference.id = 0;
}
}
}
- std::shared_ptr<Resolver> mResolver;
+ std::shared_ptr<IResolver> mResolver;
std::map<ResourceId, ResourceName>* mCache;
};
BinaryResourceParser::BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
- const std::shared_ptr<Resolver>& resolver,
+ const std::shared_ptr<IResolver>& resolver,
const Source& source,
const void* data,
size_t len) :
@@ -401,6 +396,12 @@ bool BinaryResourceParser::parsePackage(const ResChunk_header* chunk) {
}
break;
+ case RES_TABLE_PUBLIC_TYPE:
+ if (!parsePublic(parser.getChunk())) {
+ return false;
+ }
+ break;
+
default:
Logger::warn(mSource)
<< "unexpected chunk of type "
@@ -434,6 +435,55 @@ bool BinaryResourceParser::parsePackage(const ResChunk_header* chunk) {
return true;
}
+bool BinaryResourceParser::parsePublic(const ResChunk_header* chunk) {
+ const Public_header* header = convertTo<Public_header>(chunk);
+
+ if (header->typeId == 0) {
+ Logger::error(mSource)
+ << "invalid type ID " << header->typeId << std::endl;
+ return false;
+ }
+
+ const ResourceType* parsedType = parseResourceType(util::getString(mTypePool,
+ header->typeId - 1));
+ if (!parsedType) {
+ Logger::error(mSource)
+ << "invalid type " << util::getString(mTypePool, header->typeId - 1) << std::endl;
+ return false;
+ }
+
+ const uintptr_t chunkEnd = reinterpret_cast<uintptr_t>(chunk) + chunk->size;
+ const Public_entry* entry = reinterpret_cast<const Public_entry*>(
+ getChunkData(header->header));
+ for (uint32_t i = 0; i < header->count; i++) {
+ if (reinterpret_cast<uintptr_t>(entry) + sizeof(*entry) > chunkEnd) {
+ Logger::error(mSource)
+ << "Public_entry extends beyond chunk."
+ << std::endl;
+ return false;
+ }
+
+ const ResourceId resId = { mTable->getPackageId(), header->typeId, entry->entryId };
+ const ResourceName name = {
+ mTable->getPackage(),
+ *parsedType,
+ util::getString(mKeyPool, entry->key.index).toString() };
+
+ SourceLine source;
+ if (mSourcePool.getError() == NO_ERROR) {
+ source.path = util::utf16ToUtf8(util::getString(mSourcePool, entry->source.index));
+ source.line = entry->sourceLine;
+ }
+
+ if (!mTable->markPublic(name, resId, source)) {
+ return false;
+ }
+
+ entry++;
+ }
+ return true;
+}
+
bool BinaryResourceParser::parseTypeSpec(const ResChunk_header* chunk) {
if (mTypePool.getError() != NO_ERROR) {
Logger::error(mSource)
@@ -641,10 +691,6 @@ std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& na
return util::make_unique<BinaryPrimitive>(nullType);
}
- if (value->dataType == ExtendedTypes::TYPE_SENTINEL) {
- return util::make_unique<Sentinel>();
- }
-
if (value->dataType == ExtendedTypes::TYPE_RAW_STRING) {
return util::make_unique<RawString>(
mTable->getValueStringPool().makeRef(util::getString(mValuePool, value->data),
diff --git a/tools/aapt2/BinaryResourceParser.h b/tools/aapt2/BinaryResourceParser.h
index f95a0c8..32876cd 100644
--- a/tools/aapt2/BinaryResourceParser.h
+++ b/tools/aapt2/BinaryResourceParser.h
@@ -43,7 +43,7 @@ public:
* add any resources parsed to `table`. `source` is for logging purposes.
*/
BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
- const std::shared_ptr<Resolver>& resolver,
+ const std::shared_ptr<IResolver>& resolver,
const Source& source,
const void* data, size_t len);
@@ -66,6 +66,7 @@ private:
bool idToName(Reference* reference);
bool parsePackage(const android::ResChunk_header* chunk);
+ bool parsePublic(const android::ResChunk_header* chunk);
bool parseTypeSpec(const android::ResChunk_header* chunk);
bool parseType(const android::ResChunk_header* chunk);
@@ -92,7 +93,7 @@ private:
std::shared_ptr<ResourceTable> mTable;
- std::shared_ptr<Resolver> mResolver;
+ std::shared_ptr<IResolver> mResolver;
const Source mSource;
diff --git a/tools/aapt2/BinaryXmlPullParser.cpp b/tools/aapt2/BinaryXmlPullParser.cpp
index 7a07c06..476a215 100644
--- a/tools/aapt2/BinaryXmlPullParser.cpp
+++ b/tools/aapt2/BinaryXmlPullParser.cpp
@@ -15,6 +15,8 @@
*/
#include "BinaryXmlPullParser.h"
+#include "Maybe.h"
+#include "Util.h"
#include <androidfw/ResourceTypes.h>
#include <memory>
@@ -77,12 +79,31 @@ XmlPullParser::Event BinaryXmlPullParser::next() {
mEvent = codeToEvent(code);
switch (mEvent) {
case Event::kStartNamespace:
- case Event::kEndNamespace:
+ case Event::kEndNamespace: {
data = mParser->getNamespacePrefix(&len);
- mStr1.assign(data, len);
+ if (data) {
+ mStr1.assign(data, len);
+ } else {
+ mStr1.clear();
+ }
data = mParser->getNamespaceUri(&len);
- mStr2.assign(data, len);
+ if (data) {
+ mStr2.assign(data, len);
+ } else {
+ mStr2.clear();
+ }
+
+ Maybe<std::u16string> result = util::extractPackageFromNamespace(mStr2);
+ if (result) {
+ if (mEvent == Event::kStartNamespace) {
+ mPackageAliases.emplace_back(mStr1, result.value());
+ } else {
+ assert(mPackageAliases.back().second == result.value());
+ mPackageAliases.pop_back();
+ }
+ }
break;
+ }
case Event::kStartElement:
copyAttributes();
@@ -90,14 +111,26 @@ XmlPullParser::Event BinaryXmlPullParser::next() {
case Event::kEndElement:
data = mParser->getElementNamespace(&len);
- mStr1.assign(data, len);
+ if (data) {
+ mStr1.assign(data, len);
+ } else {
+ mStr1.clear();
+ }
data = mParser->getElementName(&len);
- mStr2.assign(data, len);
+ if (data) {
+ mStr2.assign(data, len);
+ } else {
+ mStr2.clear();
+ }
break;
case Event::kText:
data = mParser->getText(&len);
- mStr1.assign(data, len);
+ if (data) {
+ mStr1.assign(data, len);
+ } else {
+ mStr1.clear();
+ }
break;
default:
@@ -155,6 +188,22 @@ const std::u16string& BinaryXmlPullParser::getNamespaceUri() const {
return sEmpty;
}
+bool BinaryXmlPullParser::applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const {
+ const auto endIter = mPackageAliases.rend();
+ for (auto iter = mPackageAliases.rbegin(); iter != endIter; ++iter) {
+ if (iter->first == *package) {
+ if (iter->second.empty()) {
+ *package = defaultPackage;
+ } else {
+ *package = iter->second;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
const std::u16string& BinaryXmlPullParser::getElementNamespace() const {
if (!mHasComment && (mEvent == XmlPullParser::Event::kStartElement ||
mEvent == XmlPullParser::Event::kEndElement)) {
@@ -191,11 +240,17 @@ void BinaryXmlPullParser::copyAttributes() {
XmlPullParser::Attribute attr;
size_t len;
const char16_t* str = mParser->getAttributeNamespace(i, &len);
- attr.namespaceUri.assign(str, len);
+ if (str) {
+ attr.namespaceUri.assign(str, len);
+ }
str = mParser->getAttributeName(i, &len);
- attr.name.assign(str, len);
+ if (str) {
+ attr.name.assign(str, len);
+ }
str = mParser->getAttributeStringValue(i, &len);
- attr.value.assign(str, len);
+ if (str) {
+ attr.value.assign(str, len);
+ }
mAttributes.push_back(std::move(attr));
}
}
diff --git a/tools/aapt2/BinaryXmlPullParser.h b/tools/aapt2/BinaryXmlPullParser.h
index 2d4256a..16fc8b7 100644
--- a/tools/aapt2/BinaryXmlPullParser.h
+++ b/tools/aapt2/BinaryXmlPullParser.h
@@ -34,25 +34,27 @@ public:
BinaryXmlPullParser(const std::shared_ptr<android::ResXMLTree>& parser);
BinaryXmlPullParser(const BinaryXmlPullParser& rhs) = delete;
- Event getEvent() const;
- const std::string& getLastError() const;
- Event next();
+ Event getEvent() const override;
+ const std::string& getLastError() const override;
+ Event next() override;
- const std::u16string& getComment() const;
- size_t getLineNumber() const;
- size_t getDepth() const;
+ const std::u16string& getComment() const override;
+ size_t getLineNumber() const override;
+ size_t getDepth() const override;
- const std::u16string& getText() const;
+ const std::u16string& getText() const override;
- const std::u16string& getNamespacePrefix() const;
- const std::u16string& getNamespaceUri() const;
+ const std::u16string& getNamespacePrefix() const override;
+ const std::u16string& getNamespaceUri() const override;
+ bool applyPackageAlias(std::u16string* package, const std::u16string& defaultpackage)
+ const override;
- const std::u16string& getElementNamespace() const;
- const std::u16string& getElementName() const;
+ const std::u16string& getElementNamespace() const override;
+ const std::u16string& getElementName() const override;
- const_iterator beginAttributes() const;
- const_iterator endAttributes() const;
- size_t getAttributeCount() const;
+ const_iterator beginAttributes() const override;
+ const_iterator endAttributes() const override;
+ size_t getAttributeCount() const override;
private:
void copyAttributes();
@@ -66,6 +68,7 @@ private:
const std::u16string sEmpty;
const std::string sEmpty8;
size_t mDepth;
+ std::vector<std::pair<std::u16string, std::u16string>> mPackageAliases;
};
} // namespace aapt
diff --git a/tools/aapt2/BindingXmlPullParser.cpp b/tools/aapt2/BindingXmlPullParser.cpp
index 58b96e8..4b7a656 100644
--- a/tools/aapt2/BindingXmlPullParser.cpp
+++ b/tools/aapt2/BindingXmlPullParser.cpp
@@ -252,6 +252,11 @@ const std::u16string& BindingXmlPullParser::getNamespaceUri() const {
return mParser->getNamespaceUri();
}
+bool BindingXmlPullParser::applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const {
+ return mParser->applyPackageAlias(package, defaultPackage);
+}
+
const std::u16string& BindingXmlPullParser::getElementNamespace() const {
return mParser->getElementNamespace();
}
diff --git a/tools/aapt2/BindingXmlPullParser.h b/tools/aapt2/BindingXmlPullParser.h
index c892b09..cfb16ef 100644
--- a/tools/aapt2/BindingXmlPullParser.h
+++ b/tools/aapt2/BindingXmlPullParser.h
@@ -42,6 +42,8 @@ public:
const std::u16string& getNamespacePrefix() const override;
const std::u16string& getNamespaceUri() const override;
+ bool applyPackageAlias(std::u16string* package, const std::u16string& defaultPackage)
+ const override;
const std::u16string& getElementNamespace() const override;
const std::u16string& getElementName() const override;
diff --git a/tools/aapt2/Flag.cpp b/tools/aapt2/Flag.cpp
index 3b2ff51..0f63c2c 100644
--- a/tools/aapt2/Flag.cpp
+++ b/tools/aapt2/Flag.cpp
@@ -65,7 +65,7 @@ void parse(int argc, char** argv, const StringPiece& command) {
for (int i = 0; i < argc; i++) {
const StringPiece arg(argv[i]);
if (*arg.data() != '-') {
- sArgs.emplace_back(arg.toString());
+ sArgs.push_back(arg.toString());
continue;
}
diff --git a/tools/aapt2/JavaClassGenerator.cpp b/tools/aapt2/JavaClassGenerator.cpp
index 3f92f18..2bb0e65 100644
--- a/tools/aapt2/JavaClassGenerator.cpp
+++ b/tools/aapt2/JavaClassGenerator.cpp
@@ -94,12 +94,12 @@ void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a)
std::u16string* entryName = static_cast<GenArgs&>(a).entryName;
// This must be sorted by resource ID.
- std::vector<std::pair<ResourceId, StringPiece16>> sortedAttributes;
+ std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes;
sortedAttributes.reserve(styleable.entries.size());
for (const auto& attr : styleable.entries) {
assert(attr.id.isValid() && "no ID set for Styleable entry");
assert(attr.name.isValid() && "no name set for Styleable entry");
- sortedAttributes.emplace_back(attr.id, attr.name.entry);
+ sortedAttributes.emplace_back(attr.id, attr.name);
}
std::sort(sortedAttributes.begin(), sortedAttributes.end());
@@ -124,8 +124,15 @@ void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a)
for (size_t i = 0; i < attrCount; i++) {
*out << " "
<< "public static" << finalModifier
- << " int " << transform(*entryName) << "_" << transform(sortedAttributes[i].second)
- << " = " << i << ";" << std::endl;
+ << " int " << transform(*entryName);
+
+ // We may reference IDs from other packages, so prefix the entry name with
+ // the package.
+ const ResourceNameRef& itemName = sortedAttributes[i].second;
+ if (itemName.package != mTable->getPackage()) {
+ *out << "_" << transform(itemName.package);
+ }
+ *out << "_" << transform(itemName.entry) << " = " << i << ";" << std::endl;
}
}
diff --git a/tools/aapt2/JavaClassGenerator_test.cpp b/tools/aapt2/JavaClassGenerator_test.cpp
index 96bb10b..d4341b6 100644
--- a/tools/aapt2/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/JavaClassGenerator_test.cpp
@@ -16,8 +16,9 @@
#include "JavaClassGenerator.h"
#include "Linker.h"
-#include "Resolver.h"
+#include "MockResolver.h"
#include "ResourceTable.h"
+#include "ResourceTableResolver.h"
#include "ResourceValues.h"
#include "Util.h"
@@ -84,6 +85,7 @@ TEST_F(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
output.find("public static final int hey_dude_cool_attr = 0;"));
}
+
TEST_F(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
ResourceId{ 0x01, 0x02, 0x0000 }));
@@ -93,9 +95,8 @@ TEST_F(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
SourceLine{ "lib.xml", 33 }, util::make_unique<Id>()));
ASSERT_TRUE(mTable->merge(std::move(table)));
- std::shared_ptr<Resolver> resolver = std::make_shared<Resolver>(mTable,
- std::make_shared<const android::AssetManager>());
- Linker linker(mTable, resolver);
+ Linker linker(mTable, std::make_shared<MockResolver>(mTable,
+ std::map<ResourceName, ResourceId>()));
ASSERT_TRUE(linker.linkAndValidate());
JavaClassGenerator generator(mTable, {});
@@ -113,4 +114,32 @@ TEST_F(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
EXPECT_EQ(std::string::npos, output.find("int foo ="));
}
+TEST_F(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
+ std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+ styleable->entries.emplace_back(ResourceNameRef{ mTable->getPackage(),
+ ResourceType::kAttr,
+ u"bar" });
+ styleable->entries.emplace_back(ResourceNameRef{ u"com.lib", ResourceType::kAttr, u"bar" });
+ ASSERT_TRUE(mTable->addResource(ResourceName{ {}, ResourceType::kStyleable, u"Foo" }, {}, {},
+ std::move(styleable)));
+
+ std::shared_ptr<IResolver> resolver = std::make_shared<MockResolver>(mTable,
+ std::map<ResourceName, ResourceId>({
+ { ResourceName{ u"android", ResourceType::kAttr, u"bar" },
+ ResourceId{ 0x01, 0x01, 0x0000 } },
+ { ResourceName{ u"com.lib", ResourceType::kAttr, u"bar" },
+ ResourceId{ 0x02, 0x01, 0x0000 } }}));
+
+ Linker linker(mTable, resolver);
+ ASSERT_TRUE(linker.linkAndValidate());
+
+ JavaClassGenerator generator(mTable, {});
+
+ std::stringstream out;
+ EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
+ std::string output = out.str();
+ EXPECT_NE(std::string::npos, output.find("int Foo_bar ="));
+ EXPECT_NE(std::string::npos, output.find("int Foo_com_lib_bar ="));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/Linker.cpp b/tools/aapt2/Linker.cpp
index 4346c8b..a8b7a14 100644
--- a/tools/aapt2/Linker.cpp
+++ b/tools/aapt2/Linker.cpp
@@ -16,6 +16,8 @@
#include "Linker.h"
#include "Logger.h"
+#include "NameMangler.h"
+#include "Resolver.h"
#include "ResourceParser.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
@@ -38,7 +40,7 @@ namespace aapt {
Linker::Args::Args(const ResourceNameRef& r, const SourceLine& s) : referrer(r), source(s) {
}
-Linker::Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver) :
+Linker::Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<IResolver> resolver) :
mTable(table), mResolver(resolver), mError(false) {
}
@@ -65,13 +67,21 @@ bool Linker::linkAndValidate() {
usedIds[type->typeId].insert(entry->entryId);
}
- for (auto& valueConfig : entry->values) {
- // Dispatch to the right method of this linker
- // based on the value's type.
- valueConfig.value->accept(*this, Args{
- ResourceNameRef{ mTable->getPackage(), type->type, entry->name },
- valueConfig.source
- });
+ if (entry->publicStatus.isPublic && entry->values.empty()) {
+ // A public resource has no values. It will not be encoded
+ // properly without a symbol table. This is a unresolved symbol.
+ addUnresolvedSymbol(ResourceNameRef{
+ mTable->getPackage(), type->type, entry->name },
+ entry->publicStatus.source);
+ } else {
+ for (auto& valueConfig : entry->values) {
+ // Dispatch to the right method of this linker
+ // based on the value's type.
+ valueConfig.value->accept(*this, Args{
+ ResourceNameRef{ mTable->getPackage(), type->type, entry->name },
+ valueConfig.source
+ });
+ }
}
}
}
@@ -100,11 +110,15 @@ bool Linker::linkAndValidate() {
}
entry->entryId = nextIndex++;
+ std::u16string unmangledPackage = mTable->getPackage();
+ std::u16string unmangledName = entry->name;
+ NameMangler::unmangle(&unmangledName, &unmangledPackage);
+
// Update callers of this resource with the right ID.
auto callersIter = mGraph.find(ResourceNameRef{
- mTable->getPackage(),
+ unmangledPackage,
type->type,
- entry->name
+ unmangledName
});
if (callersIter != std::end(mGraph)) {
@@ -175,13 +189,14 @@ void Linker::processAttributeValue(const ResourceNameRef& name, const SourceLine
// we called through the original value.
auto onCreateReference = [&](const ResourceName& name) {
- mTable->addResource(name, ConfigDescription{},
- source, util::make_unique<Id>());
+ // We should never get here. All references would have been
+ // parsed in the parser phase.
+ assert(false);
+ //mTable->addResource(name, ConfigDescription{}, source, util::make_unique<Id>());
};
- convertedValue = ResourceParser::parseItemForAttribute(
- *str.value, attr, mResolver->getDefaultPackage(),
- onCreateReference);
+ convertedValue = ResourceParser::parseItemForAttribute(*str.value, attr,
+ onCreateReference);
if (!convertedValue && attr.typeMask & android::ResTable_map::TYPE_STRING) {
// Last effort is to parse as a string.
util::StringBuilder builder;
@@ -225,13 +240,13 @@ void Linker::visit(Style& style, ValueVisitorArgs& a) {
}
for (Style::Entry& styleEntry : style.entries) {
- Maybe<Resolver::Entry> result = mResolver->findAttribute(styleEntry.key.name);
+ Maybe<IResolver::Entry> result = mResolver->findAttribute(styleEntry.key.name);
if (!result || !result.value().attr) {
addUnresolvedSymbol(styleEntry.key.name, args.source);
continue;
}
- const Resolver::Entry& entry = result.value();
+ const IResolver::Entry& entry = result.value();
if (entry.id.isValid()) {
styleEntry.key.id = entry.id;
} else {
@@ -263,11 +278,6 @@ void Linker::visit(Styleable& styleable, ValueVisitorArgs& a) {
}
}
-void Linker::visit(Sentinel& sentinel, ValueVisitorArgs& a) {
- Args& args = static_cast<Args&>(a);
- addUnresolvedSymbol(args.referrer, args.source);
-}
-
void Linker::visit(Array& array, ValueVisitorArgs& a) {
Args& args = static_cast<Args&>(a);
diff --git a/tools/aapt2/Linker.h b/tools/aapt2/Linker.h
index 9b911b7..9db64ab 100644
--- a/tools/aapt2/Linker.h
+++ b/tools/aapt2/Linker.h
@@ -52,9 +52,9 @@ class Linker : ValueVisitor {
public:
/**
* Create a Linker for the given resource table with the sources available in
- * Resolver. Resolver should contain the ResourceTable as a source too.
+ * IResolver. IResolver should contain the ResourceTable as a source too.
*/
- Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver);
+ Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<IResolver> resolver);
Linker(const Linker&) = delete;
@@ -88,7 +88,6 @@ private:
void visit(Attribute& attribute, ValueVisitorArgs& args) override;
void visit(Styleable& styleable, ValueVisitorArgs& args) override;
void visit(Style& style, ValueVisitorArgs& args) override;
- void visit(Sentinel& sentinel, ValueVisitorArgs& args) override;
void visit(Array& array, ValueVisitorArgs& args) override;
void visit(Plural& plural, ValueVisitorArgs& args) override;
@@ -117,7 +116,7 @@ private:
friend ::std::ostream& operator<<(::std::ostream&, const Node&);
std::shared_ptr<ResourceTable> mTable;
- std::shared_ptr<Resolver> mResolver;
+ std::shared_ptr<IResolver> mResolver;
std::map<ResourceNameRef, std::vector<Node>> mGraph;
std::map<ResourceName, std::vector<SourceLine>> mUnresolvedSymbols;
bool mError;
diff --git a/tools/aapt2/Linker_test.cpp b/tools/aapt2/Linker_test.cpp
index 4d2d360..3c5b8b4 100644
--- a/tools/aapt2/Linker_test.cpp
+++ b/tools/aapt2/Linker_test.cpp
@@ -15,8 +15,8 @@
*/
#include "Linker.h"
-#include "Resolver.h"
#include "ResourceTable.h"
+#include "ResourceTableResolver.h"
#include "ResourceValues.h"
#include "Util.h"
@@ -31,7 +31,7 @@ struct LinkerTest : public ::testing::Test {
mTable = std::make_shared<ResourceTable>();
mTable->setPackage(u"android");
mTable->setPackageId(0x01);
- mLinker = std::make_shared<Linker>(mTable, std::make_shared<Resolver>(
+ mLinker = std::make_shared<Linker>(mTable, std::make_shared<ResourceTableResolver>(
mTable, std::make_shared<android::AssetManager>()));
// Create a few attributes for use in the tests.
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index be806c9..3377f07 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -29,6 +29,7 @@
#include "Png.h"
#include "ResourceParser.h"
#include "ResourceTable.h"
+#include "ResourceTableResolver.h"
#include "ResourceValues.h"
#include "SdkConstants.h"
#include "SourceXmlPullParser.h"
@@ -271,6 +272,7 @@ struct LinkItem {
ConfigDescription config;
std::string originalPath;
ZipFile* apk;
+ std::u16string originalPackage;
};
template <typename TChar>
@@ -321,9 +323,17 @@ struct AaptOptions {
Compile,
};
+ enum class PackageType {
+ StandardApp,
+ StaticLibrary,
+ };
+
// The phase to process.
Phase phase;
+ // The type of package to produce.
+ PackageType packageType = PackageType::StandardApp;
+
// Details about the app.
AppInfo appInfo;
@@ -371,6 +381,8 @@ bool compileXml(const AaptOptions& options, const std::shared_ptr<ResourceTable>
XmlFlattener flattener(table, {});
XmlFlattener::Options xmlOptions;
+ xmlOptions.defaultPackage = table->getPackage();
+
if (options.versionStylesAndLayouts) {
// We strip attributes that do not belong in this version of the resource.
// Non-version qualified resources have an implicit version 1 requirement.
@@ -432,7 +444,7 @@ bool compileXml(const AaptOptions& options, const std::shared_ptr<ResourceTable>
return true;
}
-bool linkXml(const AaptOptions& options, const std::shared_ptr<Resolver>& resolver,
+bool linkXml(const AaptOptions& options, const std::shared_ptr<IResolver>& resolver,
const LinkItem& item, const void* data, size_t dataLen, ZipFile* outApk) {
std::shared_ptr<android::ResXMLTree> tree = std::make_shared<android::ResXMLTree>();
if (tree->setTo(data, dataLen, false) != android::NO_ERROR) {
@@ -443,7 +455,10 @@ bool linkXml(const AaptOptions& options, const std::shared_ptr<Resolver>& resolv
BigBuffer outBuffer(1024);
XmlFlattener flattener({}, resolver);
- if (!flattener.flatten(item.source, xmlParser, &outBuffer, {})) {
+
+ XmlFlattener::Options xmlOptions;
+ xmlOptions.defaultPackage = item.originalPackage;
+ if (!flattener.flatten(item.source, xmlParser, &outBuffer, xmlOptions)) {
return false;
}
@@ -490,8 +505,8 @@ bool copyFile(const AaptOptions& options, const CompileItem& item, ZipFile* outA
return true;
}
-bool compileManifest(const AaptOptions& options, const std::shared_ptr<Resolver>& resolver,
- ZipFile* outApk) {
+bool compileManifest(const AaptOptions& options,
+ const std::shared_ptr<ResourceTableResolver>& resolver, ZipFile* outApk) {
if (options.verbose) {
Logger::note(options.manifest) << "compiling AndroidManifest.xml." << std::endl;
}
@@ -506,7 +521,9 @@ bool compileManifest(const AaptOptions& options, const std::shared_ptr<Resolver>
std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(in);
XmlFlattener flattener({}, resolver);
- if (!flattener.flatten(options.manifest, xmlParser, &outBuffer, {})) {
+ XmlFlattener::Options xmlOptions;
+ xmlOptions.defaultPackage = options.appInfo.package;
+ if (!flattener.flatten(options.manifest, xmlParser, &outBuffer, xmlOptions)) {
return false;
}
@@ -640,8 +657,12 @@ static void addApkFilesToLinkQueue(const std::u16string& package, const Source&
for (auto& value : entry->values) {
visitFunc<FileReference>(*value.value, [&](FileReference& ref) {
std::string pathUtf8 = util::utf16ToUtf8(*ref.path);
+ Source newSource = source;
+ newSource.path += "/";
+ newSource.path += pathUtf8;
outLinkQueue->push(LinkItem{
- source, name, value.config, pathUtf8, apk.get() });
+ newSource, name, value.config, pathUtf8, apk.get(),
+ table->getPackage() });
// Now rewrite the file path.
if (mangle) {
ref.path = table->getValueStringPool().makeRef(util::utf8ToUtf16(
@@ -657,9 +678,20 @@ static void addApkFilesToLinkQueue(const std::u16string& package, const Source&
static constexpr int kOpenFlags = ZipFile::kOpenCreate | ZipFile::kOpenTruncate |
ZipFile::kOpenReadWrite;
+struct DeleteMalloc {
+ void operator()(void* ptr) {
+ free(ptr);
+ }
+};
+
+struct StaticLibraryData {
+ Source source;
+ std::unique_ptr<ZipFile> apk;
+};
+
bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outTable,
- const std::shared_ptr<Resolver>& resolver) {
- std::map<std::shared_ptr<ResourceTable>, std::unique_ptr<ZipFile>> apkFiles;
+ const std::shared_ptr<ResourceTableResolver>& resolver) {
+ std::map<std::shared_ptr<ResourceTable>, StaticLibraryData> apkFiles;
std::unordered_set<std::u16string> linkedPackages;
// Populate the linkedPackages with our own.
@@ -681,19 +713,18 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT
return false;
}
- void* uncompressedData = zipFile->uncompress(entry);
+ std::unique_ptr<void, DeleteMalloc> uncompressedData = std::unique_ptr<void, DeleteMalloc>(
+ zipFile->uncompress(entry));
assert(uncompressedData);
- BinaryResourceParser parser(table, resolver, source, uncompressedData,
+ BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
entry->getUncompressedLen());
if (!parser.parse()) {
- free(uncompressedData);
return false;
}
- free(uncompressedData);
// Keep track of where this table came from.
- apkFiles[table] = std::move(zipFile);
+ apkFiles[table] = StaticLibraryData{ source, std::move(zipFile) };
// Add the package to the set of linked packages.
linkedPackages.insert(table->getPackage());
@@ -704,7 +735,8 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT
const std::shared_ptr<ResourceTable>& inTable = p.first;
// Collect all FileReferences and add them to the queue for processing.
- addApkFilesToLinkQueue(options.appInfo.package, Source{}, inTable, p.second, &linkQueue);
+ addApkFilesToLinkQueue(options.appInfo.package, p.second.source, inTable, p.second.apk,
+ &linkQueue);
// Merge the tables.
if (!outTable->merge(std::move(*inTable))) {
@@ -746,6 +778,7 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT
for (; !linkQueue.empty(); linkQueue.pop()) {
const LinkItem& item = linkQueue.front();
+ assert(!item.originalPackage.empty());
ZipEntry* entry = item.apk->getEntryByName(item.originalPath.data());
if (!entry) {
Logger::error(item.source) << "failed to find '" << item.originalPath << "'."
@@ -775,7 +808,11 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT
// Generate the Java class file.
if (options.generateJavaClass) {
- JavaClassGenerator generator(outTable, {});
+ JavaClassGenerator::Options javaOptions;
+ if (options.packageType == AaptOptions::PackageType::StaticLibrary) {
+ javaOptions.useFinal = false;
+ }
+ JavaClassGenerator generator(outTable, javaOptions);
for (const std::u16string& package : linkedPackages) {
Source outPath = options.generateJavaClass.value();
@@ -811,9 +848,26 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT
}
}
+ outTable->getValueStringPool().prune();
+ outTable->getValueStringPool().sort(
+ [](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
+ if (a.context.priority < b.context.priority) {
+ return true;
+ }
+
+ if (a.context.priority > b.context.priority) {
+ return false;
+ }
+ return a.value < b.value;
+ });
+
+
// Flatten the resource table.
TableFlattener::Options flattenerOptions;
- flattenerOptions.useExtendedChunks = false;
+ if (options.packageType == AaptOptions::PackageType::StaticLibrary) {
+ flattenerOptions.useExtendedChunks = true;
+ }
+
if (!writeResourceTable(options, outTable, flattenerOptions, &outApk)) {
return false;
}
@@ -823,7 +877,7 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT
}
bool compile(const AaptOptions& options, const std::shared_ptr<ResourceTable>& table,
- const std::shared_ptr<Resolver>& resolver) {
+ const std::shared_ptr<IResolver>& resolver) {
std::queue<CompileItem> compileQueue;
bool error = false;
@@ -960,6 +1014,7 @@ static AaptOptions prepareArgs(int argc, char** argv) {
printCommandsAndDie();
}
+ bool isStaticLib = false;
if (options.phase == AaptOptions::Phase::Compile) {
flag::requiredFlag("--package", "Android package name",
[&options](const StringPiece& arg) {
@@ -987,6 +1042,8 @@ static AaptOptions prepareArgs(int argc, char** argv) {
[&options](const StringPiece& arg) {
options.generateJavaClass = Source{ arg.toString() };
});
+ flag::optionalSwitch("--static-lib", "generate a static Android library", true,
+ &isStaticLib);
}
// Common flags for all steps.
@@ -1010,6 +1067,10 @@ static AaptOptions prepareArgs(int argc, char** argv) {
flag::usageAndDie(fullCommand);
}
+ if (isStaticLib) {
+ options.packageType = AaptOptions::PackageType::StaticLibrary;
+ }
+
// Copy all the remaining arguments.
for (const std::string& arg : flag::getArgs()) {
options.input.push_back(Source{ arg });
@@ -1073,7 +1134,8 @@ int main(int argc, char** argv) {
}
// Make the resolver that will cache IDs for us.
- std::shared_ptr<Resolver> resolver = std::make_shared<Resolver>(table, libraries);
+ std::shared_ptr<ResourceTableResolver> resolver = std::make_shared<ResourceTableResolver>(
+ table, libraries);
if (options.phase == AaptOptions::Phase::Compile) {
if (!compile(options, table, resolver)) {
diff --git a/tools/aapt2/ManifestValidator.cpp b/tools/aapt2/ManifestValidator.cpp
index 7ec0bc7..123b9fa 100644
--- a/tools/aapt2/ManifestValidator.cpp
+++ b/tools/aapt2/ManifestValidator.cpp
@@ -190,18 +190,26 @@ bool ManifestValidator::validateManifest(const Source& source, android::ResXMLPa
bool error = false;
SourceLogger logger(source);
- const size_t attrCount = parser->getAttributeCount();
- for (size_t i = 0; i < attrCount; i++) {
- size_t len = 0;
- StringPiece16 attrNamespace(parser->getAttributeNamespace(i, &len), len);
- StringPiece16 attrName(parser->getAttributeName(i, &len), len);
- if (attrNamespace.empty() && attrName == u"package") {
- error |= !validateInlineAttribute(parser, i, logger, kPackageIdentSet);
- } else if (attrNamespace == u"android") {
- if (attrName == u"sharedUserId") {
- error |= !validateInlineAttribute(parser, i, logger, kPackageIdentSet);
- }
- }
+ const StringPiece16 kAndroid = u"android";
+ const StringPiece16 kPackage = u"package";
+ const StringPiece16 kSharedUserId = u"sharedUserId";
+
+ ssize_t idx;
+
+ idx = parser->indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
+ if (idx < 0) {
+ logger.error(parser->getLineNumber())
+ << "missing package attribute."
+ << std::endl;
+ error = true;
+ } else {
+ error |= !validateInlineAttribute(parser, idx, logger, kPackageIdentSet);
+ }
+
+ idx = parser->indexOfAttribute(kAndroid.data(), kAndroid.size(),
+ kSharedUserId.data(), kSharedUserId.size());
+ if (idx >= 0) {
+ error |= !validateInlineAttribute(parser, idx, logger, kPackageIdentSet);
}
return !error;
}
diff --git a/tools/aapt2/Maybe.h b/tools/aapt2/Maybe.h
index f6a396d..ff6625f 100644
--- a/tools/aapt2/Maybe.h
+++ b/tools/aapt2/Maybe.h
@@ -34,54 +34,68 @@ public:
/**
* Construct Nothing.
*/
- inline Maybe();
+ Maybe();
- inline ~Maybe();
+ ~Maybe();
+
+ Maybe(const Maybe& rhs);
template <typename U>
- inline Maybe(const Maybe<U>& rhs);
+ Maybe(const Maybe<U>& rhs);
+
+ Maybe(Maybe&& rhs);
template <typename U>
- inline Maybe(Maybe<U>&& rhs);
+ Maybe(Maybe<U>&& rhs);
+
+ Maybe& operator=(const Maybe& rhs);
template <typename U>
- inline Maybe& operator=(const Maybe<U>& rhs);
+ Maybe& operator=(const Maybe<U>& rhs);
+
+ Maybe& operator=(Maybe&& rhs);
template <typename U>
- inline Maybe& operator=(Maybe<U>&& rhs);
+ Maybe& operator=(Maybe<U>&& rhs);
/**
* Construct a Maybe holding a value.
*/
- inline Maybe(const T& value);
+ Maybe(const T& value);
/**
* Construct a Maybe holding a value.
*/
- inline Maybe(T&& value);
+ Maybe(T&& value);
/**
* True if this holds a value, false if
* it holds Nothing.
*/
- inline operator bool() const;
+ operator bool() const;
/**
* Gets the value if one exists, or else
* panics.
*/
- inline T& value();
+ T& value();
/**
* Gets the value if one exists, or else
* panics.
*/
- inline const T& value() const;
+ const T& value() const;
private:
template <typename U>
friend class Maybe;
+ template <typename U>
+ Maybe& copy(const Maybe<U>& rhs);
+
+ template <typename U>
+ Maybe& move(Maybe<U>&& rhs);
+
void destroy();
bool mNothing;
@@ -102,6 +116,14 @@ Maybe<T>::~Maybe() {
}
template <typename T>
+Maybe<T>::Maybe(const Maybe& rhs)
+: mNothing(rhs.mNothing) {
+ if (!rhs.mNothing) {
+ new (&mStorage) T(reinterpret_cast<const T&>(rhs.mStorage));
+ }
+}
+
+template <typename T>
template <typename U>
Maybe<T>::Maybe(const Maybe<U>& rhs)
: mNothing(rhs.mNothing) {
@@ -111,6 +133,18 @@ Maybe<T>::Maybe(const Maybe<U>& rhs)
}
template <typename T>
+Maybe<T>::Maybe(Maybe&& rhs)
+: mNothing(rhs.mNothing) {
+ if (!rhs.mNothing) {
+ rhs.mNothing = true;
+
+ // Move the value from rhs.
+ new (&mStorage) T(std::move(reinterpret_cast<T&>(rhs.mStorage)));
+ rhs.destroy();
+ }
+}
+
+template <typename T>
template <typename U>
Maybe<T>::Maybe(Maybe<U>&& rhs)
: mNothing(rhs.mNothing) {
@@ -119,16 +153,25 @@ Maybe<T>::Maybe(Maybe<U>&& rhs)
// Move the value from rhs.
new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
-
- // Since the value in rhs is now Nothing,
- // run the destructor for the value.
rhs.destroy();
}
}
template <typename T>
+inline Maybe<T>& Maybe<T>::operator=(const Maybe& rhs) {
+ // Delegate to the actual assignment.
+ return copy(rhs);
+}
+
+template <typename T>
+template <typename U>
+inline Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
+ return copy(rhs);
+}
+
+template <typename T>
template <typename U>
-Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
+Maybe<T>& Maybe<T>::copy(const Maybe<U>& rhs) {
if (mNothing && rhs.mNothing) {
// Both are nothing, nothing to do.
return *this;
@@ -150,8 +193,20 @@ Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
}
template <typename T>
+inline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) {
+ // Delegate to the actual assignment.
+ return move(std::forward<Maybe<T>>(rhs));
+}
+
+template <typename T>
+template <typename U>
+inline Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
+ return move(std::forward<Maybe<U>>(rhs));
+}
+
+template <typename T>
template <typename U>
-Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
+Maybe<T>& Maybe<T>::move(Maybe<U>&& rhs) {
if (mNothing && rhs.mNothing) {
// Both are nothing, nothing to do.
return *this;
@@ -162,14 +217,15 @@ Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
rhs.destroy();
} else if (mNothing) {
// We are nothing but rhs is something.
- mNothing = rhs.mNothing;
+ mNothing = false;
+ rhs.mNothing = true;
// Move the value from rhs.
new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
rhs.destroy();
} else {
// We are something but rhs is nothing, so destroy our value.
- mNothing = rhs.mNothing;
+ mNothing = true;
destroy();
}
return *this;
diff --git a/tools/aapt2/Maybe_test.cpp b/tools/aapt2/Maybe_test.cpp
index 348d7dd..71bbb94 100644
--- a/tools/aapt2/Maybe_test.cpp
+++ b/tools/aapt2/Maybe_test.cpp
@@ -23,20 +23,64 @@ namespace aapt {
struct Dummy {
Dummy() {
- std::cerr << "Constructing Dummy " << (void *) this << std::endl;
+ data = new int;
+ *data = 1;
+ std::cerr << "Construct Dummy{0x" << (void *) this
+ << "} with data=0x" << (void*) data
+ << std::endl;
}
Dummy(const Dummy& rhs) {
- std::cerr << "Copying Dummy " << (void *) this << " from " << (const void*) &rhs << std::endl;
+ data = nullptr;
+ if (rhs.data) {
+ data = new int;
+ *data = *rhs.data;
+ }
+ std::cerr << "CopyConstruct Dummy{0x" << (void *) this
+ << "} from Dummy{0x" << (const void*) &rhs
+ << "}" << std::endl;
}
Dummy(Dummy&& rhs) {
- std::cerr << "Moving Dummy " << (void *) this << " from " << (void*) &rhs << std::endl;
+ data = rhs.data;
+ rhs.data = nullptr;
+ std::cerr << "MoveConstruct Dummy{0x" << (void *) this
+ << "} from Dummy{0x" << (const void*) &rhs
+ << "}" << std::endl;
+ }
+
+ Dummy& operator=(const Dummy& rhs) {
+ delete data;
+ data = nullptr;
+
+ if (rhs.data) {
+ data = new int;
+ *data = *rhs.data;
+ }
+ std::cerr << "CopyAssign Dummy{0x" << (void *) this
+ << "} from Dummy{0x" << (const void*) &rhs
+ << "}" << std::endl;
+ return *this;
+ }
+
+ Dummy& operator=(Dummy&& rhs) {
+ delete data;
+ data = rhs.data;
+ rhs.data = nullptr;
+ std::cerr << "MoveAssign Dummy{0x" << (void *) this
+ << "} from Dummy{0x" << (const void*) &rhs
+ << "}" << std::endl;
+ return *this;
}
~Dummy() {
- std::cerr << "Destroying Dummy " << (void *) this << std::endl;
+ std::cerr << "Destruct Dummy{0x" << (void *) this
+ << "} with data=0x" << (void*) data
+ << std::endl;
+ delete data;
}
+
+ int* data;
};
TEST(MaybeTest, MakeNothing) {
@@ -66,4 +110,12 @@ TEST(MaybeTest, Lifecycle) {
Maybe<Dummy> val2 = make_value(Dummy());
}
+TEST(MaybeTest, MoveAssign) {
+ Maybe<Dummy> val;
+ {
+ Maybe<Dummy> val2 = Dummy();
+ val = std::move(val2);
+ }
+}
+
} // namespace aapt
diff --git a/tools/aapt2/MockResolver.h b/tools/aapt2/MockResolver.h
new file mode 100644
index 0000000..48ff6a6
--- /dev/null
+++ b/tools/aapt2/MockResolver.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_MOCK_RESOLVER_H
+#define AAPT_MOCK_RESOLVER_H
+
+#include "Maybe.h"
+#include "Resolver.h"
+#include "Resource.h"
+#include "ResourceTable.h"
+#include "ResourceTableResolver.h"
+#include "ResourceValues.h"
+#include "StringPiece.h"
+
+#include <map>
+#include <string>
+
+namespace aapt {
+
+struct MockResolver : public IResolver {
+ MockResolver(const std::shared_ptr<ResourceTable>& table,
+ const std::map<ResourceName, ResourceId>& items) :
+ mResolver(std::make_shared<ResourceTableResolver>(
+ table, std::make_shared<const android::AssetManager>())),
+ mAttr(false, android::ResTable_map::TYPE_ANY), mItems(items) {
+ }
+
+ virtual Maybe<ResourceId> findId(const ResourceName& name) override {
+ Maybe<ResourceId> result = mResolver->findId(name);
+ if (result) {
+ return result;
+ }
+
+ const auto iter = mItems.find(name);
+ if (iter != mItems.end()) {
+ return iter->second;
+ }
+ return {};
+ }
+
+ virtual Maybe<Entry> findAttribute(const ResourceName& name) override {
+ Maybe<Entry> tableResult = mResolver->findAttribute(name);
+ if (tableResult) {
+ return tableResult;
+ }
+
+ Maybe<ResourceId> result = findId(name);
+ if (result) {
+ if (name.type == ResourceType::kAttr) {
+ return Entry{ result.value(), &mAttr };
+ } else {
+ return Entry{ result.value() };
+ }
+ }
+ return {};
+ }
+
+ virtual Maybe<ResourceName> findName(ResourceId resId) override {
+ Maybe<ResourceName> result = mResolver->findName(resId);
+ if (result) {
+ return result;
+ }
+
+ for (auto& p : mItems) {
+ if (p.second == resId) {
+ return p.first;
+ }
+ }
+ return {};
+ }
+
+private:
+ std::shared_ptr<ResourceTableResolver> mResolver;
+ Attribute mAttr;
+ std::map<ResourceName, ResourceId> mItems;
+};
+
+} // namespace aapt
+
+#endif // AAPT_MOCK_RESOLVER_H
diff --git a/tools/aapt2/Resolver.h b/tools/aapt2/Resolver.h
index cb2234d..cb9318e 100644
--- a/tools/aapt2/Resolver.h
+++ b/tools/aapt2/Resolver.h
@@ -19,31 +19,18 @@
#include "Maybe.h"
#include "Resource.h"
-#include "ResourceTable.h"
#include "ResourceValues.h"
-#include <androidfw/AssetManager.h>
#include <androidfw/ResourceTypes.h>
-#include <memory>
-#include <vector>
-#include <unordered_set>
namespace aapt {
/**
* Resolves symbolic references (package:type/entry) into resource IDs/objects.
- * Encapsulates the search of library sources as well as the local ResourceTable.
*/
-class Resolver {
+class IResolver {
public:
- /**
- * Creates a resolver with a local ResourceTable and an AssetManager
- * loaded with library packages.
- */
- Resolver(std::shared_ptr<const ResourceTable> table,
- std::shared_ptr<const android::AssetManager> sources);
-
- Resolver(const Resolver&) = delete; // Not copyable.
+ virtual ~IResolver() {};
/**
* Holds the result of a resource name lookup.
@@ -65,47 +52,24 @@ public:
};
/**
- * Return the package to use when none is specified. This
- * is the package name of the app being built.
- */
- const std::u16string& getDefaultPackage() const;
-
- /**
* Returns a ResourceID if the name is found. The ResourceID
* may not be valid if the resource was not assigned an ID.
*/
- Maybe<ResourceId> findId(const ResourceName& name);
+ virtual Maybe<ResourceId> findId(const ResourceName& name) = 0;
/**
* Returns an Entry if the name is found. Entry::attr
* may be nullptr if the resource is not an attribute.
*/
- Maybe<Entry> findAttribute(const ResourceName& name);
+ virtual Maybe<Entry> findAttribute(const ResourceName& name) = 0;
- const android::ResTable& getResTable() const;
-
-private:
- struct CacheEntry {
- ResourceId id;
- std::unique_ptr<Attribute> attr;
- };
-
- const CacheEntry* buildCacheEntry(const ResourceName& name);
-
- std::shared_ptr<const ResourceTable> mTable;
- std::shared_ptr<const android::AssetManager> mSources;
- std::map<ResourceName, CacheEntry> mCache;
- std::unordered_set<std::u16string> mIncludedPackages;
+ /**
+ * Find a resource by ID. Resolvers may contain resources without
+ * resource IDs assigned to them.
+ */
+ virtual Maybe<ResourceName> findName(ResourceId resId) = 0;
};
-inline const std::u16string& Resolver::getDefaultPackage() const {
- return mTable->getPackage();
-}
-
-inline const android::ResTable& Resolver::getResTable() const {
- return mSources->getResources(false);
-}
-
} // namespace aapt
#endif // AAPT_RESOLVER_H
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index f928acd..fa9ac07 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -96,6 +96,8 @@ struct ResourceNameRef {
ResourceNameRef(ResourceNameRef&&) = default;
ResourceNameRef(const ResourceName& rhs);
ResourceNameRef(const StringPiece16& p, ResourceType t, const StringPiece16& e);
+ ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
+ ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
ResourceNameRef& operator=(const ResourceName& rhs);
ResourceName toResourceName() const;
@@ -130,6 +132,7 @@ struct ResourceId {
uint8_t typeId() const;
uint16_t entryId() const;
bool operator<(const ResourceId& rhs) const;
+ bool operator==(const ResourceId& rhs) const;
};
//
@@ -178,6 +181,10 @@ inline bool ResourceId::operator<(const ResourceId& rhs) const {
return id < rhs.id;
}
+inline bool ResourceId::operator==(const ResourceId& rhs) const {
+ return id == rhs.id;
+}
+
inline ::std::ostream& operator<<(::std::ostream& out,
const ResourceId& resId) {
std::ios_base::fmtflags oldFlags = out.flags();
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 943892d..e7e824c 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -175,23 +175,16 @@ bool ResourceParser::parseStyleParentReference(const StringPiece16& str, Referen
}
std::unique_ptr<Reference> ResourceParser::tryParseReference(const StringPiece16& str,
- const StringPiece16& defaultPackage,
bool* outCreate) {
ResourceNameRef ref;
bool privateRef = false;
if (tryParseReference(str, &ref, outCreate, &privateRef)) {
- if (ref.package.empty()) {
- ref.package = defaultPackage;
- }
std::unique_ptr<Reference> value = util::make_unique<Reference>(ref);
value->privateReference = privateRef;
return value;
}
if (tryParseAttributeReference(str, &ref)) {
- if (ref.package.empty()) {
- ref.package = defaultPackage;
- }
*outCreate = false;
return util::make_unique<Reference>(ref, Reference::Type::kAttribute);
}
@@ -330,7 +323,7 @@ std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseBool(const StringPiece1
StringPiece16 trimmedStr(util::trimWhitespace(str));
uint32_t data = 0;
if (trimmedStr == u"true" || trimmedStr == u"TRUE") {
- data = 1;
+ data = 0xffffffffu;
} else if (trimmedStr != u"false" && trimmedStr != u"FALSE") {
return {};
}
@@ -397,7 +390,7 @@ uint32_t ResourceParser::androidTypeToAttributeTypeMask(uint16_t type) {
}
std::unique_ptr<Item> ResourceParser::parseItemForAttribute(
- const StringPiece16& value, uint32_t typeMask, const StringPiece16& defaultPackage,
+ const StringPiece16& value, uint32_t typeMask,
std::function<void(const ResourceName&)> onCreateReference) {
std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value);
if (nullOrEmpty) {
@@ -405,7 +398,7 @@ std::unique_ptr<Item> ResourceParser::parseItemForAttribute(
}
bool create = false;
- std::unique_ptr<Reference> reference = tryParseReference(value, defaultPackage, &create);
+ std::unique_ptr<Reference> reference = tryParseReference(value, &create);
if (reference) {
if (create && onCreateReference) {
onCreateReference(reference->name);
@@ -457,11 +450,10 @@ std::unique_ptr<Item> ResourceParser::parseItemForAttribute(
* allows.
*/
std::unique_ptr<Item> ResourceParser::parseItemForAttribute(
- const StringPiece16& str, const Attribute& attr, const StringPiece16& defaultPackage,
+ const StringPiece16& str, const Attribute& attr,
std::function<void(const ResourceName&)> onCreateReference) {
const uint32_t typeMask = attr.typeMask;
- std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, defaultPackage,
- onCreateReference);
+ std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference);
if (value) {
return value;
}
@@ -770,14 +762,25 @@ std::unique_ptr<Item> ResourceParser::parseXml(XmlPullParser* parser, uint32_t t
}
auto onCreateReference = [&](const ResourceName& name) {
+ // name.package can be empty here, as it will assume the package name of the table.
mTable->addResource(name, {}, mSource.line(beginXmlLine), util::make_unique<Id>());
};
// Process the raw value.
std::unique_ptr<Item> processedItem = parseItemForAttribute(rawValue, typeMask,
- mTable->getPackage(),
onCreateReference);
if (processedItem) {
+ // Fix up the reference.
+ visitFunc<Reference>(*processedItem, [&](Reference& ref) {
+ if (!ref.name.package.empty()) {
+ // The package name was set, so lookup its alias.
+ parser->applyPackageAlias(&ref.name.package, mTable->getPackage());
+ } else {
+ // The package name was left empty, so it assumes the default package
+ // without alias lookup.
+ ref.name.package = mTable->getPackage();
+ }
+ });
return processedItem;
}
@@ -1093,7 +1096,7 @@ bool ResourceParser::parseEnumOrFlagItem(XmlPullParser* parser, const StringPiec
return true;
}
-static bool parseXmlAttributeName(StringPiece16 str, ResourceNameRef* outRef) {
+static bool parseXmlAttributeName(StringPiece16 str, ResourceName* outName) {
str = util::trimWhitespace(str);
const char16_t* const start = str.data();
const char16_t* const end = start + str.size();
@@ -1110,12 +1113,12 @@ static bool parseXmlAttributeName(StringPiece16 str, ResourceNameRef* outRef) {
p++;
}
- outRef->package = package;
- outRef->type = ResourceType::kAttr;
+ outName->package = package.toString();
+ outName->type = ResourceType::kAttr;
if (name.size() == 0) {
- outRef->entry = str;
+ outName->entry = str.toString();
} else {
- outRef->entry = name;
+ outName->entry = name.toString();
}
return true;
}
@@ -1130,8 +1133,8 @@ bool ResourceParser::parseUntypedItem(XmlPullParser* parser, Style& style) {
return false;
}
- ResourceNameRef keyRef;
- if (!parseXmlAttributeName(nameAttrIter->value, &keyRef)) {
+ ResourceName key;
+ if (!parseXmlAttributeName(nameAttrIter->value, &key)) {
mLogger.error(parser->getLineNumber())
<< "invalid attribute name '"
<< nameAttrIter->value
@@ -1140,14 +1143,15 @@ bool ResourceParser::parseUntypedItem(XmlPullParser* parser, Style& style) {
return false;
}
- if (keyRef.package.empty()) {
- keyRef.package = mTable->getPackage();
+ if (!key.package.empty()) {
+ // We have a package name set, so lookup its alias.
+ parser->applyPackageAlias(&key.package, mTable->getPackage());
+ } else {
+ // The package name was omitted, so use the default package name with
+ // no alias lookup.
+ key.package = mTable->getPackage();
}
- // Create a copy instead of a reference because we
- // are about to invalidate keyRef when advancing the parser.
- ResourceName key = keyRef.toResourceName();
-
std::unique_ptr<Item> value = parseXml(parser, 0, kAllowRawString);
if (!value) {
return false;
@@ -1170,7 +1174,11 @@ bool ResourceParser::parseStyle(XmlPullParser* parser, const ResourceNameRef& re
return false;
}
- if (style->parent.name.package.empty()) {
+ if (!style->parent.name.package.empty()) {
+ // Try to interpret the package name as an alias. These take precedence.
+ parser->applyPackageAlias(&style->parent.name.package, mTable->getPackage());
+ } else {
+ // If no package is specified, this can not be an alias and is the local package.
style->parent.name.package = mTable->getPackage();
}
}
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 52194bd..7618999 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -76,12 +76,10 @@ public:
/*
* Returns a Reference object if the string was parsed as a resource or attribute reference,
- * ( @[+][package:]type/name | ?[package:]type/name )
- * assigning defaultPackage if the package was not present in the string, and setting
- * outCreate to true if the '+' was present in the string.
+ * ( @[+][package:]type/name | ?[package:]type/name ) setting outCreate to true if
+ * the '+' was present in the string.
*/
static std::unique_ptr<Reference> tryParseReference(const StringPiece16& str,
- const StringPiece16& defaultPackage,
bool* outCreate);
/*
@@ -127,20 +125,18 @@ public:
*/
static std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute& enumAttr,
const StringPiece16& str);
-
/*
* Try to convert a string to an Item for the given attribute. The attribute will
* restrict what values the string can be converted to.
- * The defaultPackage is used when the string is a reference with no defined package.
* The callback function onCreateReference is called when the parsed item is a
* reference to an ID that must be created (@+id/foo).
*/
static std::unique_ptr<Item> parseItemForAttribute(
- const StringPiece16& value, const Attribute& attr, const StringPiece16& defaultPackage,
+ const StringPiece16& value, const Attribute& attr,
std::function<void(const ResourceName&)> onCreateReference = {});
static std::unique_ptr<Item> parseItemForAttribute(
- const StringPiece16& value, uint32_t typeMask, const StringPiece16& defaultPackage,
+ const StringPiece16& value, uint32_t typeMask,
std::function<void(const ResourceName&)> onCreateReference = {});
static uint32_t androidTypeToAttributeTypeMask(uint16_t type);
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 63352de..00be3bd 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -125,11 +125,9 @@ struct ResourceParserTest : public ::testing::Test {
mTable->setPackage(u"android");
}
- ::testing::AssertionResult testParse(std::istream& in) {
+ ::testing::AssertionResult testParse(const StringPiece& str) {
std::stringstream input(kXmlPreamble);
- input << "<resources>" << std::endl
- << in.rdbuf() << std::endl
- << "</resources>" << std::endl;
+ input << "<resources>\n" << str << "\n</resources>" << std::endl;
ResourceParser parser(mTable, Source{ "test" }, {},
std::make_shared<SourceXmlPullParser>(input));
if (parser.parse()) {
@@ -174,7 +172,7 @@ TEST_F(ResourceParserTest, FailToParseWithNoRootResourcesElement) {
}
TEST_F(ResourceParserTest, ParseQuotedString) {
- std::stringstream input("<string name=\"foo\"> \" hey there \" </string>");
+ std::string input = "<string name=\"foo\"> \" hey there \" </string>";
ASSERT_TRUE(testParse(input));
const String* str = findResource<String>(ResourceName{
@@ -184,7 +182,7 @@ TEST_F(ResourceParserTest, ParseQuotedString) {
}
TEST_F(ResourceParserTest, ParseEscapedString) {
- std::stringstream input("<string name=\"foo\">\\?123</string>");
+ std::string input = "<string name=\"foo\">\\?123</string>";
ASSERT_TRUE(testParse(input));
const String* str = findResource<String>(ResourceName{
@@ -194,9 +192,8 @@ TEST_F(ResourceParserTest, ParseEscapedString) {
}
TEST_F(ResourceParserTest, ParseAttr) {
- std::stringstream input;
- input << "<attr name=\"foo\" format=\"string\"/>" << std::endl
- << "<attr name=\"bar\"/>" << std::endl;
+ std::string input = "<attr name=\"foo\" format=\"string\"/>\n"
+ "<attr name=\"bar\"/>";
ASSERT_TRUE(testParse(input));
const Attribute* attr = findResource<Attribute>(ResourceName{
@@ -211,11 +208,10 @@ TEST_F(ResourceParserTest, ParseAttr) {
}
TEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) {
- std::stringstream input;
- input << "<declare-styleable name=\"Styleable\">" << std::endl
- << " <attr name=\"foo\" />" << std::endl
- << "</declare-styleable>" << std::endl
- << "<attr name=\"foo\" format=\"string\"/>" << std::endl;
+ std::string input = "<declare-styleable name=\"Styleable\">\n"
+ " <attr name=\"foo\" />\n"
+ "</declare-styleable>\n"
+ "<attr name=\"foo\" format=\"string\"/>";
ASSERT_TRUE(testParse(input));
const Attribute* attr = findResource<Attribute>(ResourceName{
@@ -225,14 +221,12 @@ TEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) {
}
TEST_F(ResourceParserTest, ParseDoubleUseOfAttr) {
- std::stringstream input;
- input << "<declare-styleable name=\"Theme\">" << std::endl
- << " <attr name=\"foo\" />" << std::endl
- << "</declare-styleable>" << std::endl
- << "<declare-styleable name=\"Window\">" << std::endl
- << " <attr name=\"foo\" format=\"boolean\"/>" << std::endl
- << "</declare-styleable>" << std::endl;
-
+ std::string input = "<declare-styleable name=\"Theme\">"
+ " <attr name=\"foo\" />\n"
+ "</declare-styleable>\n"
+ "<declare-styleable name=\"Window\">\n"
+ " <attr name=\"foo\" format=\"boolean\"/>\n"
+ "</declare-styleable>";
ASSERT_TRUE(testParse(input));
const Attribute* attr = findResource<Attribute>(ResourceName{
@@ -242,12 +236,11 @@ TEST_F(ResourceParserTest, ParseDoubleUseOfAttr) {
}
TEST_F(ResourceParserTest, ParseEnumAttr) {
- std::stringstream input;
- input << "<attr name=\"foo\">" << std::endl
- << " <enum name=\"bar\" value=\"0\"/>" << std::endl
- << " <enum name=\"bat\" value=\"1\"/>" << std::endl
- << " <enum name=\"baz\" value=\"2\"/>" << std::endl
- << "</attr>" << std::endl;
+ std::string input = "<attr name=\"foo\">\n"
+ " <enum name=\"bar\" value=\"0\"/>\n"
+ " <enum name=\"bat\" value=\"1\"/>\n"
+ " <enum name=\"baz\" value=\"2\"/>\n"
+ "</attr>";
ASSERT_TRUE(testParse(input));
const Attribute* enumAttr = findResource<Attribute>(ResourceName{
@@ -267,12 +260,11 @@ TEST_F(ResourceParserTest, ParseEnumAttr) {
}
TEST_F(ResourceParserTest, ParseFlagAttr) {
- std::stringstream input;
- input << "<attr name=\"foo\">" << std::endl
- << " <flag name=\"bar\" value=\"0\"/>" << std::endl
- << " <flag name=\"bat\" value=\"1\"/>" << std::endl
- << " <flag name=\"baz\" value=\"2\"/>" << std::endl
- << "</attr>" << std::endl;
+ std::string input = "<attr name=\"foo\">\n"
+ " <flag name=\"bar\" value=\"0\"/>\n"
+ " <flag name=\"bat\" value=\"1\"/>\n"
+ " <flag name=\"baz\" value=\"2\"/>\n"
+ "</attr>";
ASSERT_TRUE(testParse(input));
const Attribute* flagAttr = findResource<Attribute>(ResourceName{
@@ -297,22 +289,20 @@ TEST_F(ResourceParserTest, ParseFlagAttr) {
}
TEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) {
- std::stringstream input;
- input << "<attr name=\"foo\">" << std::endl
- << " <enum name=\"bar\" value=\"0\"/>" << std::endl
- << " <enum name=\"bat\" value=\"1\"/>" << std::endl
- << " <enum name=\"bat\" value=\"2\"/>" << std::endl
- << "</attr>" << std::endl;
+ std::string input = "<attr name=\"foo\">\n"
+ " <enum name=\"bar\" value=\"0\"/>\n"
+ " <enum name=\"bat\" value=\"1\"/>\n"
+ " <enum name=\"bat\" value=\"2\"/>\n"
+ "</attr>";
ASSERT_FALSE(testParse(input));
}
TEST_F(ResourceParserTest, ParseStyle) {
- std::stringstream input;
- input << "<style name=\"foo\" parent=\"@style/fu\">" << std::endl
- << " <item name=\"bar\">#ffffffff</item>" << std::endl
- << " <item name=\"bat\">@string/hey</item>" << std::endl
- << " <item name=\"baz\"><b>hey</b></item>" << std::endl
- << "</style>" << std::endl;
+ std::string input = "<style name=\"foo\" parent=\"@style/fu\">\n"
+ " <item name=\"bar\">#ffffffff</item>\n"
+ " <item name=\"bat\">@string/hey</item>\n"
+ " <item name=\"baz\"><b>hey</b></item>\n"
+ "</style>";
ASSERT_TRUE(testParse(input));
const Style* style = findResource<Style>(ResourceName{
@@ -330,8 +320,7 @@ TEST_F(ResourceParserTest, ParseStyle) {
}
TEST_F(ResourceParserTest, ParseStyleWithShorthandParent) {
- std::stringstream input;
- input << "<style name=\"foo\" parent=\"com.app:Theme\"/>" << std::endl;
+ std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>";
ASSERT_TRUE(testParse(input));
const Style* style = findResource<Style>(
@@ -340,9 +329,34 @@ TEST_F(ResourceParserTest, ParseStyleWithShorthandParent) {
EXPECT_EQ(ResourceNameRef(u"com.app", ResourceType::kStyle, u"Theme"), style->parent.name);
}
+TEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) {
+ std::string input = "<style xmlns:app=\"http://schemas.android.com/apk/res/android\"\n"
+ " name=\"foo\" parent=\"app:Theme\"/>";
+ ASSERT_TRUE(testParse(input));
+
+ const Style* style = findResource<Style>(ResourceName{
+ u"android", ResourceType::kStyle, u"foo" });
+ ASSERT_NE(style, nullptr);
+ EXPECT_EQ(ResourceNameRef(u"android", ResourceType::kStyle, u"Theme"), style->parent.name);
+}
+
+TEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) {
+ std::string input =
+ "<style xmlns:app=\"http://schemas.android.com/apk/res/android\" name=\"foo\">\n"
+ " <item name=\"app:bar\">0</item>\n"
+ "</style>";
+ ASSERT_TRUE(testParse(input));
+
+ const Style* style = findResource<Style>(ResourceName{
+ u"android", ResourceType::kStyle, u"foo" });
+ ASSERT_NE(style, nullptr);
+ ASSERT_EQ(1u, style->entries.size());
+ EXPECT_EQ(ResourceNameRef(u"android", ResourceType::kAttr, u"bar"),
+ style->entries[0].key.name);
+}
+
TEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) {
- std::stringstream input;
- input << "<string name=\"foo\">@+id/bar</string>" << std::endl;
+ std::string input = "<string name=\"foo\">@+id/bar</string>";
ASSERT_TRUE(testParse(input));
const Id* id = findResource<Id>(ResourceName{ u"android", ResourceType::kId, u"bar"});
@@ -350,11 +364,10 @@ TEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) {
}
TEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) {
- std::stringstream input;
- input << "<declare-styleable name=\"foo\">" << std::endl
- << " <attr name=\"bar\" />" << std::endl
- << " <attr name=\"bat\" format=\"string|reference\"/>" << std::endl
- << "</declare-styleable>" << std::endl;
+ std::string input = "<declare-styleable name=\"foo\">\n"
+ " <attr name=\"bar\" />\n"
+ " <attr name=\"bat\" format=\"string|reference\"/>\n"
+ "</declare-styleable>";
ASSERT_TRUE(testParse(input));
const Attribute* attr = findResource<Attribute>(ResourceName{
@@ -376,12 +389,11 @@ TEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) {
}
TEST_F(ResourceParserTest, ParseArray) {
- std::stringstream input;
- input << "<array name=\"foo\">" << std::endl
- << " <item>@string/ref</item>" << std::endl
- << " <item>hey</item>" << std::endl
- << " <item>23</item>" << std::endl
- << "</array>" << std::endl;
+ std::string input = "<array name=\"foo\">\n"
+ " <item>@string/ref</item>\n"
+ " <item>hey</item>\n"
+ " <item>23</item>\n"
+ "</array>";
ASSERT_TRUE(testParse(input));
const Array* array = findResource<Array>(ResourceName{
@@ -395,19 +407,16 @@ TEST_F(ResourceParserTest, ParseArray) {
}
TEST_F(ResourceParserTest, ParsePlural) {
- std::stringstream input;
- input << "<plurals name=\"foo\">" << std::endl
- << " <item quantity=\"other\">apples</item>" << std::endl
- << " <item quantity=\"one\">apple</item>" << std::endl
- << "</plurals>" << std::endl
- << std::endl;
+ std::string input = "<plurals name=\"foo\">\n"
+ " <item quantity=\"other\">apples</item>\n"
+ " <item quantity=\"one\">apple</item>\n"
+ "</plurals>";
ASSERT_TRUE(testParse(input));
}
TEST_F(ResourceParserTest, ParseCommentsWithResource) {
- std::stringstream input;
- input << "<!-- This is a comment -->" << std::endl
- << "<string name=\"foo\">Hi</string>" << std::endl;
+ std::string input = "<!-- This is a comment -->\n"
+ "<string name=\"foo\">Hi</string>";
ASSERT_TRUE(testParse(input));
const ResourceTableType* type;
@@ -425,7 +434,7 @@ TEST_F(ResourceParserTest, ParseCommentsWithResource) {
* (as an ID has no value).
*/
TEST_F(ResourceParserTest, ParsePublicIdAsDefinition) {
- std::stringstream input("<public type=\"id\" name=\"foo\"/>");
+ std::string input = "<public type=\"id\" name=\"foo\"/>";
ASSERT_TRUE(testParse(input));
const Id* id = findResource<Id>(ResourceName{ u"android", ResourceType::kId, u"foo" });
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 02be651..9468860 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -299,16 +299,12 @@ bool ResourceTable::markPublic(const ResourceNameRef& name, const ResourceId res
type->publicStatus.isPublic = true;
entry->publicStatus.isPublic = true;
+ entry->publicStatus.source = source;
if (resId.isValid()) {
type->typeId = resId.typeId();
entry->entryId = resId.entryId();
}
-
- if (entry->values.empty()) {
- entry->values.push_back(ResourceConfigValue{ {}, source, {},
- util::make_unique<Sentinel>() });
- }
return true;
}
@@ -318,12 +314,16 @@ bool ResourceTable::merge(ResourceTable&& other) {
for (auto& otherType : other) {
std::unique_ptr<ResourceTableType>& type = findOrCreateType(otherType->type);
- if (type->publicStatus.isPublic && otherType->publicStatus.isPublic &&
- type->typeId != otherType->typeId) {
- Logger::error() << "can not merge type '" << type->type << "': conflicting public IDs "
- << "(" << type->typeId << " vs " << otherType->typeId << ")."
- << std::endl;
- return false;
+ if (otherType->publicStatus.isPublic) {
+ if (type->publicStatus.isPublic && type->typeId != otherType->typeId) {
+ Logger::error() << "can not merge type '" << type->type
+ << "': conflicting public IDs "
+ << "(" << type->typeId << " vs " << otherType->typeId << ")."
+ << std::endl;
+ return false;
+ }
+ type->publicStatus = std::move(otherType->publicStatus);
+ type->typeId = otherType->typeId;
}
for (auto& otherEntry : otherType->entries) {
@@ -335,13 +335,16 @@ bool ResourceTable::merge(ResourceTable&& other) {
}
std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, *nameToAdd);
- if (entry->publicStatus.isPublic && otherEntry->publicStatus.isPublic &&
- entry->entryId != otherEntry->entryId) {
- Logger::error() << "can not merge entry '" << type->type << "/" << entry->name
- << "': conflicting public IDs "
- << "(" << entry->entryId << " vs " << entry->entryId << ")."
- << std::endl;
- return false;
+ if (otherEntry->publicStatus.isPublic) {
+ if (entry->publicStatus.isPublic && entry->entryId != otherEntry->entryId) {
+ Logger::error() << "can not merge entry '" << type->type << "/" << entry->name
+ << "': conflicting public IDs "
+ << "(" << entry->entryId << " vs " << entry->entryId << ")."
+ << std::endl;
+ return false;
+ }
+ entry->publicStatus = std::move(otherEntry->publicStatus);
+ entry->entryId = otherEntry->entryId;
}
for (ResourceConfigValue& otherValue : otherEntry->values) {
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 3591d11..94bacd8 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -35,6 +35,7 @@ namespace aapt {
*/
struct Public {
bool isPublic = false;
+ SourceLine source;
std::u16string comment;
};
diff --git a/tools/aapt2/Resolver.cpp b/tools/aapt2/ResourceTableResolver.cpp
index ae006ab..0a9f521 100644
--- a/tools/aapt2/Resolver.cpp
+++ b/tools/aapt2/ResourceTableResolver.cpp
@@ -16,9 +16,9 @@
#include "Maybe.h"
#include "NameMangler.h"
-#include "Resolver.h"
#include "Resource.h"
#include "ResourceTable.h"
+#include "ResourceTableResolver.h"
#include "ResourceValues.h"
#include "Util.h"
@@ -29,8 +29,9 @@
namespace aapt {
-Resolver::Resolver(std::shared_ptr<const ResourceTable> table,
- std::shared_ptr<const android::AssetManager> sources) :
+ResourceTableResolver::ResourceTableResolver(
+ std::shared_ptr<const ResourceTable> table,
+ std::shared_ptr<const android::AssetManager> sources) :
mTable(table), mSources(sources) {
const android::ResTable& resTable = mSources->getResources(false);
const size_t packageCount = resTable.getBasePackageCount();
@@ -40,7 +41,7 @@ Resolver::Resolver(std::shared_ptr<const ResourceTable> table,
}
}
-Maybe<ResourceId> Resolver::findId(const ResourceName& name) {
+Maybe<ResourceId> ResourceTableResolver::findId(const ResourceName& name) {
Maybe<Entry> result = findAttribute(name);
if (result) {
return result.value().id;
@@ -48,7 +49,7 @@ Maybe<ResourceId> Resolver::findId(const ResourceName& name) {
return {};
}
-Maybe<Resolver::Entry> Resolver::findAttribute(const ResourceName& name) {
+Maybe<IResolver::Entry> ResourceTableResolver::findAttribute(const ResourceName& name) {
auto cacheIter = mCache.find(name);
if (cacheIter != std::end(mCache)) {
return Entry{ cacheIter->second.id, cacheIter->second.attr.get() };
@@ -97,12 +98,30 @@ Maybe<Resolver::Entry> Resolver::findAttribute(const ResourceName& name) {
return {};
}
+Maybe<ResourceName> ResourceTableResolver::findName(ResourceId resId) {
+ const android::ResTable& table = mSources->getResources(false);
+
+ android::ResTable::resource_name resourceName;
+ if (!table.getResourceName(resId.id, false, &resourceName)) {
+ return {};
+ }
+
+ const ResourceType* type = parseResourceType(StringPiece16(resourceName.type,
+ resourceName.typeLen));
+ assert(type);
+ return ResourceName{
+ { resourceName.package, resourceName.packageLen },
+ *type,
+ { resourceName.name, resourceName.nameLen } };
+}
+
/**
* This is called when we need to lookup a resource name in the AssetManager.
* Since the values in the AssetManager are not parsed like in a ResourceTable,
* we must create Attribute objects here if we find them.
*/
-const Resolver::CacheEntry* Resolver::buildCacheEntry(const ResourceName& name) {
+const ResourceTableResolver::CacheEntry* ResourceTableResolver::buildCacheEntry(
+ const ResourceName& name) {
const android::ResTable& table = mSources->getResources(false);
const StringPiece16 type16 = toString(name.type);
diff --git a/tools/aapt2/ResourceTableResolver.h b/tools/aapt2/ResourceTableResolver.h
new file mode 100644
index 0000000..c8e8ab7
--- /dev/null
+++ b/tools/aapt2/ResourceTableResolver.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_RESOURCE_TABLE_RESOLVER_H
+#define AAPT_RESOURCE_TABLE_RESOLVER_H
+
+#include "Maybe.h"
+#include "Resolver.h"
+#include "Resource.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <memory>
+#include <vector>
+#include <unordered_set>
+
+namespace aapt {
+
+/**
+ * Encapsulates the search of library sources as well as the local ResourceTable.
+ */
+class ResourceTableResolver : public IResolver {
+public:
+ /**
+ * Creates a resolver with a local ResourceTable and an AssetManager
+ * loaded with library packages.
+ */
+ ResourceTableResolver(std::shared_ptr<const ResourceTable> table,
+ std::shared_ptr<const android::AssetManager> sources);
+
+ ResourceTableResolver(const ResourceTableResolver&) = delete; // Not copyable.
+
+ virtual Maybe<ResourceId> findId(const ResourceName& name) override;
+
+ virtual Maybe<Entry> findAttribute(const ResourceName& name) override;
+
+ virtual Maybe<ResourceName> findName(ResourceId resId) override;
+
+ const android::ResTable& getResTable() const;
+
+private:
+ struct CacheEntry {
+ ResourceId id;
+ std::unique_ptr<Attribute> attr;
+ };
+
+ const CacheEntry* buildCacheEntry(const ResourceName& name);
+
+ std::shared_ptr<const ResourceTable> mTable;
+ std::shared_ptr<const android::AssetManager> mSources;
+ std::map<ResourceName, CacheEntry> mCache;
+ std::unordered_set<std::u16string> mIncludedPackages;
+};
+
+inline const android::ResTable& ResourceTableResolver::getResTable() const {
+ return mSources->getResources(false);
+}
+
+} // namespace aapt
+
+#endif // AAPT_RESOURCE_TABLE_RESOLVER_H
diff --git a/tools/aapt2/ResourceTypeExtensions.h b/tools/aapt2/ResourceTypeExtensions.h
index 60e225e..dcbe923 100644
--- a/tools/aapt2/ResourceTypeExtensions.h
+++ b/tools/aapt2/ResourceTypeExtensions.h
@@ -30,6 +30,8 @@ namespace aapt {
* future collisions.
*/
enum {
+ RES_TABLE_PUBLIC_TYPE = 0x000d,
+
/**
* A chunk that holds the string pool
* for source entries (path/to/source:line).
@@ -51,13 +53,6 @@ enum {
struct ExtendedTypes {
enum {
/**
- * A sentinel value used when a resource is defined as
- * public but it has no defined value yet. If we don't
- * flatten it with some value, we will lose its name.
- */
- TYPE_SENTINEL = 0xff,
-
- /**
* A raw string value that hasn't had its escape sequences
* processed nor whitespace removed.
*/
@@ -65,6 +60,38 @@ struct ExtendedTypes {
};
};
+struct Public_header {
+ android::ResChunk_header header;
+
+ /**
+ * The ID of the type this structure refers to.
+ */
+ uint8_t typeId;
+
+ /**
+ * Reserved. Must be 0.
+ */
+ uint8_t res0;
+
+ /**
+ * Reserved. Must be 0.
+ */
+ uint16_t res1;
+
+ /**
+ * Number of public entries.
+ */
+ uint32_t count;
+};
+
+struct Public_entry {
+ uint16_t entryId;
+ uint16_t res0;
+ android::ResStringPool_ref key;
+ android::ResStringPool_ref source;
+ uint32_t sourceLine;
+};
+
/**
* A chunk with type RES_TABLE_SYMBOL_TABLE_TYPE.
* Following the header are count number of SymbolTable_entry
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 3a6d65d..2bf38e4 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -217,25 +217,6 @@ void BinaryPrimitive::print(std::ostream& out) const {
}
}
-bool Sentinel::isWeak() const {
- return true;
-}
-
-bool Sentinel::flatten(android::Res_value& outValue) const {
- outValue.dataType = ExtendedTypes::TYPE_SENTINEL;
- outValue.data = 0;
- return true;
-}
-
-Sentinel* Sentinel::clone(StringPool* /*newPool*/) const {
- return new Sentinel();
-}
-
-void Sentinel::print(std::ostream& out) const {
- out << "(sentinel)";
- return;
-}
-
Attribute::Attribute(bool w, uint32_t t) : weak(w), typeMask(t) {
}
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index e3352f3..f8ece6f 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -206,18 +206,6 @@ struct BinaryPrimitive : public BaseItem<BinaryPrimitive> {
void print(std::ostream& out) const override;
};
-/**
- * Sentinel value that should be ignored in the final output.
- * Mainly used as a placeholder for public entries with no
- * values defined yet.
- */
-struct Sentinel : public BaseItem<Sentinel> {
- bool isWeak() const override;
- bool flatten(android::Res_value& outValue) const override;
- Sentinel* clone(StringPool* newPool) const override;
- void print(std::ostream& out) const override;
-};
-
struct Attribute : public BaseValue<Attribute> {
struct Symbol {
Reference symbol;
@@ -332,10 +320,6 @@ struct ValueVisitor {
visitItem(primitive, args);
}
- virtual void visit(Sentinel& sentinel, ValueVisitorArgs& args) {
- visitItem(sentinel, args);
- }
-
virtual void visit(Attribute& attr, ValueVisitorArgs& args) {}
virtual void visit(Style& style, ValueVisitorArgs& args) {}
virtual void visit(Array& array, ValueVisitorArgs& args) {}
@@ -377,10 +361,6 @@ struct ConstValueVisitor {
visitItem(primitive, args);
}
- virtual void visit(const Sentinel& sentinel, ValueVisitorArgs& args) {
- visitItem(sentinel, args);
- }
-
virtual void visit(const Attribute& attr, ValueVisitorArgs& args) {}
virtual void visit(const Style& style, ValueVisitorArgs& args) {}
virtual void visit(const Array& array, ValueVisitorArgs& args) {}
diff --git a/tools/aapt2/ScopedXmlPullParser.cpp b/tools/aapt2/ScopedXmlPullParser.cpp
index d9ae72c..48da93e 100644
--- a/tools/aapt2/ScopedXmlPullParser.cpp
+++ b/tools/aapt2/ScopedXmlPullParser.cpp
@@ -76,6 +76,11 @@ const std::u16string& ScopedXmlPullParser::getNamespaceUri() const {
return mParser->getNamespaceUri();
}
+bool ScopedXmlPullParser::applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const {
+ return mParser->applyPackageAlias(package, defaultPackage);
+}
+
const std::u16string& ScopedXmlPullParser::getElementNamespace() const {
return mParser->getElementNamespace();
}
diff --git a/tools/aapt2/ScopedXmlPullParser.h b/tools/aapt2/ScopedXmlPullParser.h
index e660499..a040f60 100644
--- a/tools/aapt2/ScopedXmlPullParser.h
+++ b/tools/aapt2/ScopedXmlPullParser.h
@@ -52,25 +52,27 @@ public:
ScopedXmlPullParser& operator=(const ScopedXmlPullParser&) = delete;
~ScopedXmlPullParser();
- Event getEvent() const;
- const std::string& getLastError() const;
- Event next();
+ Event getEvent() const override;
+ const std::string& getLastError() const override;
+ Event next() override;
- const std::u16string& getComment() const;
- size_t getLineNumber() const;
- size_t getDepth() const;
+ const std::u16string& getComment() const override;
+ size_t getLineNumber() const override;
+ size_t getDepth() const override;
- const std::u16string& getText() const;
+ const std::u16string& getText() const override;
- const std::u16string& getNamespacePrefix() const;
- const std::u16string& getNamespaceUri() const;
+ const std::u16string& getNamespacePrefix() const override;
+ const std::u16string& getNamespaceUri() const override;
+ bool applyPackageAlias(std::u16string* package, const std::u16string& defaultPackage)
+ const override;
- const std::u16string& getElementNamespace() const;
- const std::u16string& getElementName() const;
+ const std::u16string& getElementNamespace() const override;
+ const std::u16string& getElementName() const override;
- const_iterator beginAttributes() const;
- const_iterator endAttributes() const;
- size_t getAttributeCount() const;
+ const_iterator beginAttributes() const override;
+ const_iterator endAttributes() const override;
+ size_t getAttributeCount() const override;
private:
XmlPullParser* mParser;
diff --git a/tools/aapt2/SourceXmlPullParser.cpp b/tools/aapt2/SourceXmlPullParser.cpp
index cb6a3c0..8099044 100644
--- a/tools/aapt2/SourceXmlPullParser.cpp
+++ b/tools/aapt2/SourceXmlPullParser.cpp
@@ -17,6 +17,7 @@
#include <iostream>
#include <string>
+#include "Maybe.h"
#include "SourceXmlPullParser.h"
#include "Util.h"
@@ -66,7 +67,25 @@ SourceXmlPullParser::Event SourceXmlPullParser::next() {
}
}
- return getEvent();
+ Event event = getEvent();
+
+ // Record namespace prefixes and package names so that we can do our own
+ // handling of references that use namespace aliases.
+ if (event == Event::kStartNamespace || event == Event::kEndNamespace) {
+ Maybe<std::u16string> result = util::extractPackageFromNamespace(getNamespaceUri());
+ if (event == Event::kStartNamespace) {
+ if (result) {
+ mPackageAliases.emplace_back(getNamespacePrefix(), result.value());
+ }
+ } else {
+ if (result) {
+ assert(mPackageAliases.back().second == result.value());
+ mPackageAliases.pop_back();
+ }
+ }
+ }
+
+ return event;
}
SourceXmlPullParser::Event SourceXmlPullParser::getEvent() const {
@@ -112,6 +131,22 @@ const std::u16string& SourceXmlPullParser::getNamespaceUri() const {
return mEventQueue.front().data2;
}
+bool SourceXmlPullParser::applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const {
+ const auto endIter = mPackageAliases.rend();
+ for (auto iter = mPackageAliases.rbegin(); iter != endIter; ++iter) {
+ if (iter->first == *package) {
+ if (iter->second.empty()) {
+ *package = defaultPackage;
+ } else {
+ *package = iter->second;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
const std::u16string& SourceXmlPullParser::getElementNamespace() const {
const Event currentEvent = getEvent();
if (currentEvent != Event::kStartElement && currentEvent != Event::kEndElement) {
diff --git a/tools/aapt2/SourceXmlPullParser.h b/tools/aapt2/SourceXmlPullParser.h
index ba904ba..15936d6 100644
--- a/tools/aapt2/SourceXmlPullParser.h
+++ b/tools/aapt2/SourceXmlPullParser.h
@@ -17,6 +17,8 @@
#ifndef AAPT_SOURCE_XML_PULL_PARSER_H
#define AAPT_SOURCE_XML_PULL_PARSER_H
+#include "XmlPullParser.h"
+
#include <istream>
#include <libexpat/expat.h>
#include <queue>
@@ -24,8 +26,6 @@
#include <string>
#include <vector>
-#include "XmlPullParser.h"
-
namespace aapt {
class SourceXmlPullParser : public XmlPullParser {
@@ -34,25 +34,28 @@ public:
SourceXmlPullParser(const SourceXmlPullParser& rhs) = delete;
~SourceXmlPullParser();
- Event getEvent() const;
- const std::string& getLastError() const;
- Event next();
+ Event getEvent() const override;
+ const std::string& getLastError() const override ;
+ Event next() override ;
+
+ const std::u16string& getComment() const override;
+ size_t getLineNumber() const override;
+ size_t getDepth() const override;
- const std::u16string& getComment() const;
- size_t getLineNumber() const;
- size_t getDepth() const;
+ const std::u16string& getText() const override;
- const std::u16string& getText() const;
+ const std::u16string& getNamespacePrefix() const override;
+ const std::u16string& getNamespaceUri() const override;
+ bool applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const override;
- const std::u16string& getNamespacePrefix() const;
- const std::u16string& getNamespaceUri() const;
- const std::u16string& getElementNamespace() const;
- const std::u16string& getElementName() const;
+ const std::u16string& getElementNamespace() const override;
+ const std::u16string& getElementName() const override;
- const_iterator beginAttributes() const;
- const_iterator endAttributes() const;
- size_t getAttributeCount() const;
+ const_iterator beginAttributes() const override;
+ const_iterator endAttributes() const override;
+ size_t getAttributeCount() const override;
private:
static void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri);
@@ -80,6 +83,7 @@ private:
const std::u16string mEmpty;
size_t mDepth;
std::stack<std::u16string> mNamespaceUris;
+ std::vector<std::pair<std::u16string, std::u16string>> mPackageAliases;
};
} // namespace aapt
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index b983a53..c19aa98 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -265,25 +265,38 @@ void StringPool::sort(const std::function<bool(const Entry&, const Entry&)>& cmp
);
}
-static uint8_t* encodeLength(uint8_t* data, size_t length) {
- if (length > 0x7fu) {
- *data++ = 0x80u | (0x000000ffu & (length >> 8));
+template <typename T>
+static T* encodeLength(T* data, size_t length) {
+ static_assert(std::is_integral<T>::value, "wat.");
+
+ constexpr size_t kMask = 1 << ((sizeof(T) * 8) - 1);
+ constexpr size_t kMaxSize = kMask - 1;
+ if (length > kMaxSize) {
+ *data++ = kMask | (kMaxSize & (length >> (sizeof(T) * 8)));
}
- *data++ = 0x000000ffu & length;
+ *data++ = length;
return data;
}
-static size_t encodedLengthByteCount(size_t length) {
- return length > 0x7fu ? 2 : 1;
+template <typename T>
+static size_t encodedLengthUnits(size_t length) {
+ static_assert(std::is_integral<T>::value, "wat.");
+
+ constexpr size_t kMask = 1 << ((sizeof(T) * 8) - 1);
+ constexpr size_t kMaxSize = kMask - 1;
+ return length > kMaxSize ? 2 : 1;
}
-bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
+
+bool StringPool::flatten(BigBuffer* out, const StringPool& pool, bool utf8) {
const size_t startIndex = out->size();
android::ResStringPool_header* header = out->nextBlock<android::ResStringPool_header>();
header->header.type = android::RES_STRING_POOL_TYPE;
header->header.headerSize = sizeof(*header);
header->stringCount = pool.size();
- header->flags |= android::ResStringPool_header::UTF8_FLAG;
+ if (utf8) {
+ header->flags |= android::ResStringPool_header::UTF8_FLAG;
+ }
uint32_t* indices = pool.size() != 0 ? out->nextBlock<uint32_t>(pool.size()) : nullptr;
@@ -300,25 +313,31 @@ bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
*indices = out->size() - beforeStringsIndex;
indices++;
- std::string encoded = util::utf16ToUtf8(entry->value);
+ if (utf8) {
+ std::string encoded = util::utf16ToUtf8(entry->value);
+
+ const size_t totalSize = encodedLengthUnits<char>(entry->value.size())
+ + encodedLengthUnits<char>(encoded.length())
+ + encoded.size() + 1;
- const size_t stringByteLength = sizeof(char) * encoded.length();
- const size_t totalSize = encodedLengthByteCount(entry->value.size())
- + encodedLengthByteCount(encoded.length())
- + stringByteLength
- + sizeof(char);
+ char* data = out->nextBlock<char>(totalSize);
- uint8_t* data = out->nextBlock<uint8_t>(totalSize);
+ // First encode the actual UTF16 string length.
+ data = encodeLength(data, entry->value.size());
- // First encode the actual UTF16 string length.
- data = encodeLength(data, entry->value.size());
+ // Now encode the size of the converted UTF8 string.
+ data = encodeLength(data, encoded.length());
+ strncpy(data, encoded.data(), encoded.size());
+ } else {
+ const size_t totalSize = encodedLengthUnits<char16_t>(entry->value.size())
+ + entry->value.size() + 1;
- // Now encode the size of the converted UTF8 string.
- data = encodeLength(data, encoded.length());
+ char16_t* data = out->nextBlock<char16_t>(totalSize);
- memcpy(data, encoded.data(), stringByteLength);
- data += stringByteLength;
- *data = 0;
+ // Encode the actual UTF16 string length.
+ data = encodeLength(data, entry->value.size());
+ strncpy16(data, entry->value.data(), entry->value.size());
+ }
}
out->align4();
@@ -364,4 +383,12 @@ bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
return true;
}
+bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
+ return flatten(out, pool, true);
+}
+
+bool StringPool::flattenUtf16(BigBuffer* out, const StringPool& pool) {
+ return flatten(out, pool, false);
+}
+
} // namespace aapt
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 64772a4..14304a6 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -127,7 +127,7 @@ public:
using const_iterator = std::vector<std::unique_ptr<Entry>>::const_iterator;
static bool flattenUtf8(BigBuffer* out, const StringPool& pool);
- static bool flatten(BigBuffer* out, const StringPool& pool);
+ static bool flattenUtf16(BigBuffer* out, const StringPool& pool);
StringPool() = default;
StringPool(const StringPool&) = delete;
@@ -193,6 +193,8 @@ private:
friend const_iterator begin(const StringPool& pool);
friend const_iterator end(const StringPool& pool);
+ static bool flatten(BigBuffer* out, const StringPool& pool, bool utf8);
+
Ref makeRefImpl(const StringPiece16& str, const Context& context, bool unique);
std::vector<std::unique_ptr<Entry>> mStrings;
diff --git a/tools/aapt2/TableFlattener.cpp b/tools/aapt2/TableFlattener.cpp
index 4aadadc..aa0f1d5 100644
--- a/tools/aapt2/TableFlattener.cpp
+++ b/tools/aapt2/TableFlattener.cpp
@@ -31,8 +31,8 @@
namespace aapt {
struct FlatEntry {
- const ResourceEntry& entry;
- const Value& value;
+ const ResourceEntry* entry;
+ const Value* value;
uint32_t entryKey;
uint32_t sourcePathKey;
uint32_t sourceLine;
@@ -48,10 +48,10 @@ public:
mMap = mOut->nextBlock<android::ResTable_map_entry>();
mMap->key.index = flatEntry.entryKey;
mMap->flags = android::ResTable_entry::FLAG_COMPLEX;
- if (flatEntry.entry.publicStatus.isPublic) {
+ if (flatEntry.entry->publicStatus.isPublic) {
mMap->flags |= android::ResTable_entry::FLAG_PUBLIC;
}
- if (flatEntry.value.isWeak()) {
+ if (flatEntry.value->isWeak()) {
mMap->flags |= android::ResTable_entry::FLAG_WEAK;
}
@@ -211,6 +211,7 @@ struct ValueFlattener : ConstValueVisitor {
virtual void visitItem(const Item& item, ValueVisitorArgs&) override {
result = item.flatten(*mOutValue);
+ mOutValue->res0 = 0;
mOutValue->size = sizeof(*mOutValue);
}
@@ -228,14 +229,14 @@ TableFlattener::TableFlattener(Options options)
bool TableFlattener::flattenValue(BigBuffer* out, const FlatEntry& flatEntry,
SymbolEntryVector* symbols) {
- if (flatEntry.value.isItem()) {
+ if (flatEntry.value->isItem()) {
android::ResTable_entry* entry = out->nextBlock<android::ResTable_entry>();
- if (flatEntry.entry.publicStatus.isPublic) {
+ if (flatEntry.entry->publicStatus.isPublic) {
entry->flags |= android::ResTable_entry::FLAG_PUBLIC;
}
- if (flatEntry.value.isWeak()) {
+ if (flatEntry.value->isWeak()) {
entry->flags |= android::ResTable_entry::FLAG_WEAK;
}
@@ -251,14 +252,14 @@ bool TableFlattener::flattenValue(BigBuffer* out, const FlatEntry& flatEntry,
entry->size += sizeof(*sourceBlock);
}
- const Item* item = static_cast<const Item*>(&flatEntry.value);
+ const Item* item = static_cast<const Item*>(flatEntry.value);
ValueFlattener flattener(out, symbols);
item->accept(flattener, {});
return flattener.result;
}
MapFlattener flattener(out, flatEntry, symbols);
- flatEntry.value.accept(flattener, {});
+ flatEntry.value->accept(flattener, {});
return true;
}
@@ -372,6 +373,15 @@ bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
}
}
+ const size_t beforePublicHeader = typeBlock.size();
+ Public_header* publicHeader = nullptr;
+ if (mOptions.useExtendedChunks) {
+ publicHeader = typeBlock.nextBlock<Public_header>();
+ publicHeader->header.type = RES_TABLE_PUBLIC_TYPE;
+ publicHeader->header.headerSize = sizeof(*publicHeader);
+ publicHeader->typeId = type->typeId;
+ }
+
// The binary resource table lists resource entries for each configuration.
// We store them inverted, where a resource entry lists the values for each
// configuration available. Here we reverse this to match the binary table.
@@ -386,18 +396,35 @@ bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
return false;
}
+ if (publicHeader && entry->publicStatus.isPublic) {
+ // Write the public status of this entry.
+ Public_entry* publicEntry = typeBlock.nextBlock<Public_entry>();
+ publicEntry->entryId = static_cast<uint32_t>(entry->entryId);
+ publicEntry->key.index = static_cast<uint32_t>(keyIndex);
+ publicEntry->source.index = static_cast<uint32_t>(sourcePool.makeRef(
+ util::utf8ToUtf16(entry->publicStatus.source.path)).getIndex());
+ publicEntry->sourceLine = static_cast<uint32_t>(entry->publicStatus.source.line);
+ publicHeader->count += 1;
+ }
+
for (const auto& configValue : entry->values) {
data[configValue.config].push_back(FlatEntry{
- *entry,
- *configValue.value,
+ entry,
+ configValue.value.get(),
static_cast<uint32_t>(keyIndex),
static_cast<uint32_t>(sourcePool.makeRef(util::utf8ToUtf16(
- configValue.source.path)).getIndex()),
+ configValue.source.path)).getIndex()),
static_cast<uint32_t>(configValue.source.line)
});
}
}
+ if (publicHeader) {
+ typeBlock.align4();
+ publicHeader->header.size =
+ static_cast<uint32_t>(typeBlock.size() - beforePublicHeader);
+ }
+
// Begin flattening a configuration for the current type.
for (const auto& entry : data) {
const size_t typeHeaderStart = typeBlock.size();
@@ -415,13 +442,13 @@ bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
const size_t entryStart = typeBlock.size();
for (const FlatEntry& flatEntry : entry.second) {
- assert(flatEntry.entry.entryId < type->entries.size());
- indices[flatEntry.entry.entryId] = typeBlock.size() - entryStart;
+ assert(flatEntry.entry->entryId < type->entries.size());
+ indices[flatEntry.entry->entryId] = typeBlock.size() - entryStart;
if (!flattenValue(&typeBlock, flatEntry, &symbolEntries)) {
Logger::error()
<< "failed to flatten resource '"
<< ResourceNameRef {
- table.getPackage(), type->type, flatEntry.entry.name }
+ table.getPackage(), type->type, flatEntry.entry->name }
<< "' for configuration '"
<< entry.first
<< "'."
@@ -508,9 +535,9 @@ bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
package->name[table.getPackage().length()] = 0;
package->typeStrings = package->header.headerSize;
- StringPool::flattenUtf8(out, typePool);
+ StringPool::flattenUtf16(out, typePool);
package->keyStrings = out->size() - beforePackageIndex;
- StringPool::flattenUtf8(out, keyPool);
+ StringPool::flattenUtf16(out, keyPool);
if (symbolEntryData != nullptr) {
for (size_t i = 0; i < symbolEntries.size(); i++) {
diff --git a/tools/aapt2/Util.cpp b/tools/aapt2/Util.cpp
index c2418eb..7adaf1e 100644
--- a/tools/aapt2/Util.cpp
+++ b/tools/aapt2/Util.cpp
@@ -28,6 +28,9 @@
namespace aapt {
namespace util {
+constexpr const char16_t* kSchemaAuto = u"http://schemas.android.com/apk/res-auto";
+constexpr const char16_t* kSchemaPrefix = u"http://schemas.android.com/apk/res/";
+
static std::vector<std::string> splitAndTransform(const StringPiece& str, char sep,
const std::function<char(char)>& f) {
std::vector<std::string> parts;
@@ -279,5 +282,17 @@ std::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer) {
return data;
}
+Maybe<std::u16string> extractPackageFromNamespace(const std::u16string& namespaceUri) {
+ if (stringStartsWith<char16_t>(namespaceUri, kSchemaPrefix)) {
+ StringPiece16 schemaPrefix = kSchemaPrefix;
+ StringPiece16 package = namespaceUri;
+ return package.substr(schemaPrefix.size(), package.size() - schemaPrefix.size())
+ .toString();
+ } else if (namespaceUri == kSchemaAuto) {
+ return std::u16string();
+ }
+ return {};
+}
+
} // namespace util
} // namespace aapt
diff --git a/tools/aapt2/Util.h b/tools/aapt2/Util.h
index 9f9707c..6015d82 100644
--- a/tools/aapt2/Util.h
+++ b/tools/aapt2/Util.h
@@ -18,6 +18,7 @@
#define AAPT_UTIL_H
#include "BigBuffer.h"
+#include "Maybe.h"
#include "StringPiece.h"
#include <androidfw/ResourceTypes.h>
@@ -277,6 +278,15 @@ inline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0)) {
}
+/**
+ * Returns a package name if the namespace URI is of the form:
+ * http://schemas.android.com/apk/res/<package>
+ *
+ * Special case: if namespaceUri is http://schemas.android.com/apk/res-auto,
+ * returns an empty package name.
+ */
+Maybe<std::u16string> extractPackageFromNamespace(const std::u16string& namespaceUri);
+
} // namespace util
/**
diff --git a/tools/aapt2/XliffXmlPullParser.cpp b/tools/aapt2/XliffXmlPullParser.cpp
index f0950a3..31115f2 100644
--- a/tools/aapt2/XliffXmlPullParser.cpp
+++ b/tools/aapt2/XliffXmlPullParser.cpp
@@ -85,6 +85,11 @@ const std::u16string& XliffXmlPullParser::getNamespaceUri() const {
return mParser->getNamespaceUri();
}
+bool XliffXmlPullParser::applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const {
+ return mParser->applyPackageAlias(package, defaultPackage);
+}
+
const std::u16string& XliffXmlPullParser::getElementNamespace() const {
return mParser->getElementNamespace();
}
diff --git a/tools/aapt2/XliffXmlPullParser.h b/tools/aapt2/XliffXmlPullParser.h
index d4aa222..7791227 100644
--- a/tools/aapt2/XliffXmlPullParser.h
+++ b/tools/aapt2/XliffXmlPullParser.h
@@ -33,25 +33,27 @@ public:
XliffXmlPullParser(const std::shared_ptr<XmlPullParser>& parser);
XliffXmlPullParser(const XliffXmlPullParser& rhs) = delete;
- Event getEvent() const;
- const std::string& getLastError() const;
- Event next();
+ Event getEvent() const override;
+ const std::string& getLastError() const override;
+ Event next() override;
- const std::u16string& getComment() const;
- size_t getLineNumber() const;
- size_t getDepth() const;
+ const std::u16string& getComment() const override;
+ size_t getLineNumber() const override;
+ size_t getDepth() const override;
- const std::u16string& getText() const;
+ const std::u16string& getText() const override;
- const std::u16string& getNamespacePrefix() const;
- const std::u16string& getNamespaceUri() const;
+ const std::u16string& getNamespacePrefix() const override;
+ const std::u16string& getNamespaceUri() const override;
+ bool applyPackageAlias(std::u16string* package, const std::u16string& defaultPackage)
+ const override;
- const std::u16string& getElementNamespace() const;
- const std::u16string& getElementName() const;
+ const std::u16string& getElementNamespace() const override;
+ const std::u16string& getElementName() const override;
- const_iterator beginAttributes() const;
- const_iterator endAttributes() const;
- size_t getAttributeCount() const;
+ const_iterator beginAttributes() const override;
+ const_iterator endAttributes() const override;
+ size_t getAttributeCount() const override;
private:
std::shared_ptr<XmlPullParser> mParser;
diff --git a/tools/aapt2/XmlFlattener.cpp b/tools/aapt2/XmlFlattener.cpp
index dd6f63a..650e624 100644
--- a/tools/aapt2/XmlFlattener.cpp
+++ b/tools/aapt2/XmlFlattener.cpp
@@ -36,56 +36,67 @@
namespace aapt {
constexpr const char16_t* kSchemaAndroid = u"http://schemas.android.com/apk/res/android";
-constexpr const char16_t* kSchemaAuto = u"http://schemas.android.com/apk/res-auto";
-constexpr const char16_t* kSchemaPrefix = u"http://schemas.android.com/apk/res/";
struct AttributeValueFlattener : ValueVisitor {
- struct Args : ValueVisitorArgs {
- Args(std::shared_ptr<Resolver> r, SourceLogger& s, android::Res_value& oV,
- std::shared_ptr<XmlPullParser> p, bool& e, StringPool::Ref& rV,
- std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>>& sR) :
- resolver(r), logger(s), outValue(oV), parser(p), error(e), rawValue(rV),
- stringRefs(sR) {
- }
+ AttributeValueFlattener(
+ std::shared_ptr<IResolver> resolver, SourceLogger* logger,
+ android::Res_value* outValue, std::shared_ptr<XmlPullParser> parser, bool* outError,
+ StringPool::Ref rawValue, std::u16string* defaultPackage,
+ std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>>* outStringRefs) :
+ mResolver(resolver), mLogger(logger), mOutValue(outValue), mParser(parser),
+ mError(outError), mRawValue(rawValue), mDefaultPackage(defaultPackage),
+ mStringRefs(outStringRefs) {
+ }
- std::shared_ptr<Resolver> resolver;
- SourceLogger& logger;
- android::Res_value& outValue;
- std::shared_ptr<XmlPullParser> parser;
- bool& error;
- StringPool::Ref& rawValue;
- std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>>& stringRefs;
- };
+ void visit(Reference& reference, ValueVisitorArgs&) override {
+ // First see if we can convert the package name from a prefix to a real
+ // package name.
+ ResourceName aliasedName = reference.name;
- void visit(Reference& reference, ValueVisitorArgs& a) override {
- Args& args = static_cast<Args&>(a);
+ if (!reference.name.package.empty()) {
+ // Only if we specified a package do we look for its alias.
+ mParser->applyPackageAlias(&reference.name.package, *mDefaultPackage);
+ } else {
+ reference.name.package = *mDefaultPackage;
+ }
- Maybe<ResourceId> result = args.resolver->findId(reference.name);
+ Maybe<ResourceId> result = mResolver->findId(reference.name);
if (!result || !result.value().isValid()) {
- args.logger.error(args.parser->getLineNumber())
+ std::ostream& out = mLogger->error(mParser->getLineNumber())
<< "unresolved reference '"
- << reference.name
- << "'."
- << std::endl;
- args.error = true;
+ << aliasedName
+ << "'";
+ if (aliasedName != reference.name) {
+ out << " (aka '" << reference.name << "')";
+ }
+ out << "'." << std::endl;
+ *mError = true;
} else {
reference.id = result.value();
- reference.flatten(args.outValue);
+ reference.flatten(*mOutValue);
}
}
- void visit(String& string, ValueVisitorArgs& a) override {
- Args& args = static_cast<Args&>(a);
-
- args.outValue.dataType = android::Res_value::TYPE_STRING;
- args.stringRefs.emplace_back(args.rawValue,
- reinterpret_cast<android::ResStringPool_ref*>(&args.outValue.data));
+ void visit(String& string, ValueVisitorArgs&) override {
+ mOutValue->dataType = android::Res_value::TYPE_STRING;
+ mStringRefs->emplace_back(
+ mRawValue,
+ reinterpret_cast<android::ResStringPool_ref*>(mOutValue->data));
}
- void visitItem(Item& item, ValueVisitorArgs& a) override {
- Args& args = static_cast<Args&>(a);
- item.flatten(args.outValue);
+ void visitItem(Item& item, ValueVisitorArgs&) override {
+ item.flatten(*mOutValue);
}
+
+private:
+ std::shared_ptr<IResolver> mResolver;
+ SourceLogger* mLogger;
+ android::Res_value* mOutValue;
+ std::shared_ptr<XmlPullParser> mParser;
+ bool* mError;
+ StringPool::Ref mRawValue;
+ std::u16string* mDefaultPackage;
+ std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>>* mStringRefs;
};
struct XmlAttribute {
@@ -100,7 +111,7 @@ static bool lessAttributeId(const XmlAttribute& a, uint32_t id) {
}
XmlFlattener::XmlFlattener(const std::shared_ptr<ResourceTable>& table,
- const std::shared_ptr<Resolver>& resolver) :
+ const std::shared_ptr<IResolver>& resolver) :
mTable(table), mResolver(resolver) {
}
@@ -184,8 +195,13 @@ Maybe<size_t> XmlFlattener::flatten(const Source& source,
node->comment.index = -1;
android::ResXMLTree_attrExt* elem = out.nextBlock<android::ResXMLTree_attrExt>();
- stringRefs.emplace_back(
- pool.makeRef(parser->getElementNamespace(), lowPriority), &elem->ns);
+ if (!parser->getElementNamespace().empty()) {
+ stringRefs.emplace_back(
+ pool.makeRef(parser->getElementNamespace(), lowPriority), &elem->ns);
+ } else {
+ // The device doesn't think a string of size 0 is the same as null.
+ elem->ns.index = -1;
+ }
stringRefs.emplace_back(
pool.makeRef(parser->getElementName(), lowPriority), &elem->name);
elem->attributeStart = sizeof(*elem);
@@ -222,28 +238,25 @@ Maybe<size_t> XmlFlattener::flatten(const Source& source,
}
- StringPiece16 package;
- if (util::stringStartsWith<char16_t>(attrIter->namespaceUri, kSchemaPrefix)) {
- StringPiece16 schemaPrefix = kSchemaPrefix;
- package = attrIter->namespaceUri;
- package = package.substr(schemaPrefix.size(),
- package.size() - schemaPrefix.size());
- } else if (attrIter->namespaceUri == kSchemaAuto && mResolver) {
- package = mResolver->getDefaultPackage();
- }
-
- if (package.empty() || !mResolver) {
+ Maybe<std::u16string> package = util::extractPackageFromNamespace(
+ attrIter->namespaceUri);
+ if (!package || !mResolver) {
// Attributes that have no resource ID (because they don't belong to a
// package) should appear after those that do have resource IDs. Assign
- // them some/ integer value that will appear after.
+ // them some integer value that will appear after.
id = 0x80000000u | nextAttributeId++;
nameRef = pool.makeRef(attrIter->name, StringPool::Context{ id });
} else {
// Find the Attribute object via our Resolver.
ResourceName attrName = {
- package.toString(), ResourceType::kAttr, attrIter->name };
- Maybe<Resolver::Entry> result = mResolver->findAttribute(attrName);
+ package.value(), ResourceType::kAttr, attrIter->name };
+
+ if (attrName.package.empty()) {
+ attrName.package = options.defaultPackage;
+ }
+
+ Maybe<IResolver::Entry> result = mResolver->findAttribute(attrName);
if (!result || !result.value().id.isValid()) {
logger.error(parser->getLineNumber())
<< "unresolved attribute '"
@@ -269,7 +282,7 @@ Maybe<size_t> XmlFlattener::flatten(const Source& source,
// Put the attribute name into a package specific pool, since we don't
// want to collapse names from different packages.
- nameRef = packagePools[package.toString()].makeRef(
+ nameRef = packagePools[package.value()].makeRef(
attrIter->name, StringPool::Context{ id });
}
@@ -290,26 +303,32 @@ Maybe<size_t> XmlFlattener::flatten(const Source& source,
for (auto entry : sortedAttributes) {
android::ResXMLTree_attribute* attr =
out.nextBlock<android::ResXMLTree_attribute>();
- stringRefs.emplace_back(
- pool.makeRef(entry.xmlAttr->namespaceUri, lowPriority), &attr->ns);
- StringPool::Ref rawValueRef = pool.makeRef(entry.xmlAttr->value, lowPriority);
- stringRefs.emplace_back(rawValueRef, &attr->rawValue);
+ if (!entry.xmlAttr->namespaceUri.empty()) {
+ stringRefs.emplace_back(
+ pool.makeRef(entry.xmlAttr->namespaceUri, lowPriority), &attr->ns);
+ } else {
+ attr->ns.index = -1;
+ }
+
stringRefs.emplace_back(entry.nameRef, &attr->name);
+ attr->rawValue.index = -1;
+
+ StringPool::Ref rawValueRef = pool.makeRef(entry.xmlAttr->value, lowPriority);
if (entry.attr) {
std::unique_ptr<Item> value = ResourceParser::parseItemForAttribute(
- entry.xmlAttr->value, *entry.attr, mResolver->getDefaultPackage());
+ entry.xmlAttr->value, *entry.attr);
if (value) {
- AttributeValueFlattener flattener;
- value->accept(flattener, AttributeValueFlattener::Args{
+ AttributeValueFlattener flattener(
mResolver,
- logger,
- attr->typedValue,
+ &logger,
+ &attr->typedValue,
parser,
- error,
+ &error,
rawValueRef,
- stringRefs
- });
+ &options.defaultPackage,
+ &stringRefs);
+ value->accept(flattener, {});
} else if (!(entry.attr->typeMask & android::ResTable_map::TYPE_STRING)) {
logger.error(parser->getLineNumber())
<< "'"
@@ -321,12 +340,14 @@ Maybe<size_t> XmlFlattener::flatten(const Source& source,
error = true;
} else {
attr->typedValue.dataType = android::Res_value::TYPE_STRING;
+ stringRefs.emplace_back(rawValueRef, &attr->rawValue);
stringRefs.emplace_back(rawValueRef,
reinterpret_cast<android::ResStringPool_ref*>(
&attr->typedValue.data));
}
} else {
attr->typedValue.dataType = android::Res_value::TYPE_STRING;
+ stringRefs.emplace_back(rawValueRef, &attr->rawValue);
stringRefs.emplace_back(rawValueRef,
reinterpret_cast<android::ResStringPool_ref*>(
&attr->typedValue.data));
@@ -438,7 +459,7 @@ Maybe<size_t> XmlFlattener::flatten(const Source& source,
resIdMapChunk->size = outBuffer->size() - beforeResIdMapIndex;
// Flatten the StringPool.
- StringPool::flattenUtf8(outBuffer, pool);
+ StringPool::flattenUtf16(outBuffer, pool);
// Move the temporary BigBuffer into outBuffer->
outBuffer->appendBuffer(std::move(out));
diff --git a/tools/aapt2/XmlFlattener.h b/tools/aapt2/XmlFlattener.h
index 540a5ef..60a500e 100644
--- a/tools/aapt2/XmlFlattener.h
+++ b/tools/aapt2/XmlFlattener.h
@@ -23,6 +23,8 @@
#include "Source.h"
#include "XmlPullParser.h"
+#include <string>
+
namespace aapt {
/**
@@ -34,6 +36,12 @@ class XmlFlattener {
public:
struct Options {
/**
+ * The package to use when a reference has no package specified
+ * (or a namespace URI equals "http://schemas.android.com/apk/res-auto").
+ */
+ std::u16string defaultPackage;
+
+ /**
* If set, tells the XmlFlattener to strip out
* attributes that have been introduced after
* max SDK.
@@ -46,7 +54,7 @@ public:
* and attributes.
*/
XmlFlattener(const std::shared_ptr<ResourceTable>& table,
- const std::shared_ptr<Resolver>& resolver);
+ const std::shared_ptr<IResolver>& resolver);
XmlFlattener(const XmlFlattener&) = delete; // Not copyable.
@@ -62,7 +70,7 @@ public:
private:
std::shared_ptr<ResourceTable> mTable;
- std::shared_ptr<Resolver> mResolver;
+ std::shared_ptr<IResolver> mResolver;
};
} // namespace aapt
diff --git a/tools/aapt2/XmlFlattener_test.cpp b/tools/aapt2/XmlFlattener_test.cpp
index a7d7ac6..b45cd9b 100644
--- a/tools/aapt2/XmlFlattener_test.cpp
+++ b/tools/aapt2/XmlFlattener_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Resolver.h"
+#include "MockResolver.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
#include "SourceXmlPullParser.h"
@@ -36,27 +36,29 @@ constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
class XmlFlattenerTest : public ::testing::Test {
public:
virtual void SetUp() override {
- std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
- table->setPackage(u"android");
- table->setPackageId(0x01);
-
- table->addResource(ResourceName{ {}, ResourceType::kAttr, u"id" },
- ResourceId{ 0x01010000 }, {}, {},
- util::make_unique<Attribute>(false, ResTable_map::TYPE_ANY));
-
- table->addResource(ResourceName{ {}, ResourceType::kId, u"test" },
- ResourceId{ 0x01020000 }, {}, {}, util::make_unique<Id>());
-
- mFlattener = std::make_shared<XmlFlattener>(nullptr,
- std::make_shared<Resolver>(table, std::make_shared<AssetManager>()));
+ std::shared_ptr<IResolver> resolver = std::make_shared<MockResolver>(
+ std::make_shared<ResourceTable>(),
+ std::map<ResourceName, ResourceId>({
+ { ResourceName{ u"android", ResourceType::kAttr, u"attr" },
+ ResourceId{ 0x01010000u } },
+ { ResourceName{ u"android", ResourceType::kId, u"id" },
+ ResourceId{ 0x01020000u } },
+ { ResourceName{ u"com.lib", ResourceType::kAttr, u"attr" },
+ ResourceId{ 0x01010001u } },
+ { ResourceName{ u"com.lib", ResourceType::kId, u"id" },
+ ResourceId{ 0x01020001u } }}));
+
+ mFlattener = std::make_shared<XmlFlattener>(nullptr, resolver);
}
- ::testing::AssertionResult testFlatten(std::istream& in, ResXMLTree* outTree) {
+ ::testing::AssertionResult testFlatten(const std::string& in, ResXMLTree* outTree) {
std::stringstream input(kXmlPreamble);
- input << in.rdbuf() << std::endl;
+ input << in << std::endl;
std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(input);
BigBuffer outBuffer(1024);
- if (!mFlattener->flatten(Source{ "test" }, xmlParser, &outBuffer, {})) {
+ XmlFlattener::Options xmlOptions;
+ xmlOptions.defaultPackage = u"android";
+ if (!mFlattener->flatten(Source{ "test" }, xmlParser, &outBuffer, xmlOptions)) {
return ::testing::AssertionFailure();
}
@@ -71,11 +73,22 @@ public:
};
TEST_F(XmlFlattenerTest, ParseSimpleView) {
- std::stringstream input;
- input << "<View xmlns:android=\"http://schemas.android.com/apk/res/android\"" << std::endl
- << " android:id=\"@id/test\">" << std::endl
- << "</View>" << std::endl;
+ std::string input = "<View xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " android:attr=\"@id/id\">\n"
+ "</View>";
+ ResXMLTree tree;
+ ASSERT_TRUE(testFlatten(input, &tree));
+ while (tree.next() != ResXMLTree::END_DOCUMENT) {
+ ASSERT_NE(tree.getEventType(), ResXMLTree::BAD_DOCUMENT);
+ }
+}
+
+TEST_F(XmlFlattenerTest, ParseViewWithPackageAlias) {
+ std::string input = "<View xmlns:ns1=\"http://schemas.android.com/apk/res/android\"\n"
+ " xmlns:ns2=\"http://schemas.android.com/apk/res/android\"\n"
+ " ns1:attr=\"@ns2:id/id\">\n"
+ "</View>";
ResXMLTree tree;
ASSERT_TRUE(testFlatten(input, &tree));
@@ -84,4 +97,100 @@ TEST_F(XmlFlattenerTest, ParseSimpleView) {
}
}
+::testing::AssertionResult attributeNameAndValueEquals(ResXMLTree* tree, size_t index,
+ ResourceId nameId, ResourceId valueId) {
+ if (index >= tree->getAttributeCount()) {
+ return ::testing::AssertionFailure() << "index " << index << " is out of bounds ("
+ << tree->getAttributeCount() << ")";
+ }
+
+ if (tree->getAttributeNameResID(index) != nameId.id) {
+ return ::testing::AssertionFailure()
+ << "attribute at index " << index << " has ID "
+ << ResourceId{ (uint32_t) tree->getAttributeNameResID(index) }
+ << ". Expected ID " << nameId;
+ }
+
+ if (tree->getAttributeDataType(index) != Res_value::TYPE_REFERENCE) {
+ return ::testing::AssertionFailure() << "attribute at index " << index << " has value of "
+ << "type " << std::hex
+ << tree->getAttributeDataType(index) << std::dec
+ << ". Expected reference (" << std::hex
+ << Res_value::TYPE_REFERENCE << std::dec << ")";
+ }
+
+ if ((uint32_t) tree->getAttributeData(index) != valueId.id) {
+ return ::testing::AssertionFailure()
+ << "attribute at index " << index << " has value " << "with ID "
+ << ResourceId{ (uint32_t) tree->getAttributeData(index) }
+ << ". Expected ID " << valueId;
+ }
+ return ::testing::AssertionSuccess();
+}
+
+TEST_F(XmlFlattenerTest, ParseViewWithShadowedPackageAlias) {
+ std::string input = "<View xmlns:app=\"http://schemas.android.com/apk/res/android\"\n"
+ " app:attr=\"@app:id/id\">\n"
+ " <View xmlns:app=\"http://schemas.android.com/apk/res/com.lib\"\n"
+ " app:attr=\"@app:id/id\"/>\n"
+ "</View>";
+ ResXMLTree tree;
+ ASSERT_TRUE(testFlatten(input, &tree));
+
+ while (tree.next() != ResXMLTree::START_TAG) {
+ ASSERT_NE(tree.getEventType(), ResXMLTree::BAD_DOCUMENT);
+ ASSERT_NE(tree.getEventType(), ResXMLTree::END_DOCUMENT);
+ }
+
+ ASSERT_TRUE(attributeNameAndValueEquals(&tree, 0u, ResourceId{ 0x01010000u },
+ ResourceId{ 0x01020000u }));
+
+ while (tree.next() != ResXMLTree::START_TAG) {
+ ASSERT_NE(tree.getEventType(), ResXMLTree::BAD_DOCUMENT);
+ ASSERT_NE(tree.getEventType(), ResXMLTree::END_DOCUMENT);
+ }
+
+ ASSERT_TRUE(attributeNameAndValueEquals(&tree, 0u, ResourceId{ 0x01010001u },
+ ResourceId{ 0x01020001u }));
+}
+
+TEST_F(XmlFlattenerTest, ParseViewWithLocalPackageAndAliasOfTheSameName) {
+ std::string input = "<View xmlns:android=\"http://schemas.android.com/apk/res/com.lib\"\n"
+ " android:attr=\"@id/id\"/>";
+ ResXMLTree tree;
+ ASSERT_TRUE(testFlatten(input, &tree));
+
+ while (tree.next() != ResXMLTree::START_TAG) {
+ ASSERT_NE(tree.getEventType(), ResXMLTree::BAD_DOCUMENT);
+ ASSERT_NE(tree.getEventType(), ResXMLTree::END_DOCUMENT);
+ }
+
+ // We expect the 'android:attr' to be converted to 'com.lib:attr' due to the namespace
+ // assignment.
+ // However, we didn't give '@id/id' a package, so it should use the default package
+ // 'android', and not be converted from 'android' to 'com.lib'.
+ ASSERT_TRUE(attributeNameAndValueEquals(&tree, 0u, ResourceId{ 0x01010001u },
+ ResourceId{ 0x01020000u }));
+}
+
+/*
+ * The device ResXMLParser in libandroidfw differentiates between empty namespace and null
+ * namespace.
+ */
+TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
+ std::string input = "<View xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ " package=\"android\"/>";
+
+ ResXMLTree tree;
+ ASSERT_TRUE(testFlatten(input, &tree));
+
+ while (tree.next() != ResXMLTree::START_TAG) {
+ ASSERT_NE(tree.getEventType(), ResXMLTree::BAD_DOCUMENT);
+ ASSERT_NE(tree.getEventType(), ResXMLTree::END_DOCUMENT);
+ }
+
+ const StringPiece16 kPackage = u"package";
+ EXPECT_GE(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()), 0);
+}
+
} // namespace aapt
diff --git a/tools/aapt2/XmlPullParser.h b/tools/aapt2/XmlPullParser.h
index 753405c..accfd30 100644
--- a/tools/aapt2/XmlPullParser.h
+++ b/tools/aapt2/XmlPullParser.h
@@ -72,15 +72,26 @@ public:
*/
virtual const std::u16string& getText() const = 0;
- /**
- * Namespace prefix is available for StartNamespace and EndNamespace.
- */
+ //
+ // Namespace prefix and URI are available for StartNamespace and EndNamespace.
+ //
+
virtual const std::u16string& getNamespacePrefix() const = 0;
+ virtual const std::u16string& getNamespaceUri() const = 0;
- /**
- * Namespace URI is available for StartNamespace.
+ /*
+ * Uses the current stack of namespaces to resolve the package. Eg:
+ * xmlns:app = "http://schemas.android.com/apk/res/com.android.app"
+ * ...
+ * android:text="@app:string/message"
+ *
+ * In this case, 'app' will be converted to 'com.android.app'.
+ *
+ * If xmlns:app="http://schemas.android.com/apk/res-auto", then
+ * 'package' will be set to 'defaultPackage'.
*/
- virtual const std::u16string& getNamespaceUri() const = 0;
+ virtual bool applyPackageAlias(std::u16string* package,
+ const std::u16string& defaultPackage) const = 0;
//
// These are available for StartElement and EndElement.
diff --git a/tools/aapt2/data/lib/Makefile b/tools/aapt2/data/lib/Makefile
index 8f56c54..372c225 100644
--- a/tools/aapt2/data/lib/Makefile
+++ b/tools/aapt2/data/lib/Makefile
@@ -56,7 +56,7 @@ $(foreach d,$(PRIVATE_RESOURCE_TYPES),$(eval $(call make-collect-rule,$d)))
# Link: out/package-unaligned.apk <- out/values-v4.apk out/drawable-v4.apk
$(PRIVATE_APK_UNALIGNED): $(PRIVATE_INTERMEDIATE_TABLES) $(PRIVATE_LIBS) AndroidManifest.xml
- $(AAPT) link --manifest AndroidManifest.xml $(addprefix -I ,$(PRIVATE_LIBS)) --java $(LOCAL_GEN) -o $@ $(PRIVATE_INTERMEDIATE_TABLES)
+ $(AAPT) link --manifest AndroidManifest.xml $(addprefix -I ,$(PRIVATE_LIBS)) --java $(LOCAL_GEN) -o $@ $(PRIVATE_INTERMEDIATE_TABLES) --static-lib
# R.java: gen/com/android/app/R.java <- out/resources.arsc
# No action since R.java is generated when out/resources.arsc is.
diff --git a/tools/aapt2/data/lib/res/values/styles.xml b/tools/aapt2/data/lib/res/values/styles.xml
index adb5c4f..4ce6333 100644
--- a/tools/aapt2/data/lib/res/values/styles.xml
+++ b/tools/aapt2/data/lib/res/values/styles.xml
@@ -3,4 +3,6 @@
<style name="Platform.AppCompat" parent="@android:style/Theme">
<item name="android:windowNoTitle">true</item>
</style>
+
+ <bool name="allow">true</bool>
</resources>
diff --git a/tools/aapt2/data/res/layout/main.xml b/tools/aapt2/data/res/layout/main.xml
index 5160570..77ccedb 100644
--- a/tools/aapt2/data/res/layout/main.xml
+++ b/tools/aapt2/data/res/layout/main.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -11,7 +12,7 @@
android:layout_width="1dp"
android:text="@{user.name}"
android:layout_height="match_parent"
- app:layout_width="false"
+ app:layout_width="@support:bool/allow"
app:flags="complex|weak"
android:colorAccent="#ffffff"/>
</LinearLayout>
diff --git a/tools/aapt2/data/res/values/styles.xml b/tools/aapt2/data/res/values/styles.xml
index c5dd276..d0b19a3 100644
--- a/tools/aapt2/data/res/values/styles.xml
+++ b/tools/aapt2/data/res/values/styles.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<resources>
+<resources xmlns:lib="http://schemas.android.com/apk/res/android.appcompat">
<style name="App" parent="android.appcompat:Platform.AppCompat">
<item name="android:background">@color/primary</item>
<item name="android:colorPrimary">@color/primary</item>
@@ -9,6 +9,7 @@
<attr name="custom" format="reference" />
<style name="Pop">
<item name="custom">@drawable/image</item>
+ <item name="android:focusable">@lib:bool/allow</item>
</style>
<string name="yo">@string/wow</string>
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index 013e570..d9ddf08 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -52,7 +52,8 @@ hostStaticLibs := \
libutils \
libcutils \
libexpat \
- libziparchive-host
+ libziparchive-host \
+ libbase
cFlags := -Wall -Werror
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0e888e8..00cdc71 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -25,6 +25,7 @@ import android.net.wifi.WifiChannel;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConnectionStatistics;
import android.net.wifi.WifiActivityEnergyInfo;
+import android.net.Network;
import android.net.DhcpInfo;
@@ -168,5 +169,7 @@ interface IWifiManager
void disableEphemeralNetwork(String SSID);
void factoryReset();
+
+ Network getCurrentNetwork();
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index d2fb0dd..dde8dba 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -134,6 +134,8 @@ public class RttManager {
public static final int REASON_NOT_AVAILABLE = -2;
public static final int REASON_INVALID_LISTENER = -3;
public static final int REASON_INVALID_REQUEST = -4;
+ /** Do not have required permission */
+ public static final int REASON_PERMISSION_DENIED = -5;
public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description";
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index b731316..a38a96e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -926,7 +926,7 @@ public class WifiConfiguration implements Parcelable {
public boolean isValid() {
String reason = strIsValid();
if (reason != null) {
- Log.e("WFII", "WiFi Config not valid: " + reason);
+ Log.e(TAG, "WiFi Config not valid: " + reason);
return false;
}
else {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 3205351..5e99672 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2804,4 +2804,17 @@ public class WifiManager {
} catch (RemoteException e) {
}
}
+
+ /**
+ * Get Network object of current wifi network
+ * @return Get Network object of current wifi network
+ * @hide
+ */
+ public Network getCurrentNetwork() {
+ try {
+ return mService.getCurrentNetwork();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
}