| /* |
| * Copyright (C) 2014 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. |
| */ |
| |
| package com.android.build.gradle.internal; |
| |
| import static com.android.SdkConstants.FN_LOCAL_PROPERTIES; |
| |
| import com.android.annotations.NonNull; |
| import com.android.annotations.Nullable; |
| import com.android.builder.core.AndroidBuilder; |
| import com.android.builder.sdk.DefaultSdkLoader; |
| import com.android.builder.sdk.PlatformLoader; |
| import com.android.builder.sdk.SdkInfo; |
| import com.android.builder.sdk.SdkLoader; |
| import com.android.builder.sdk.TargetInfo; |
| import com.android.sdklib.repository.FullRevision; |
| import com.android.utils.ILogger; |
| import com.google.common.base.Charsets; |
| import com.google.common.io.Closeables; |
| |
| import org.gradle.api.Project; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.util.Properties; |
| |
| /** |
| * Handles the all things SDK for the Gradle plugin. There is one instance per project, around |
| * a singleton {@link com.android.builder.sdk.SdkLoader}. |
| */ |
| public class SdkHandler { |
| |
| // Used for injecting SDK location in tests. |
| public static File sTestSdkFolder; |
| |
| @NonNull |
| private final ILogger logger; |
| |
| private SdkLoader sdkLoader; |
| private File sdkFolder; |
| private File ndkFolder; |
| private boolean isRegularSdk = true; |
| |
| public static void setTestSdkFolder(File testSdkFolder) { |
| sTestSdkFolder = testSdkFolder; |
| } |
| |
| public SdkHandler(@NonNull Project project, |
| @NonNull ILogger logger) { |
| this.logger = logger; |
| findLocation(project); |
| } |
| |
| public SdkInfo getSdkInfo() { |
| SdkLoader sdkLoader = getSdkLoader(); |
| return sdkLoader.getSdkInfo(logger); |
| } |
| |
| public void initTarget( |
| String targetHash, |
| FullRevision buildToolRevision, |
| @NonNull AndroidBuilder androidBuilder) { |
| if (targetHash == null) { |
| throw new IllegalArgumentException("android.compileSdkVersion is missing!"); |
| } |
| |
| if (buildToolRevision == null) { |
| throw new IllegalArgumentException("android.buildToolsVersion is missing!"); |
| } |
| |
| SdkLoader sdkLoader = getSdkLoader(); |
| |
| SdkInfo sdkInfo = sdkLoader.getSdkInfo(logger); |
| TargetInfo targetInfo = sdkLoader.getTargetInfo(targetHash, buildToolRevision, logger); |
| |
| androidBuilder.setTargetInfo(sdkInfo, targetInfo); |
| } |
| |
| @Nullable |
| public File getSdkFolder() { |
| return sdkFolder; |
| } |
| |
| @Nullable |
| public File getAndCheckSdkFolder() { |
| if (sdkFolder == null) { |
| throw new RuntimeException( |
| "SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable."); |
| } |
| |
| return sdkFolder; |
| } |
| |
| public synchronized SdkLoader getSdkLoader() { |
| if (sdkLoader == null) { |
| if (isRegularSdk) { |
| getAndCheckSdkFolder(); |
| |
| // check if the SDK folder actually exist. |
| // For internal test we provide a fake SDK location through |
| // setTestSdkFolder in order to have an SDK, even though we don't use it |
| // so in this case we ignore the check. |
| if (sTestSdkFolder == null && !sdkFolder.isDirectory()) { |
| throw new RuntimeException(String.format( |
| "The SDK directory '%1$s' does not exist.", sdkFolder)); |
| } |
| |
| sdkLoader = DefaultSdkLoader.getLoader(sdkFolder); |
| } else { |
| sdkLoader = PlatformLoader.getLoader(sdkFolder); |
| } |
| } |
| |
| return sdkLoader; |
| } |
| |
| public synchronized void unload() { |
| if (sdkLoader != null) { |
| if (isRegularSdk) { |
| DefaultSdkLoader.unload(); |
| } else { |
| PlatformLoader.unload(); |
| } |
| |
| sdkLoader = null; |
| } |
| } |
| |
| @Nullable |
| public File getNdkFolder() { |
| return ndkFolder; |
| } |
| |
| private void findSdkLocation(@NonNull Properties properties, @NonNull File rootDir) { |
| String sdkDirProp = properties.getProperty("sdk.dir"); |
| if (sdkDirProp != null) { |
| sdkFolder = new File(sdkDirProp); |
| if (!sdkFolder.isAbsolute()) { |
| sdkFolder = new File(rootDir, sdkDirProp); |
| } |
| return; |
| } |
| |
| sdkDirProp = properties.getProperty("android.dir"); |
| if (sdkDirProp != null) { |
| sdkFolder = new File(rootDir, sdkDirProp); |
| isRegularSdk = false; |
| return; |
| } |
| |
| String envVar = System.getenv("ANDROID_HOME"); |
| if (envVar != null) { |
| sdkFolder = new File(envVar); |
| return; |
| } |
| |
| String property = System.getProperty("android.home"); |
| if (property != null) { |
| sdkFolder = new File(property); |
| } |
| } |
| |
| private void findNdkLocation(@NonNull Properties properties) { |
| String ndkDirProp = properties.getProperty("ndk.dir"); |
| if (ndkDirProp != null) { |
| ndkFolder = new File(ndkDirProp); |
| return; |
| } |
| |
| String envVar = System.getenv("ANDROID_NDK_HOME"); |
| if (envVar != null) { |
| ndkFolder = new File(envVar); |
| } |
| } |
| |
| private void findLocation(@NonNull Project project) { |
| if (sTestSdkFolder != null) { |
| sdkFolder = sTestSdkFolder; |
| return; |
| } |
| |
| File rootDir = project.getRootDir(); |
| File localProperties = new File(rootDir, FN_LOCAL_PROPERTIES); |
| Properties properties = new Properties(); |
| |
| if (localProperties.isFile()) { |
| InputStreamReader reader = null; |
| try { |
| //noinspection IOResourceOpenedButNotSafelyClosed |
| FileInputStream fis = new FileInputStream(localProperties); |
| reader = new InputStreamReader(fis, Charsets.UTF_8); |
| properties.load(reader); |
| } catch (FileNotFoundException ignored) { |
| // ignore since we check up front and we don't want to fail on it anyway |
| // in case there's an env var. |
| } catch (IOException e) { |
| throw new RuntimeException( |
| String.format("Unable to read %1$s.", localProperties.getAbsolutePath()), |
| e); |
| } finally { |
| try { |
| Closeables.close(reader, true /* swallowIOException */); |
| } catch (IOException e) { |
| // ignore. |
| } |
| } |
| } |
| |
| findSdkLocation(properties, rootDir); |
| findNdkLocation(properties); |
| } |
| } |