summaryrefslogtreecommitdiff
path: root/android/ultimate
diff options
context:
space:
mode:
authorEugene Kudelevsky <Eugene.Kudelevsky@jetbrains.com>2013-10-07 10:36:56 +0400
committerTor Norbye <tnorbye@google.com>2013-10-10 10:07:24 -0700
commit5ec60f348b1b73004e9c62fc88592a6afd659833 (patch)
tree0e4c58b04d1403a01723a8c0c6dfab37c9ed97e3 /android/ultimate
parentc694bba2a8637a147dd9dff8b833a8be816f7baf (diff)
downloadidea-5ec60f348b1b73004e9c62fc88592a6afd659833.tar.gz
install command line tool onto device to get exact modification time; use it instead of ls and md5 computation, since md5 may be not available on some devices
Diffstat (limited to 'android/ultimate')
-rw-r--r--android/ultimate/get_modification_time/jni/Android.mk22
-rw-r--r--android/ultimate/get_modification_time/jni/Application.mk1
-rw-r--r--android/ultimate/get_modification_time/jni/get_modification_time.c15
-rwxr-xr-xandroid/ultimate/src/native_tools/armeabi-v7a/get_modification_timebin0 -> 9500 bytes
-rwxr-xr-xandroid/ultimate/src/native_tools/armeabi/get_modification_timebin0 -> 9496 bytes
-rwxr-xr-xandroid/ultimate/src/native_tools/mips/get_modification_timebin0 -> 5356 bytes
-rwxr-xr-xandroid/ultimate/src/native_tools/x86/get_modification_timebin0 -> 5276 bytes
-rw-r--r--android/ultimate/src/org/jetbrains/android/database/AndroidDbUtil.java197
-rw-r--r--android/ultimate/src/org/jetbrains/android/database/AndroidRemoteDataBaseManager.java3
-rw-r--r--android/ultimate/src/org/jetbrains/android/database/AndroidSynchronizeHandler.java13
-rw-r--r--android/ultimate/src/org/jetbrains/android/database/AndroidUploadDatabaseAction.java7
11 files changed, 186 insertions, 72 deletions
diff --git a/android/ultimate/get_modification_time/jni/Android.mk b/android/ultimate/get_modification_time/jni/Android.mk
new file mode 100644
index 00000000000..f9092b41024
--- /dev/null
+++ b/android/ultimate/get_modification_time/jni/Android.mk
@@ -0,0 +1,22 @@
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := get_modification_time
+LOCAL_SRC_FILES := get_modification_time.c
+
+include $(BUILD_EXECUTABLE)
diff --git a/android/ultimate/get_modification_time/jni/Application.mk b/android/ultimate/get_modification_time/jni/Application.mk
new file mode 100644
index 00000000000..a252a72d729
--- /dev/null
+++ b/android/ultimate/get_modification_time/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/android/ultimate/get_modification_time/jni/get_modification_time.c b/android/ultimate/get_modification_time/jni/get_modification_time.c
new file mode 100644
index 00000000000..0ccd2705029
--- /dev/null
+++ b/android/ultimate/get_modification_time/jni/get_modification_time.c
@@ -0,0 +1,15 @@
+#include <sys/stat.h>
+#include <stdio.h>
+
+int main(int argc, char** args) {
+ struct stat st;
+ char* filename = args[1];
+
+ if (stat(filename, &st) < 0) {
+ perror(filename);
+ return 1;
+ }
+ printf("%lu\n", st.st_mtime);
+ return 0;
+}
+
diff --git a/android/ultimate/src/native_tools/armeabi-v7a/get_modification_time b/android/ultimate/src/native_tools/armeabi-v7a/get_modification_time
new file mode 100755
index 00000000000..022854b551d
--- /dev/null
+++ b/android/ultimate/src/native_tools/armeabi-v7a/get_modification_time
Binary files differ
diff --git a/android/ultimate/src/native_tools/armeabi/get_modification_time b/android/ultimate/src/native_tools/armeabi/get_modification_time
new file mode 100755
index 00000000000..1e68fd5ac4b
--- /dev/null
+++ b/android/ultimate/src/native_tools/armeabi/get_modification_time
Binary files differ
diff --git a/android/ultimate/src/native_tools/mips/get_modification_time b/android/ultimate/src/native_tools/mips/get_modification_time
new file mode 100755
index 00000000000..ae60c2ade1c
--- /dev/null
+++ b/android/ultimate/src/native_tools/mips/get_modification_time
Binary files differ
diff --git a/android/ultimate/src/native_tools/x86/get_modification_time b/android/ultimate/src/native_tools/x86/get_modification_time
new file mode 100755
index 00000000000..f481f260985
--- /dev/null
+++ b/android/ultimate/src/native_tools/x86/get_modification_time
Binary files differ
diff --git a/android/ultimate/src/org/jetbrains/android/database/AndroidDbUtil.java b/android/ultimate/src/org/jetbrains/android/database/AndroidDbUtil.java
index 29636cee73b..7552969ee02 100644
--- a/android/ultimate/src/org/jetbrains/android/database/AndroidDbUtil.java
+++ b/android/ultimate/src/org/jetbrains/android/database/AndroidDbUtil.java
@@ -1,9 +1,6 @@
package org.jetbrains.android.database;
-import com.android.ddmlib.AndroidDebugBridge;
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.MultiLineReceiver;
-import com.android.ddmlib.SyncService;
+import com.android.ddmlib.*;
import com.intellij.javaee.dataSource.LoaderContext;
import com.intellij.javaee.module.view.dataSource.DataSourceUiUtil;
import com.intellij.javaee.module.view.dataSource.LocalDataSource;
@@ -12,16 +9,17 @@ import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.persistence.database.autoconfig.DataSourceConfigUtil;
import com.intellij.persistence.database.autoconfig.MissingDriversNotification;
+import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.io.File;
+import java.io.*;
+import java.net.URL;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* @author Eugene.Kudelevsky
@@ -31,11 +29,10 @@ class AndroidDbUtil {
public static final Object DB_SYNC_LOCK = new Object();
public static final String TEMP_REMOTE_DB_PATH = "/data/local/tmp/intellij_temp_db_file";
+ public static final String TEMP_REMOTE_GET_MODIFICATION_TIME_TOOL_PATH =
+ "/data/local/tmp/intellij_native_tools/get_modification_time";
public static final long DB_COPYING_TIMEOUT_SEC = 30;
public static final int SHELL_COMMAND_TIMEOUT_SECONDS = 2;
- private static final Pattern LS_L_OUTPUT_PATTERN = Pattern.compile(
- "^([bcdlsp-][-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xstST])\\s+(\\S+)\\s+(\\S+)\\s+" +
- "([\\d\\s,]*)\\s+(\\d{4}-\\d\\d-\\d\\d)\\s+(\\d\\d:\\d\\d)\\s+(.*)$");
private AndroidDbUtil() {
}
@@ -175,44 +172,150 @@ class AndroidDbUtil {
return null;
}
- @Nullable
- public static String getRemoteDbModificationTimeAndSize(@NotNull IDevice device,
- @NotNull final String packageName,
- @NotNull String dbName,
- @NotNull AndroidDbErrorReporter errorReporter) {
- final String command = "run-as " + packageName + " ls -l /data/data/" + packageName + "/databases/" + dbName;
- final String result = executeSingleCommand(device, errorReporter, command);
- return result != null ? parseModificationTimeAndSizeFromLsResult(result, errorReporter) : null;
+
+ private static boolean installGetModificationTimeTool(@NotNull IDevice device,
+ @NotNull AndroidDbErrorReporter reporter,
+ @NotNull ProgressIndicator progressIndicator) {
+ String abi = device.getProperty("ro.product.cpu.abi");
+
+ if (abi == null) {
+ abi = "armeabi";
+ }
+ final String urlStr = "/native_tools/" + abi + "/get_modification_time";
+ final URL url = AndroidDbUtil.class.getResource(urlStr);
+
+ if (url == null) {
+ LOG.error("Cannot find resource " + urlStr);
+ return false;
+ }
+ final String remoteToolPath = TEMP_REMOTE_GET_MODIFICATION_TIME_TOOL_PATH;
+
+ if (!pushGetModificationTimeTool(device, url, reporter, progressIndicator, remoteToolPath)) {
+ return false;
+ }
+ final String chmodResult = executeSingleCommand(device, reporter, "chmod 755 " + remoteToolPath);
+
+ if (chmodResult == null) {
+ return false;
+ }
+ if (!chmodResult.isEmpty()) {
+ reporter.reportError(chmodResult);
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean pushGetModificationTimeTool(@NotNull IDevice device,
+ @NotNull URL url,
+ @NotNull AndroidDbErrorReporter reporter,
+ @NotNull ProgressIndicator progressIndicator,
+ @NotNull String remotePath) {
+ final File toolLocalCopy;
+
+ try {
+ toolLocalCopy = FileUtil.createTempFile("android_get_modification_time_tool", "tmp");
+ }
+ catch (IOException e) {
+ reporter.reportError(e);
+ return false;
+ }
+ try {
+ if (!copyResourceToFile(url, toolLocalCopy, reporter)) {
+ return false;
+ }
+
+ try {
+ final SyncService service = device.getSyncService();
+ try {
+ service.pushFile(toolLocalCopy.getPath(), remotePath,
+ new MySyncProgressMonitor(progressIndicator));
+ }
+ finally {
+ service.close();
+ }
+ }
+ catch (Exception e) {
+ reporter.reportError(e);
+ return false;
+ }
+ }
+ finally {
+ FileUtil.delete(toolLocalCopy);
+ }
+ return true;
+ }
+
+ private static boolean copyResourceToFile(@NotNull URL url, @NotNull File file, @NotNull AndroidDbErrorReporter reporter) {
+ try {
+ final InputStream is = new BufferedInputStream(URLUtil.openStream(url));
+ final OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
+
+ try {
+ FileUtil.copy(is, os);
+ }
+ finally {
+ is.close();
+ os.close();
+ }
+ }
+ catch (IOException e) {
+ reporter.reportError(e);
+ return false;
+ }
+ return true;
}
@Nullable
- static String getRemoteDbMd5Hash(@NotNull IDevice device,
- @NotNull final String packageName,
- @NotNull String dbName,
- @NotNull AndroidDbErrorReporter errorReporter) {
- final String command = "run-as " + packageName + " md5 /data/data/" + packageName + "/databases/" + dbName;
- final String result = executeSingleCommand(device, errorReporter, command);
-
- if (result == null) {
+ public static Long getModificationTime(@NotNull IDevice device,
+ @NotNull final String packageName,
+ @NotNull String dbName,
+ @NotNull AndroidDbErrorReporter errorReporter,
+ @NotNull ProgressIndicator progressIndicator) {
+ final String path = TEMP_REMOTE_GET_MODIFICATION_TIME_TOOL_PATH;
+ final String lsResult = executeSingleCommand(device, errorReporter, "ls " + path);
+
+ if (lsResult == null) {
return null;
}
- if (result.startsWith("run-as:")) {
- errorReporter.reportError(result);
- return null;
+ boolean reinstalled = false;
+
+ if (!lsResult.equals(path)) {
+ if (!installGetModificationTimeTool(device, errorReporter, progressIndicator)) {
+ return null;
+ }
+ reinstalled = true;
}
- final int idx = result.indexOf(' ');
+ Long l = doGetModificationTime(device, packageName, dbName, errorReporter);
- if (idx < 0) {
- errorReporter.reportError(result);
- return null;
+ if (l != null) {
+ return l;
+ }
+ if (!reinstalled) {
+ // get_modification_time tools seems to be broken, so reinstall it for future
+ installGetModificationTimeTool(device, errorReporter, progressIndicator);
}
- final String md5Str = result.substring(0, idx);
+ return null;
+ }
- if (md5Str.length() != 32) {
- errorReporter.reportError(result);
+ @Nullable
+ private static Long doGetModificationTime(@NotNull IDevice device,
+ @NotNull String packageName,
+ @NotNull String dbName,
+ @NotNull AndroidDbErrorReporter errorReporter) {
+ final String command = "run-as " + packageName + " " + TEMP_REMOTE_GET_MODIFICATION_TIME_TOOL_PATH +
+ " /data/data/" + packageName + "/databases/" + dbName;
+ final String s = executeSingleCommand(device, errorReporter, command);
+
+ if (s == null) {
+ return null;
+ }
+ try {
+ return Long.parseLong(s);
+ }
+ catch (NumberFormatException e) {
+ errorReporter.reportError(s);
return null;
}
- return md5Str;
}
@Nullable
@@ -231,26 +334,6 @@ class AndroidDbUtil {
return receiver.getOutput();
}
- @Nullable
- private static String parseModificationTimeAndSizeFromLsResult(@NotNull String s, @NotNull AndroidDbErrorReporter errorReporter) {
- final Matcher matcher = LS_L_OUTPUT_PATTERN.matcher(s);
-
- if (!matcher.matches()) {
- errorReporter.reportError(s);
- return null;
- }
- final String sizeStr = matcher.group(4);
- final String dateStr = matcher.group(5);
- final String timeStr = matcher.group(6);
- final String fullDateStr = dateStr + "|" + timeStr + "|" + sizeStr;
-
- if (sizeStr.length() == 0 || dateStr.length() == 0 || timeStr.length() == 0) {
- LOG.error("Incorrect ls output: " + fullDateStr);
- return null;
- }
- return fullDateStr;
- }
-
public static void detectDriverAndRefresh(@NotNull Project project, @NotNull AndroidDataSource dataSource, boolean create) {
if (!DataSourceConfigUtil.detectDriverClassPath(project, dataSource.getDriverClass(), dataSource.getClasspathElements())) {
final String message =
diff --git a/android/ultimate/src/org/jetbrains/android/database/AndroidRemoteDataBaseManager.java b/android/ultimate/src/org/jetbrains/android/database/AndroidRemoteDataBaseManager.java
index 8838000ce91..4ec8c9d7913 100644
--- a/android/ultimate/src/org/jetbrains/android/database/AndroidRemoteDataBaseManager.java
+++ b/android/ultimate/src/org/jetbrains/android/database/AndroidRemoteDataBaseManager.java
@@ -173,8 +173,7 @@ public class AndroidRemoteDataBaseManager implements PersistentStateComponent<An
@Tag("db-info")
public static class MyDatabaseInfo {
- public String lsResult = "";
- public String md5Hash = "";
+ public long modificationTime = 0;
public Set<String> referringProjects = new HashSet<String>();
}
}
diff --git a/android/ultimate/src/org/jetbrains/android/database/AndroidSynchronizeHandler.java b/android/ultimate/src/org/jetbrains/android/database/AndroidSynchronizeHandler.java
index dbfea8c1b1b..13d4f9ce331 100644
--- a/android/ultimate/src/org/jetbrains/android/database/AndroidSynchronizeHandler.java
+++ b/android/ultimate/src/org/jetbrains/android/database/AndroidSynchronizeHandler.java
@@ -82,10 +82,10 @@ public class AndroidSynchronizeHandler extends SynchronizeHandler {
final String packageName = dbConnectionInfo.getPackageName();
final String dbName = dbConnectionInfo.getDbName();
- final String lsResult = AndroidDbUtil.getRemoteDbModificationTimeAndSize(device, packageName, dbName, errorReporter);
+ final Long modificationTime = AndroidDbUtil.getModificationTime(device, packageName, dbName, errorReporter, progressIndicator);
progressIndicator.checkCanceled();
- if (lsResult == null) {
+ if (modificationTime == null) {
return;
}
final AndroidRemoteDataBaseManager remoteDbManager = AndroidRemoteDataBaseManager.getInstance();
@@ -94,19 +94,14 @@ public class AndroidSynchronizeHandler extends SynchronizeHandler {
if (info == null) {
info = new AndroidRemoteDataBaseManager.MyDatabaseInfo();
}
- final String remoteDbMd5 = AndroidDbUtil.getRemoteDbMd5Hash(device, packageName, dbName, errorReporter);
progressIndicator.checkCanceled();
- if (remoteDbMd5 == null) {
- return;
- }
final File localDbFile = new File(dataSource.buildLocalDbFileOsPath());
info.referringProjects.add(FileUtil.toCanonicalPath(project.getBasePath()));
- if (!localDbFile.exists() || !lsResult.equals(info.lsResult) || !remoteDbMd5.equals(info.md5Hash)) {
+ if (!localDbFile.exists() || !modificationTime.equals(info.modificationTime)) {
if (AndroidDbUtil.downloadDatabase(device, packageName, dbName, localDbFile, progressIndicator, errorReporter)) {
- info.lsResult = lsResult;
- info.md5Hash = remoteDbMd5;
+ info.modificationTime = modificationTime;
remoteDbManager.setDatabaseInfo(deviceSerialNumber, packageName, dbName, info);
}
}
diff --git a/android/ultimate/src/org/jetbrains/android/database/AndroidUploadDatabaseAction.java b/android/ultimate/src/org/jetbrains/android/database/AndroidUploadDatabaseAction.java
index f8c893aeda6..a6902d2c6ab 100644
--- a/android/ultimate/src/org/jetbrains/android/database/AndroidUploadDatabaseAction.java
+++ b/android/ultimate/src/org/jetbrains/android/database/AndroidUploadDatabaseAction.java
@@ -105,9 +105,9 @@ public class AndroidUploadDatabaseAction extends AnAction {
return;
}
if (AndroidDbUtil.uploadDatabase(device, packageName, dbName, localDbFilePath, indicator, errorReporter)) {
- final String lsResult = AndroidDbUtil.getRemoteDbModificationTimeAndSize(device, packageName, dbName, errorReporter);
+ final Long modificationTime = AndroidDbUtil.getModificationTime(device, packageName, dbName, errorReporter, indicator);
- if (lsResult != null) {
+ if (modificationTime != null) {
final String deviceSerialNumber = device.getSerialNumber();
AndroidRemoteDataBaseManager.MyDatabaseInfo dbInfo = AndroidRemoteDataBaseManager.
getInstance().getDatabaseInfo(deviceSerialNumber, packageName, dbName);
@@ -115,8 +115,7 @@ public class AndroidUploadDatabaseAction extends AnAction {
if (dbInfo == null) {
dbInfo = new AndroidRemoteDataBaseManager.MyDatabaseInfo();
}
- dbInfo.lsResult = lsResult;
- dbInfo.md5Hash = localFileMd5Hash;
+ dbInfo.modificationTime = modificationTime;
AndroidRemoteDataBaseManager.getInstance().setDatabaseInfo(deviceSerialNumber, packageName, dbName, dbInfo);
}
}