Commit c2481863 authored by Haiyang Pan's avatar Haiyang Pan Committed by Commit Bot

Update Android SDK and Android System SDK to Q

Bug: 1003532
Change-Id: Ia6da252f2eae264c383c154e722591e4e3567582
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1824130
Commit-Queue: Haiyang Pan <hypan@google.com>
Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avatarPeter Kotwicz <pkotwicz@chromium.org>
Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarTao Bai <michaelbai@chromium.org>
Reviewed-by: default avatarJohn Budorick <jbudorick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714652}
parent 31378ffa
......@@ -251,11 +251,11 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_build-tools_version
# and whatever else without interference from each other.
'android_sdk_build-tools_version': '5DL7LQQjVMLClXLzLgmGysccPGsGcjJdvH9z5-uetiIC',
'android_sdk_build-tools_version': 'n-b1Qd7iFb8qzHlr1C_jIeu070UDgO_BwePtH42UqGcC',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_emulator_version
# and whatever else without interference from each other.
'android_sdk_emulator_version': 'xhyuoquVvBTcJelgRjMKZeoBVSQRjB7pLVJPt5C9saIC',
'android_sdk_emulator_version': 'f4WdgkPvDdVCE8zBWPzcSIj4N9WFhKp3CSKDWylXuLEC',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_extras_version
# and whatever else without interference from each other.
......@@ -267,15 +267,15 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_platform-tools_version
# and whatever else without interference from each other.
'android_sdk_platform-tools_version': 'MSnxgXN7IurL-MQs1RrTkSFSb8Xd1UtZjLArI8Ty1FgC',
'android_sdk_platform-tools_version': 'n5NRtk1IRM87UHkSNPKGfMf6VL_BfjEOBXhD9uqynhIC',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_platforms_version
# and whatever else without interference from each other.
'android_sdk_platforms_version': 'Kg2t9p0YnQk8bldUv4VA3o156uPXLUfIFAmVZ-Gm5ewC',
'android_sdk_platforms_version': 'yb33klKQV9UzzB-lDSsq36vzhTXOUZ2aRONBvPGwvdcC',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_sources_version
# and whatever else without interference from each other.
'android_sdk_sources_version': 'K9uEn3JvNELEVjjVK_GQD3ZQD3rqAnJSxCWxjmUmRkgC',
'android_sdk_sources_version': '4gxhM8E62bvZpQs7Q3d0DinQaW0RLCIefhXrQBFkNy8C',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_tools_version
# and whatever else without interference from each other.
......@@ -666,7 +666,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_system_sdk',
'version': '0c0a94a9326c045c8aabb7fc418ea9c849b782f2',
'version': '4IAlMU4jo15KjMPF3EUnrPZs0RYoPW8n9jSJ4dvHDWUC',
},
],
'condition': 'checkout_android',
......@@ -714,7 +714,7 @@ deps = {
'src/third_party/android_sdk/public': {
'packages': [
{
'package': 'chromium/third_party/android_sdk/public/build-tools',
'package': 'chromium/third_party/android_sdk/public/build-tools/29.0.2',
'version': Var('android_sdk_build-tools_version'),
},
{
......@@ -734,11 +734,11 @@ deps = {
'version': Var('android_sdk_platform-tools_version'),
},
{
'package': 'chromium/third_party/android_sdk/public/platforms',
'package': 'chromium/third_party/android_sdk/public/platforms/android-29',
'version': Var('android_sdk_platforms_version'),
},
{
'package': 'chromium/third_party/android_sdk/public/sources',
'package': 'chromium/third_party/android_sdk/public/sources/android-29',
'version': Var('android_sdk_sources_version'),
},
{
......
......@@ -7,6 +7,21 @@ import("//android_webview/variables.gni")
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
# TODO(crbug.com/951275): Clean this up once internal code is upstreamed.
android_library("webview_chromium_for_q_upstream_java") {
# Needed for android.webkit.WebViewDelegate.
alternative_android_sdk_dep =
"//third_party/android_sdk:public_framework_system_java"
deps = [
":glue",
]
java_files = [ "java/src/com/android/webview/chromium/WebViewChromiumFactoryProviderForQ.java" ]
jacoco_never_instrument = true
}
android_library("glue") {
deps = [
"//android_webview:android_webview_java",
......
......@@ -4,7 +4,9 @@
package com.android.webview.chromium;
import android.annotation.SuppressLint;
import android.os.Build;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebSettings.PluginState;
import android.webkit.WebSettings.RenderPriority;
......@@ -605,4 +607,37 @@ public class ContentSettingsAdapter extends android.webkit.WebSettings {
// Always false, see http://crbug.com/616583
return false;
}
@Override
@SuppressLint("Override")
public void setForceDark(int forceDarkMode) {
switch (forceDarkMode) {
case WebSettings.FORCE_DARK_OFF:
getAwSettings().setForceDarkMode(AwSettings.FORCE_DARK_OFF);
break;
case WebSettings.FORCE_DARK_AUTO:
getAwSettings().setForceDarkMode(AwSettings.FORCE_DARK_AUTO);
break;
case WebSettings.FORCE_DARK_ON:
getAwSettings().setForceDarkMode(AwSettings.FORCE_DARK_ON);
break;
default:
throw new IllegalArgumentException(
"Force dark mode is not one of FORCE_DARK_(ON|OFF|AUTO)");
}
}
@Override
@SuppressLint("Override")
public int getForceDark() {
switch (getAwSettings().getForceDarkMode()) {
case AwSettings.FORCE_DARK_OFF:
return WebSettings.FORCE_DARK_OFF;
case AwSettings.FORCE_DARK_AUTO:
return WebSettings.FORCE_DARK_AUTO;
case AwSettings.FORCE_DARK_ON:
return WebSettings.FORCE_DARK_ON;
}
return WebSettings.FORCE_DARK_AUTO;
}
}
......@@ -52,6 +52,8 @@ import android.webkit.WebView;
import android.webkit.WebView.VisualStateCallback;
import android.webkit.WebViewClient;
import android.webkit.WebViewProvider;
import android.webkit.WebViewRenderProcess;
import android.webkit.WebViewRenderProcessClient;
import android.widget.TextView;
import androidx.annotation.IntDef;
......@@ -59,6 +61,7 @@ import androidx.annotation.IntDef;
import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwContentsStatics;
import org.chromium.android_webview.AwPrintDocumentAdapter;
import org.chromium.android_webview.AwRenderProcess;
import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.gfx.AwDrawFnImpl;
import org.chromium.android_webview.renderer_priority.RendererPriority;
......@@ -76,10 +79,13 @@ import org.chromium.content_public.browser.UiThreadTaskTraits;
import java.io.BufferedWriter;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
/**
* This class is the delegate to which WebViewProxy forwards all API calls.
......@@ -266,6 +272,75 @@ class WebViewChromium implements WebViewProvider, WebViewProvider.ScrollDelegate
parentContents.supplyContentsForPopup(childContents);
}
@TargetApi(Build.VERSION_CODES.Q)
private static class WebViewRenderProcessAdapter extends WebViewRenderProcess {
private static WeakHashMap<AwRenderProcess, WebViewRenderProcessAdapter> sInstances =
new WeakHashMap<>();
private WeakReference<AwRenderProcess> mAwRenderProcessWeakRef;
public static WebViewRenderProcessAdapter getInstanceFor(AwRenderProcess awRenderProcess) {
if (awRenderProcess == null) {
return null;
}
WebViewRenderProcessAdapter instance = sInstances.get(awRenderProcess);
if (instance == null) {
sInstances.put(awRenderProcess,
instance = new WebViewRenderProcessAdapter(awRenderProcess));
}
return instance;
}
private WebViewRenderProcessAdapter(AwRenderProcess awRenderProcess) {
mAwRenderProcessWeakRef = new WeakReference<>(awRenderProcess);
}
@Override
@SuppressLint("Override")
public boolean terminate() {
AwRenderProcess renderer = mAwRenderProcessWeakRef.get();
if (renderer == null) {
return false;
}
return renderer.terminate();
}
}
private static class WebViewRenderProcessClientAdapter
extends SharedWebViewRendererClientAdapter {
private Executor mExecutor;
private WebViewRenderProcessClient mWebViewRenderProcessClient;
public WebViewRenderProcessClientAdapter(
Executor executor, WebViewRenderProcessClient webViewRenderProcessClient) {
mExecutor = executor;
mWebViewRenderProcessClient = webViewRenderProcessClient;
}
public WebViewRenderProcessClient getWebViewRenderProcessClient() {
return mWebViewRenderProcessClient;
}
@Override
@TargetApi(Build.VERSION_CODES.Q)
public void onRendererUnresponsive(
final WebView view, final AwRenderProcess renderProcess) {
WebViewRenderProcess renderer =
WebViewRenderProcessAdapter.getInstanceFor(renderProcess);
mExecutor.execute(
() -> mWebViewRenderProcessClient.onRenderProcessUnresponsive(view, renderer));
}
@Override
@TargetApi(Build.VERSION_CODES.Q)
public void onRendererResponsive(final WebView view, final AwRenderProcess renderProcess) {
WebViewRenderProcess renderer =
WebViewRenderProcessAdapter.getInstanceFor(renderProcess);
mExecutor.execute(
() -> mWebViewRenderProcessClient.onRenderProcessResponsive(view, renderer));
}
}
// WebViewProvider methods --------------------------------------------------------------------
@Override
......@@ -1466,6 +1541,36 @@ class WebViewChromium implements WebViewProvider, WebViewProvider.ScrollDelegate
return mSharedWebViewChromium.getWebViewClient();
}
@Override
public WebViewRenderProcess getWebViewRenderProcess() {
return WebViewRenderProcessAdapter.getInstanceFor(
mSharedWebViewChromium.getRenderProcess());
}
@Override
public void setWebViewRenderProcessClient(
Executor executor, WebViewRenderProcessClient webViewRenderProcessClient) {
if (webViewRenderProcessClient == null) {
mSharedWebViewChromium.setWebViewRendererClientAdapter(null);
} else {
if (executor == null) {
executor = (Runnable r) -> r.run();
}
mSharedWebViewChromium.setWebViewRendererClientAdapter(
new WebViewRenderProcessClientAdapter(executor, webViewRenderProcessClient));
}
}
@Override
public WebViewRenderProcessClient getWebViewRenderProcessClient() {
SharedWebViewRendererClientAdapter adapter =
mSharedWebViewChromium.getWebViewRendererClientAdapter();
if (adapter == null || !(adapter instanceof WebViewRenderProcessClientAdapter)) {
return null;
}
return ((WebViewRenderProcessClientAdapter) adapter).getWebViewRenderProcessClient();
}
@Override
public void setDownloadListener(DownloadListener listener) {
sWebViewApiCallSample.record(ApiCall.SET_DOWNLOAD_LISTENER);
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.android.webview.chromium;
public class WebViewChromiumFactoryProviderForQ extends WebViewChromiumFactoryProvider {
public static WebViewChromiumFactoryProvider create(android.webkit.WebViewDelegate delegate) {
return new WebViewChromiumFactoryProviderForQ(delegate);
}
protected WebViewChromiumFactoryProviderForQ(android.webkit.WebViewDelegate delegate) {
super(delegate);
}
}
......@@ -218,7 +218,7 @@ class WebViewDelegateFactory {
@Override
public void drawWebViewFunctor(Canvas canvas, int functor) {
throw new RuntimeException();
mDelegate.drawWebViewFunctor(canvas, functor);
}
}
......
......@@ -16,6 +16,10 @@ trichrome_webview_64_32_android_manifest = "$root_gen_dir/android_webview/trichr
upstream_only_webview_deps = [
"//android_webview:platform_service_bridge_upstream_implementation_java",
"//android_webview/apk:icon_resources",
# TODO(crbug.com/951275): Clean this up once relevant internal code
# is upstreamed.
"//android_webview/glue:webview_chromium_for_q_upstream_java",
"//weblayer/browser/java:gms_bridge_upstream_impl_java",
]
......
......@@ -3361,6 +3361,7 @@ if (is_android) {
"android/java/src/org/chromium/base/compat/ApiHelperForO.java",
"android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
"android/java/src/org/chromium/base/compat/ApiHelperForP.java",
"android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
"android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
"android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
"android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
......
......@@ -2,48 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.omnibox.geo;
package org.chromium.base.compat;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.os.Build;
import android.telephony.CellInfo;
import android.telephony.TelephonyManager;
import org.chromium.base.BuildInfo;
import org.chromium.base.Callback;
import org.chromium.base.annotations.VerifiesOnQ;
import org.chromium.base.task.AsyncTask;
import java.util.List;
/**
* Wrapper class to delegate requests for {@link CellInfo} data to {@link TelephonyManager}.
*
* TODO(crbug.com/954620): Replace this class once P builds are no longer supported.
* Utility class to use new APIs that were added in Q (API level 29). These need to exist in a
* separate class so that Android framework can successfully verify classes without
* encountering the new APIs.
*/
class CellInfoDelegate {
static void requestCellInfoUpdate(
TelephonyManager telephonyManager, Callback<List<CellInfo>> callback) {
// Apps targeting Q+ must call a different API to trigger a refresh of the cached CellInfo.
// https://developer.android.com/reference/android/telephony/TelephonyManager.html#getAllCellInfo()
if (BuildInfo.isAtLeastQ()) {
requestCellInfoUpdateAtLeastQ(telephonyManager, callback);
return;
}
requestCellInfoUpdatePreQ(telephonyManager, callback);
}
@VerifiesOnQ
@TargetApi(Build.VERSION_CODES.Q)
public final class ApiHelperForQ {
private ApiHelperForQ() {}
private static void requestCellInfoUpdateAtLeastQ(
/** See {@link TelephonyManager.requestCellInfoUpdate() }. */
public static void requestCellInfoUpdate(
TelephonyManager telephonyManager, Callback<List<CellInfo>> callback) {
telephonyManager.requestCellInfoUpdate(
AsyncTask.THREAD_POOL_EXECUTOR, new TelephonyManager.CellInfoCallback() {
@Override
@SuppressLint("Override")
public void onCellInfo(List<CellInfo> cellInfos) {
callback.onResult(cellInfos);
}
});
}
private static void requestCellInfoUpdatePreQ(
TelephonyManager telephonyManager, Callback<List<CellInfo>> callback) {
callback.onResult(telephonyManager.getAllCellInfo());
}
}
......@@ -126,8 +126,8 @@ generate various related files (e.g. `ui_java_resources_R.txt`):
```sh
python ../../build/android/gyp/process_resources.py \
--depfile gen/ui/android/ui_java_resources_1.d \
--android-sdk-jar ../../third_party/android_sdk/public/platforms/android-28/android.jar \
--aapt-path ../../third_party/android_sdk/public/build-tools/27.0.3/aapt \
--android-sdk-jar ../../third_party/android_sdk/public/platforms/android-29/android.jar \
--aapt-path ../../third_party/android_sdk/public/build-tools/29.0.2/aapt \
--dependencies-res-zips=@FileArg\(gen/ui/android/ui_java_resources.build_config:resources:dependency_zips\) \
--extra-res-packages=@FileArg\(gen/ui/android/ui_java_resources.build_config:resources:extra_package_names\) \
--extra-r-text-files=@FileArg\(gen/ui/android/ui_java_resources.build_config:resources:extra_r_text_files\) \
......
......@@ -236,6 +236,8 @@ Still reading?
<ignore regexp="Static interface method requires API level 24"/>
<!-- 1 This is for testonly target android_support_chromium_java in android_sdk. -->
<ignore regexp="third_party/android_sdk/public/extras/chromium/support/src/org/chromium/android/support/PackageManagerWrapper.java"/>
<!-- 1 TaskInfo is refactored at API 29. -->
<ignore regexp="Field requires API level 29.*`android.app.TaskInfo"/>
<!-- Endnote: Please specify number of suppressions when adding more -->
</issue>
<!-- This warning just adds a lot of false positives. -->
......
......@@ -78,14 +78,18 @@ if (is_android || is_chromeos) {
default_android_sdk_build_tools_version = "29.0.2"
default_android_sdk_tools_version_suffix = "-26.0.0-dev"
public_android_sdk = true
}
if (android_sdk_release == "p") {
} else if (android_sdk_release == "p") {
default_android_sdk_root = "//third_party/android_sdk/public"
default_android_sdk_version = 28
default_android_sdk_build_tools_version = "29.0.2"
default_android_sdk_tools_version_suffix = "-26.0.0-dev"
public_android_sdk = true
} else if (android_sdk_release == "q") {
default_android_sdk_root = "//third_party/android_sdk/public"
default_android_sdk_version = 29
default_android_sdk_build_tools_version = "29.0.2"
default_android_sdk_tools_version_suffix = "-26.0.0-dev"
public_android_sdk = true
}
if (!defined(default_lint_android_sdk_root)) {
......
......@@ -4,7 +4,7 @@
# The default SDK release used by public builds. Value may differ in
# internal builds.
default_android_sdk_release = "p"
default_android_sdk_release = "q"
# SDK releases against which public builds are supported.
public_sdk_releases = [ "p" ]
public_sdk_releases = [ "q" ]
......@@ -1768,6 +1768,10 @@ template("monochrome_public_apk_or_module_tmpl") {
deps += [
":monochrome_java",
"//android_webview:platform_service_bridge_upstream_implementation_java",
# TODO(crbug.com/951275): Clean this up once relevant internal code
# is upstreamed.
"//android_webview/glue:webview_chromium_for_q_upstream_java",
]
}
}
......
......@@ -1119,6 +1119,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java",
"java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java",
"java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java",
"java/src/org/chromium/chrome/browser/omnibox/geo/CellInfoDelegate.java",
"java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
"java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java",
"java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java",
......
<?xml version="1.0" ?>
<manifest
package="org.chromium.chrome"
platformBuildVersionCode="28"
platformBuildVersionName="9"
platformBuildVersionCode="29"
platformBuildVersionName="10"
tools:ignore="MissingVersion"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="28"/>
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="29"/>
<uses-permission-sdk-23 android:name="android.permission.USE_FINGERPRINT"/>
<uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission-sdk-23 android:name="android.permission.REORDER_TASKS"/>
......
......@@ -7,7 +7,9 @@ package org.chromium.chrome.browser.omnibox.geo;
import android.telephony.CellInfo;
import android.telephony.TelephonyManager;
import org.chromium.base.BuildInfo;
import org.chromium.base.Callback;
import org.chromium.base.compat.ApiHelperForQ;
import java.util.List;
......@@ -19,6 +21,10 @@ import java.util.List;
class CellInfoDelegate {
static void requestCellInfoUpdate(
TelephonyManager telephonyManager, Callback<List<CellInfo>> callback) {
if (BuildInfo.isAtLeastQ()) {
ApiHelperForQ.requestCellInfoUpdate(telephonyManager, callback);
return;
}
callback.onResult(telephonyManager.getAllCellInfo());
}
}
......@@ -48,11 +48,3 @@ if (enable_arcore) {
"java/src/org/chromium/chrome/browser/vr/ArImmersiveOverlay.java",
]
}
if (android_sdk_release == "q") {
chrome_java_sources += [ "geo/java/src/org/chromium/chrome/browser/omnibox/geo/CellInfoDelegate.java" ]
} else {
chrome_java_sources += [
"java/src/org/chromium/chrome/browser/omnibox/geo/CellInfoDelegate.java",
]
}
Name: Android SDK
URL: http://developer.android.com/sdk/index.html
Version: 28
Android SDK Build-tools 27.0.3
Android SDK Emulator 29.0.9
Android SDK Platform-tools 28.0.3
Android SDK Platform API 28
Android SDK Sources 28
Version: 29
Android SDK Build-tools 29.0.2
Android SDK Emulator 29.1.12
Android SDK Platform-tools 29.0.3
Android SDK Platform API 29
Android SDK Sources 29
Android SDK Tools 26.1.1
Android Lint 26.4.0-alpha04
Google Cloud Messaging 3
......@@ -38,11 +38,11 @@ No other modifications has been made to the public Android SDK.
Update Instructions:
public/tools/bin/sdkmanager --list # Look for"Installed packages:"
public/tools/bin/sdkmanager --update "name from --list's output"
cipd create --pkg-def cipd_emulator.yaml # For each package updated
Then,
* Update //DEPS with InstanceIds printed by "cipd create".
* public/tools/bin/sdkmanager --list # Look for "Installed packages:"
* Prepare the CIPD yaml files for packages that need update and add them
to android-sdk-packager buildbucket configuation file.
Submit the changes into gerrit (See crrev.com/c/1803895 as a reference)
* Wait till the builder android-sdk-packager create new CIPD packages
* Update //DEPS with InstanceIds from the CIPD
* Update versions in this README.chromium.
* The overall Version field should corresponde to the Platform API version.
......@@ -2,7 +2,7 @@ Name: Android System SDK
URL: http://go/ab
Short Name: Android System SDK
Version: 0
Revision: OPM1.171018.001
Revision: QPP6.190730.006
License: GPL v2
License File: LICENSE
Security Critical: No
......
......@@ -145,7 +145,7 @@ to the classpath for downstream development. See "additional_entries" below.
<classpathentry kind="src" path="ui/android/java/src"/>
<classpathentry kind="src" path="ui/android/javatests/src"/>
<classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/google/gcm/gcm-client/dist/gcm.jar" sourcepath="../src/third_party/android_sdk/public/extras/google/gcm/gcm-client/src"/>
<classpathentry kind="lib" path="../src/third_party/android_sdk/public/platforms/android-28/android.jar" sourcepath="../src/third_party/android_sdk/public/sources/">
<classpathentry kind="lib" path="../src/third_party/android_sdk/public/platforms/android-29/android.jar" sourcepath="../src/third_party/android_sdk/public/sources/">
<attributes>
<attribute name="javadoc_location" value="http://developer.android.com/reference/"/>
</attributes>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment