diff --git a/.gradle/2.4/taskArtifacts/cache.properties.lock b/.gradle/2.4/taskArtifacts/cache.properties.lock index 298d1399..f4f73720 100644 Binary files a/.gradle/2.4/taskArtifacts/cache.properties.lock and b/.gradle/2.4/taskArtifacts/cache.properties.lock differ diff --git a/.gradle/2.4/taskArtifacts/fileHashes.bin b/.gradle/2.4/taskArtifacts/fileHashes.bin index e15f4912..45309110 100644 Binary files a/.gradle/2.4/taskArtifacts/fileHashes.bin and b/.gradle/2.4/taskArtifacts/fileHashes.bin differ diff --git a/.gradle/2.4/taskArtifacts/fileSnapshots.bin b/.gradle/2.4/taskArtifacts/fileSnapshots.bin index 466073b4..647e4984 100644 Binary files a/.gradle/2.4/taskArtifacts/fileSnapshots.bin and b/.gradle/2.4/taskArtifacts/fileSnapshots.bin differ diff --git a/.gradle/2.4/taskArtifacts/outputFileStates.bin b/.gradle/2.4/taskArtifacts/outputFileStates.bin index f6bcf7b0..8f0f7611 100644 Binary files a/.gradle/2.4/taskArtifacts/outputFileStates.bin and b/.gradle/2.4/taskArtifacts/outputFileStates.bin differ diff --git a/.gradle/2.4/taskArtifacts/taskArtifacts.bin b/.gradle/2.4/taskArtifacts/taskArtifacts.bin index ffa46b77..14e4ab64 100644 Binary files a/.gradle/2.4/taskArtifacts/taskArtifacts.bin and b/.gradle/2.4/taskArtifacts/taskArtifacts.bin differ diff --git a/.idea/misc.xml b/.idea/misc.xml index 5d199810..fbb68289 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 84c2961e..6386a569 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,7 +20,8 @@ + android:theme="@style/AppTheme.NoActionBar" + android:noHistory="true"> @@ -61,8 +62,15 @@ + android:noHistory="true" + android:label="Sugilite Script Recording" > + + + + + + diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/MainActivity.java b/app/src/main/java/edu/cmu/hcii/sugilite/MainActivity.java index 50dbb41d..65a34431 100644 --- a/app/src/main/java/edu/cmu/hcii/sugilite/MainActivity.java +++ b/app/src/main/java/edu/cmu/hcii/sugilite/MainActivity.java @@ -44,6 +44,7 @@ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { + Intent intent = getIntent(); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/RecordingPopUpDialog.java b/app/src/main/java/edu/cmu/hcii/sugilite/RecordingPopUpDialog.java new file mode 100644 index 00000000..e04df758 --- /dev/null +++ b/app/src/main/java/edu/cmu/hcii/sugilite/RecordingPopUpDialog.java @@ -0,0 +1,9 @@ +package edu.cmu.hcii.sugilite; + +/** + * @author toby + * @date 7/22/16 + * @time 12:18 PM + */ +public class RecordingPopUpDialog { +} diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/SugiliteAccessibilityService.java b/app/src/main/java/edu/cmu/hcii/sugilite/SugiliteAccessibilityService.java index 33c7c8e3..0dfa7807 100644 --- a/app/src/main/java/edu/cmu/hcii/sugilite/SugiliteAccessibilityService.java +++ b/app/src/main/java/edu/cmu/hcii/sugilite/SugiliteAccessibilityService.java @@ -222,6 +222,8 @@ private Intent generatePopUpActivityIntentFromEvent(AccessibilityEvent event, Ac //pop up the selection window Intent popUpIntent = new Intent(this, mRecordingPopUpActivity.class); popUpIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + popUpIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + popUpIntent.putExtra("packageName", sourceNode.getPackageName()); popUpIntent.putExtra("className", sourceNode.getClassName()); popUpIntent.putExtra("text", sourceNode.getText()); diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationActicvity.java b/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationActicvity.java new file mode 100644 index 00000000..5cbcc197 --- /dev/null +++ b/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationActicvity.java @@ -0,0 +1,224 @@ +package edu.cmu.hcii.sugilite.communication; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.WindowManager; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.Gson; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import edu.cmu.hcii.sugilite.R; +import edu.cmu.hcii.sugilite.SugiliteData; +import edu.cmu.hcii.sugilite.automation.ServiceStatusManager; +import edu.cmu.hcii.sugilite.dao.SugiliteScriptDao; +import edu.cmu.hcii.sugilite.model.block.SugiliteStartingBlock; +import edu.cmu.hcii.sugilite.ui.VariableSetValueDialog; + +public class SugiliteCommunicationActicvity extends AppCompatActivity { + TextView messageType, scriptName; + SugiliteScriptDao sugiliteScriptDao; + SugiliteBlockJSONProcessor jsonProcessor; + SugiliteData sugiliteData; + SharedPreferences sharedPreferences; + Context context; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sugilite_communication_acticvity); + messageType = (TextView)findViewById(R.id.receive_message_textview); + scriptName = (TextView)findViewById(R.id.receive_message_script_name); + messageType.setText("TEST MESSAGE TYPE"); + String arg1 = "", arg2 = ""; + if (getIntent().getExtras() != null) + { + arg1 = getIntent().getStringExtra("messageType"); + messageType.setText(arg1); + /* + START_RECORDING, scriptName + END_RECORDING, "NULL" + RUN_SCRIPT, scriptName + GET_SCRIPT, scriptName + GET_SCRIPT_LIST, "NULL + */ + + arg2 = getIntent().getStringExtra("scriptName"); + scriptName.setText(arg2); + + } + this.sugiliteScriptDao = new SugiliteScriptDao(this); + this.jsonProcessor = new SugiliteBlockJSONProcessor(this); + this.sugiliteData = (SugiliteData)getApplication(); + this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + this.context = this; + handleRequest(arg1, arg2); + + } + + private void handleRequest(String messageType, final String scriptName){ + boolean recordingInProcess = sharedPreferences.getBoolean("recording_in_process", false); + switch (messageType){ + case "START_RECORDING": + if(recordingInProcess) { + //the exception message below will be sent when there's already recording in process + //TODO: send exception message + } + else { + //NOTE: script name should be specified in msg.getData().getString("request"); + if (scriptName != null) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("New Recording") + .setMessage("Now start recording new script " + scriptName) + .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + sugiliteData.clearInstructionQueue(); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("scriptName", scriptName); + editor.putBoolean("recording_in_process", true); + editor.commit(); + + sugiliteData.initiateScript(scriptName + ".SugiliteScript"); + sugiliteData.initiatedExternally = true; + + try { + sugiliteScriptDao.save(sugiliteData.getScriptHead()); + } catch (Exception e) { + e.printStackTrace(); + } + + Toast.makeText(getApplicationContext(), "Recording new script " + sharedPreferences.getString("scriptName", "NULL"), Toast.LENGTH_SHORT).show(); + + //go to home screen for recording + Intent startMain = new Intent(Intent.ACTION_MAIN); + startMain.addCategory(Intent.CATEGORY_HOME); + startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(startMain); + } + }); + AlertDialog dialog = builder.create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + } + break; + case "END_RECORDING": + if(recordingInProcess) { + + SharedPreferences.Editor prefEditor = sharedPreferences.edit(); + prefEditor.putBoolean("recording_in_process", false); + prefEditor.commit(); + if(sugiliteData.initiatedExternally == true && sugiliteData.getScriptHead() != null) + sendRecordingFinishedSignal(sugiliteData.getScriptHead().getScriptName()); + + Toast.makeText(context, "end recording", Toast.LENGTH_SHORT).show(); + } + else { + //the exception message below will be sent when there's no recording in process + //TODO: send exception message + } + break; + case "RUN_SCRIPT": + if(recordingInProcess) { + //TODO: send exception message + } + else { + SugiliteStartingBlock script = sugiliteScriptDao.read(scriptName + ".SugiliteScript"); + if(script == null) + //TODO: send exception message + sugiliteData.clearInstructionQueue(); + final ServiceStatusManager serviceStatusManager = new ServiceStatusManager(context); + + if(!serviceStatusManager.isRunning()){ + //prompt the user if the accessiblity service is not active + AlertDialog.Builder builder1 = new AlertDialog.Builder(context); + builder1.setTitle("Service not running") + .setMessage("The Sugilite accessiblity service is not enabled. Please enable the service in the phone settings before recording.") + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + serviceStatusManager.promptEnabling(); + //do nothing + } + }); + AlertDialog dialog = builder1.create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + else { + sugiliteData.stringVariableMap.putAll(script.variableNameDefaultValueMap); + + //kill all the relevant packages + for (String packageName : script.relevantPackages) { + try { + Process sh = Runtime.getRuntime().exec("su", null, null); + OutputStream os = sh.getOutputStream(); + os.write(("am force-stop " + packageName).getBytes("ASCII")); + os.flush(); + os.close(); + System.out.println(packageName); + } catch (Exception e) { + e.printStackTrace(); + // do nothing, likely this exception is caused by non-rooted device + } + } + sugiliteData.runScript(script); + try { + Thread.sleep(VariableSetValueDialog.SCRIPT_DELAY); + } catch (Exception e) { + // do nothing + } + //go to home screen for running the automation + Intent startMain = new Intent(Intent.ACTION_MAIN); + startMain.addCategory(Intent.CATEGORY_HOME); + startMain.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + context.startActivity(startMain); + } + } + break; + case "GET_SCRIPT": + SugiliteStartingBlock script = sugiliteScriptDao.read(scriptName + ".SugiliteScript"); + if(script != null) + sendReturnValue(jsonProcessor.scriptToJson(script)); + else + //the exception message below will be sent when can't find a script with provided name + //TODO: send exception message + break; + case "GET_SCRIPT_LIST": + List allNames = sugiliteScriptDao.getAllNames(); + List retVal = new ArrayList<>(); + for(String name : allNames) + retVal.add(name.replace(".SugiliteScript", "")); + sendReturnValue(new Gson().toJson(retVal)); + break; + } + } + + public boolean sendRecordingFinishedSignal(String scriptName){ + return true; + } + + private void sendReturnValue(String retVal){ + Intent returnIntent = new Intent(); + returnIntent.putExtra("result", retVal); + setResult(Activity.RESULT_OK,returnIntent); + finish(); + } +} diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationController.java b/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationController.java index 26c68773..97d9abf3 100644 --- a/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationController.java +++ b/app/src/main/java/edu/cmu/hcii/sugilite/communication/SugiliteCommunicationController.java @@ -300,6 +300,7 @@ public void onClick(DialogInterface dialog, int which) { context.startActivity(startMain); } } + break; default: Log.e( TAG, "Message not supported!"); diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/communication/json/SugiliteScriptJSON.java b/app/src/main/java/edu/cmu/hcii/sugilite/communication/json/SugiliteScriptJSON.java index bdd771b1..474983ca 100644 --- a/app/src/main/java/edu/cmu/hcii/sugilite/communication/json/SugiliteScriptJSON.java +++ b/app/src/main/java/edu/cmu/hcii/sugilite/communication/json/SugiliteScriptJSON.java @@ -2,6 +2,7 @@ import android.content.Context; +import java.util.HashMap; import java.util.Map; import edu.cmu.hcii.sugilite.model.block.SugiliteOperationBlock; @@ -16,9 +17,10 @@ public class SugiliteScriptJSON { public SugiliteScriptJSON(SugiliteStartingBlock startingBlock){ this.scriptName = new String(startingBlock.getScriptName()); this.scriptName.replace(".SugiliteScript", ""); + variables = new HashMap<>(); for(Map.Entry entry : startingBlock.variableNameDefaultValueMap.entrySet()){ if(entry.getValue() instanceof StringVariable) - variables.put(entry.getKey(), ((StringVariable) entry.getValue()).getValue()); + this.variables.put(entry.getKey(), ((StringVariable) entry.getValue()).getValue()); } if(startingBlock.getNextBlock() != null && startingBlock.getNextBlock() instanceof SugiliteOperationBlock) nextBlock = new SugiliteOperationBlockJSON((SugiliteOperationBlock)startingBlock.getNextBlock()); diff --git a/app/src/main/java/edu/cmu/hcii/sugilite/mRecordingPopUpActivity.java b/app/src/main/java/edu/cmu/hcii/sugilite/mRecordingPopUpActivity.java index 47502fab..233dba11 100644 --- a/app/src/main/java/edu/cmu/hcii/sugilite/mRecordingPopUpActivity.java +++ b/app/src/main/java/edu/cmu/hcii/sugilite/mRecordingPopUpActivity.java @@ -238,7 +238,7 @@ private void setupSelections(){ SimpleDateFormat dateFormat; dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("US/Eastern")); - boolean autoFillEnabled = sharedPreferences.getBoolean("auto_fill_enabled", false); + boolean autoFillEnabled = sharedPreferences.getBoolean("auto_fill_enabled", true); LinearLayout identifierLayout = (LinearLayout) findViewById(R.id.identifier_layout); CompoundButton.OnCheckedChangeListener identiferCheckboxChangeListener = new CompoundButton.OnCheckedChangeListener() { diff --git a/app/src/main/res/layout/activity_sugilite_communication_acticvity.xml b/app/src/main/res/layout/activity_sugilite_communication_acticvity.xml new file mode 100644 index 00000000..da489103 --- /dev/null +++ b/app/src/main/res/layout/activity_sugilite_communication_acticvity.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 47ca4d3f..f0b626ff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,5 +63,6 @@ Silent Vibrate + CommunicationInterfaceActivity