private static void WriteCommand(string program, string arguments, StreamWriter writer) { if (string.IsNullOrEmpty(program)) { writer.WriteLine("error: program path was null"); } else { string stdOut; string stdErr; ShellHelper.RunCommand(program, arguments, out stdOut, out stdErr); if (!string.IsNullOrEmpty(stdOut)) { writer.WriteLine(stdOut); } if (!string.IsNullOrEmpty(stdErr)) { writer.WriteLine(stdErr); } } writer.WriteLine(); }
private bool _IsApiKeyDirty(string jarPath, string aarPath, string apiKey) { bool isApiKeyDirty = true; var cachedCurrentDirectory = Directory.GetCurrentDirectory(); var tempDirectoryPath = Path.Combine(cachedCurrentDirectory, FileUtil.GetUniqueTempPathInProject()); if (!File.Exists(aarPath)) { return(isApiKeyDirty); } try { // Move to a temp directory. Directory.CreateDirectory(tempDirectoryPath); Directory.SetCurrentDirectory(tempDirectoryPath); var tempAarPath = Path.Combine(tempDirectoryPath, "cloud_anchor_manifest.aar"); File.Copy(aarPath, tempAarPath, true); // Extract the aar. string output; string errors; ShellHelper.RunCommand(jarPath, string.Format("xf \"{0}\"", tempAarPath), out output, out errors); // Read Api key parameter in manifest file. var manifestPath = Path.Combine(tempDirectoryPath, "AndroidManifest.xml"); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(manifestPath); XmlNode metaDataNode = xmlDocument.SelectSingleNode("/manifest/application/meta-data"); string oldApiKey = metaDataNode.Attributes["android:value"].Value; isApiKeyDirty = !apiKey.Equals(oldApiKey); } finally { // Cleanup. Directory.SetCurrentDirectory(cachedCurrentDirectory); Directory.Delete(tempDirectoryPath, true); } return(isApiKeyDirty); }
private static void WritePackageVersionString( string adbPath, string package, StreamWriter writer) { if (string.IsNullOrEmpty(adbPath)) { writer.WriteLine("error: adb path was null"); } else { string stdOut; string stdErr; string arguments = "shell pm dump " + package + " | " + "egrep -m 1 -i 'versionName' | sed -n 's/.*versionName=//p'"; ShellHelper.RunCommand(adbPath, arguments, out stdOut, out stdErr); // If stdOut is populated, the device is connected and the app is installed if (!string.IsNullOrEmpty(stdOut)) { writer.WriteLine(stdOut); } else { // If stdErr isn't empty, then either the device isn't connected or something // else went wrong, such as adb not being installed. if (!string.IsNullOrEmpty(stdErr)) { writer.WriteLine(stdErr); } else { // If stdErr is empty, then the device is connected and the app isn't // installed writer.WriteLine(package + " is not installed on device"); } } } writer.WriteLine(); }
/// <summary> /// Tries to install and run the Instant Preview android app. /// </summary> /// <param name="adbPath">Path to adb to use for installing.</param> /// <param name="localVersion">Local version of Instant Preview plugin to compare installed /// APK against.</param> /// <returns>Enumerator for coroutine that handles installation if necessary.</returns> private static IEnumerator InstallApkAndRunIfConnected(string adbPath, string localVersion) { string apkPath = null; #if UNITY_EDITOR apkPath = UnityEditor.AssetDatabase.GUIDToAssetPath(k_ApkGuid); #endif // !UNITY_EDITOR // Early outs if set to install but the apk can't be found. if (!File.Exists(apkPath)) { Debug.LogErrorFormat( "Trying to install Instant Preview APK but reference to InstantPreview.apk " + "is broken. Couldn't find an asset with .meta file guid={0}.", k_ApkGuid); yield break; } Result result = new Result(); Thread checkAdbThread = new Thread((object obj) => { Result res = (Result)obj; string output; string errors; // Gets version of installed apk. ShellHelper.RunCommand(adbPath, "shell dumpsys package com.google.ar.core.instantpreview | grep versionName", out output, out errors); string installedVersion = null; if (!string.IsNullOrEmpty(output) && string.IsNullOrEmpty(errors)) { installedVersion = output.Substring(output.IndexOf('=') + 1); } // Early outs if no device is connected. if (string.Compare(errors, k_NoDevicesFoundAdbResult) == 0) { return; } // Prints errors and exits on failure. if (!string.IsNullOrEmpty(errors)) { Debug.LogError(errors); return; } if (installedVersion == null) { Debug.LogFormat( "Instant Preview app not installed on device.", apkPath); } else if (installedVersion != localVersion) { Debug.LogFormat( "Instant Preview installed version \"{0}\" does not match local version " + "\"{1}\".", installedVersion, localVersion); } res.ShouldPromptForInstall = installedVersion != localVersion; }); checkAdbThread.Start(result); while (!checkAdbThread.Join(0)) { yield return(0); } if (result.ShouldPromptForInstall) { if (PromptToInstall()) { Thread installThread = new Thread(() => { string output; string errors; Debug.LogFormat( "Installing Instant Preview app version {0}.", localVersion); ShellHelper.RunCommand(adbPath, "uninstall com.google.ar.core.instantpreview", out output, out errors); ShellHelper.RunCommand(adbPath, string.Format("install \"{0}\"", apkPath), out output, out errors); // Prints any output from trying to install. if (!string.IsNullOrEmpty(output)) { Debug.LogFormat("Instant Preview installation:\n{0}", output); } if (!string.IsNullOrEmpty(errors) && errors != "Success") { Debug.LogErrorFormat( "Failed to install Instant Preview app:\n{0}", errors); } }); installThread.Start(); while (!installThread.Join(0)) { yield return(0); } } else { yield break; } } }
private static IEnumerator UpdateLoop(string adbPath) { var renderEventFunc = NativeApi.GetRenderEventFunc(); var shouldConvertToBgra = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11; var loggedAspectRatioWarning = false; // Waits until the end of the first frame until capturing the screen size, // because it might be incorrect when first querying it. yield return(k_WaitForEndOfFrame); var currentWidth = 0; var currentHeight = 0; var needToStartActivity = true; var prevFrameLandscape = false; RenderTexture screenTexture = null; RenderTexture targetTexture = null; RenderTexture bgrTexture = null; // Begins update loop. The coroutine will cease when the // ARCoreSession component it's called from is destroyed. for (;;) { yield return(k_WaitForEndOfFrame); var curFrameLandscape = Screen.width > Screen.height; if (prevFrameLandscape != curFrameLandscape) { needToStartActivity = true; } prevFrameLandscape = curFrameLandscape; if (needToStartActivity) { string activityName = curFrameLandscape ? "InstantPreviewLandscapeActivity" : "InstantPreviewActivity"; string output; string errors; ShellHelper.RunCommand(adbPath, "shell am start -S -n com.google.ar.core.instantpreview/." + activityName, out output, out errors); needToStartActivity = false; } // Creates a target texture to capture the preview window onto. // Some video encoders prefer the dimensions to be a multiple of 16. var targetWidth = RoundUpToNearestMultipleOf16(Screen.width); var targetHeight = RoundUpToNearestMultipleOf16(Screen.height); if (targetWidth != currentWidth || targetHeight != currentHeight) { screenTexture = new RenderTexture(targetWidth, targetHeight, 0); targetTexture = screenTexture; if (shouldConvertToBgra) { bgrTexture = new RenderTexture( screenTexture.width, screenTexture.height, 0, RenderTextureFormat.BGRA32); targetTexture = bgrTexture; } currentWidth = targetWidth; currentHeight = targetHeight; } NativeApi.Update(); InstantPreviewInput.Update(); if (NativeApi.AppShowedTouchWarning()) { Debug.LogWarning(k_InstantPreviewInputWarning); NativeApi.UnityLoggedTouchWarning(); } AddInstantPreviewTrackedPoseDriverWhenNeeded(); Graphics.Blit(null, screenTexture); if (shouldConvertToBgra) { Graphics.Blit(screenTexture, bgrTexture); } var cameraTexture = Frame.CameraImage.Texture; if (!loggedAspectRatioWarning && cameraTexture != null) { var sourceWidth = cameraTexture.width; var sourceHeight = cameraTexture.height; var sourceAspectRatio = (float)sourceWidth / sourceHeight; var destinationWidth = Screen.width; var destinationHeight = Screen.height; var destinationAspectRatio = (float)destinationWidth / destinationHeight; if (Mathf.Abs(sourceAspectRatio - destinationAspectRatio) > k_MaxTolerableAspectRatioDifference) { Debug.LogWarningFormat( k_MismatchedAspectRatioWarningFormatString, sourceAspectRatio, destinationAspectRatio, sourceWidth, sourceHeight); loggedAspectRatioWarning = true; } } NativeApi.SendFrame(targetTexture.GetNativeTexturePtr()); GL.IssuePluginEvent(renderEventFunc, 1); } }
private static void _RunDirtyQualityJobs(AugmentedImageDatabase database) { if (database == null) { return; } if (s_DatabaseForQualityJobs != database) { // If another database is already running quality evaluation, // stop all pending jobs to prioritise the current database. if (s_DatabaseForQualityJobs != null) { s_QualityBackgroundExecutor.RemoveAllPendingJobs(); } s_DatabaseForQualityJobs = database; } _UpdateDatabaseQuality(database); // Set database dirty to refresh inspector UI for each frame that there are still // pending jobs. // Otherwise if there exists one frame with no newly finished jobs, the UI will never // get refreshed. // EditorUtility.SetDirty can only be called from main thread. if (s_QualityBackgroundExecutor.PendingJobsCount > 0) { EditorUtility.SetDirty(database); return; } List <AugmentedImageDatabaseEntry> dirtyEntries = database.GetDirtyQualityEntries(); if (dirtyEntries.Count == 0) { return; } string cliBinaryPath; if (!AugmentedImageDatabase.FindCliBinaryPath(out cliBinaryPath)) { return; } for (int i = 0; i < dirtyEntries.Count; ++i) { AugmentedImageDatabaseEntry image = dirtyEntries[i]; var imagePath = AssetDatabase.GetAssetPath(image.Texture); var textureGUID = image.TextureGUID; s_QualityBackgroundExecutor.PushJob(() => { string quality; string error; ShellHelper.RunCommand( cliBinaryPath, string.Format("eval-img --input_image_path \"{0}\"", imagePath), out quality, out error); if (!string.IsNullOrEmpty(error)) { Debug.LogError(error); quality = "ERROR"; } lock (s_UpdatedQualityScores) { s_UpdatedQualityScores.Add(textureGUID, quality); } }); } // For refreshing inspector UI as new jobs have been enqueued. EditorUtility.SetDirty(database); }
private void _PreprocessAndroidBuild() { // Get the Jdk path. var jdkPath = UnityEditor.EditorPrefs.GetString("JdkPath"); if (string.IsNullOrEmpty(jdkPath)) { Debug.Log( "Unity 'Preferences > External Tools > Android JDK' path is not set. " + "Falling back to JAVA_HOME environment variable."); jdkPath = System.Environment.GetEnvironmentVariable("JAVA_HOME"); } if (string.IsNullOrEmpty(jdkPath)) { throw new BuildFailedException( "A JDK path needs to be specified for the Android build."); } bool cloudAnchorsEnabled = !string.IsNullOrEmpty(ARCoreProjectSettings.Instance.CloudServicesApiKey); var cachedCurrentDirectory = Directory.GetCurrentDirectory(); var pluginsFolderPath = Path.Combine(cachedCurrentDirectory, AssetDatabase.GUIDToAssetPath(k_PluginsFolderGuid)); string cloudAnchorsManifestAarPath = Path.Combine(pluginsFolderPath, "cloud_anchor_manifest.aar"); var jarPath = Path.Combine(jdkPath, "bin/jar"); if (cloudAnchorsEnabled) { // If the Api Key didn't change then do nothing. if (!_IsApiKeyDirty(jarPath, cloudAnchorsManifestAarPath, ARCoreProjectSettings.Instance.CloudServicesApiKey)) { return; } // Replace the project's cloud anchor AAR with the newly generated AAR. Debug.Log("Enabling Cloud Anchors in this build."); var tempDirectoryPath = Path.Combine(cachedCurrentDirectory, FileUtil.GetUniqueTempPathInProject()); try { // Move to a temp directory. Directory.CreateDirectory(tempDirectoryPath); Directory.SetCurrentDirectory(tempDirectoryPath); var manifestTemplatePath = Path.Combine( cachedCurrentDirectory, AssetDatabase.GUIDToAssetPath(k_ManifestTemplateGuid)); // Extract the "template AAR" and remove it. string output; string errors; ShellHelper.RunCommand( jarPath, string.Format("xf \"{0}\"", manifestTemplatePath), out output, out errors); // Replace Api key template parameter in manifest file. var manifestPath = Path.Combine(tempDirectoryPath, "AndroidManifest.xml"); var manifestText = File.ReadAllText(manifestPath); manifestText = manifestText.Replace( "{{CLOUD_ANCHOR_API_KEY}}", ARCoreProjectSettings.Instance.CloudServicesApiKey); File.WriteAllText(manifestPath, manifestText); // Compress the new AAR. var fileListBuilder = new StringBuilder(); foreach (var filePath in Directory.GetFiles(tempDirectoryPath)) { fileListBuilder.AppendFormat(" {0}", Path.GetFileName(filePath)); } string command = string.Format( "cf cloud_anchor_manifest.aar {0}", fileListBuilder.ToString()); ShellHelper.RunCommand( jarPath, command, out output, out errors); if (!string.IsNullOrEmpty(errors)) { throw new BuildFailedException( string.Format( "Error creating jar for cloud anchor manifest: {0}", errors)); } File.Copy(Path.Combine(tempDirectoryPath, "cloud_anchor_manifest.aar"), cloudAnchorsManifestAarPath, true); } finally { // Cleanup. Directory.SetCurrentDirectory(cachedCurrentDirectory); Directory.Delete(tempDirectoryPath, true); AssetDatabase.Refresh(); } AssetHelper.GetPluginImporterByName("cloud_anchor_manifest.aar") .SetCompatibleWithPlatform(BuildTarget.Android, true); } else { Debug.Log( "Cloud Anchor API key has not been set. Cloud Anchors will be disabled in " + "this build."); File.Delete(cloudAnchorsManifestAarPath); AssetDatabase.Refresh(); } }
private static void CaptureBugReport() { string desktopPath = Environment.GetFolderPath( Environment.SpecialFolder.Desktop); DateTime timeStamp = DateTime.Now; string fileNameTimestamp = timeStamp.ToString("yyyyMMdd_hhmmss"); string filePath = Path.Combine( desktopPath, k_FileNamePrefix + fileNameTimestamp + ".txt"); StreamWriter writer; // Operating system and hardware info have to be handled separately based on OS switch (SystemInfo.operatingSystemFamily) { case OperatingSystemFamily.MacOSX: writer = File.CreateText(filePath); writer.WriteLine("*** GOOGLE ARCORE SDK FOR UNITY OSX BUG REPORT ***"); writer.WriteLine("Timestamp: " + timeStamp.ToString()); writer.WriteLine(); writer.WriteLine("*** OPERATING SYSTEM INFORMATION ***"); WriteCommand("system_profiler", "SPSoftwareDataType", writer); writer.WriteLine("*** GRAPHICS INFORMATION ***"); WriteCommand("system_profiler", "SPDisplaysDataType", writer); WriteOsIndependentFields(writer); string stdOut; string stdErr; // Get PATH directories to search for adb in. ShellHelper.RunCommand( "/bin/bash", "-c -l \"echo $PATH\"", out stdOut, out stdErr); stdOut.Trim(); writer.WriteLine("*** ADB VERSIONS ON PATH ***"); WriteAdbPathVersions(stdOut.Split(':'), writer); writer.WriteLine("*** TYPE -A ADB ***"); WriteCommand("/bin/bash", "-c -l \"type -a adb\"", writer); writer.WriteLine("*** RUNNING ADB PROCESSES ***"); WriteCommand( "/bin/bash", "-c -l \"ps -ef | grep -i adb | grep -v grep\"", writer); writer.WriteLine("*** RUNNING UNITY PROCESSES ***"); WriteCommand( "/bin/bash", "-c -l \"ps -ef | grep -i Unity | grep -v grep\"", writer); writer.Close(); Debug.Log( "ARCore bug report captured. File can be found here:\n" + Path.GetFullPath(filePath)); break; case OperatingSystemFamily.Windows: writer = File.CreateText(filePath); writer.WriteLine("*** GOOGLE ARCORE SDK FOR UNITY WINDOWS BUG REPORT ***"); writer.WriteLine("Timestamp: " + timeStamp.ToString()); writer.WriteLine("*** OPERATING SYSTEM INFORMATION ***"); WriteCommand("cmd.exe", "/C systeminfo", writer); writer.WriteLine("*** GRAPHICS INFORMATION ***"); WriteCommand( "cmd.exe", "/C wmic path win32_VideoController get /format:list", writer); WriteOsIndependentFields(writer); string pathStr = Environment.GetEnvironmentVariable("PATH").Trim(); writer.WriteLine("*** ADB VERSIONS ON PATH ***"); WriteAdbPathVersions(pathStr.Split(';'), writer); writer.WriteLine("*** RUNNING ADB PROCESSES ***"); WriteCommand("cmd.exe", "/C TASKLIST | c:\\Windows\\System32\\findstr.exe \"adb\"", writer); writer.WriteLine("*** RUNNING UNITY PROCESSES ***"); WriteCommand("cmd.exe", "/C TASKLIST | c:\\Windows\\System32\\findstr.exe \"Unity\"", writer); writer.Close(); Debug.Log( "ARCore bug report captured. File can be found here:\n" + Path.GetFullPath(filePath)); break; default: string dialogMessage = "ARCore does not support capturing bug reports for " + SystemInfo.operatingSystemFamily + " at this time."; EditorUtility.DisplayDialog("ARCore Bug Report", dialogMessage, "OK"); break; } }