Methods - mindaptiv/Saul GitHub Wiki
#com.mindaptiv.saul ##Cylon.java ###Constructor Standard constructors for creating new instances of the appropriate classes.
- public Cylon(Context context)
- This constructor initializes a new Cylon object, grabbing the context (assumed to be supplied by the main Activity class of the current Android app) in the argument field, and then calling all of the Producer functions to populate the rest of its data members to the best of its ability. The constructor also makes requests for specific permissions (contacts, camera, storage, etc.) in place of calling certain producer methods. The data associated with these permission-locked methods stays unfilled until the asynchronous permission requests return based on user interaction. A boolean flag system is used for keeping track of the status of the various producer methods/permission requests to determine what has/hasn't been replied to yet by the user.
###Permissions Permission methods are associated with handling input from users regarding granting the app permission or denying permission to access specific runtime permissions.
-
void makeReqeuest(final String manifestPermission, final int cylonRequestCode)
-
This method checks if a given permission is denied. In cases where it is denied, it displays a popup window giving the user the option to accept or decline. If the permission is already granted, the producer methods that need the specified permission are executed and the flag for the permission request being answered is set to true.
-
public boolean onRequestPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
-
This method checks the requestCode against the possible values defined as constants in Cylon.java that are associated with a request. If a match is found, the flag for that specific request is set to true and if the permission is granted, the associated producer methods are run.
###Producers These functions make calls to Java and Android API's to get relevant user, OS, and hardware information. After retrieving this information, these functions format, and store the data in the calling Cylon object.
-
public void produceBluetoothDevices()
-
This producer creates a new BluetoothAdapter object via the class' getDefaultAdapter() method. If no adapter is found, the function returns immediately. Otherwise, a new Device object is created for the Bluetooth radio, and stored in the calling Cylon's detectedDevices LinkedList. If the radio is disabled, the function will also return immediately. Otherwise, a Set of type BluetoothDevice is populated using the adapter's getBondedDevices() method.
-
public void produceCameras()
-
This producer runs differently depending on the version of Android present on the device. For older devices (pre-Lollipop), the original Camera class is used. An integer value is retrieved for the amount of camera's present on the device, and then a new CameraInfo object is populated for information about each camera based on the original integer. A new Device object is then created based on this information and stored in the calling Cylon's detectedDevices LinkedList.
For devices running Lollipop (or newer), the Cylon's context field is used to retrieve the system's CameraManager service. The manager populates a String array of camera ID's, and for each value in this array, a new CameraCharacteristics is retrieved and used to create a new Device object, which is finally stored in the calling Cylon's detectedDevices LinkedList. If a CameraAccessException occurs for this version of the method, the function returns immediately. -
public void produceDateTime()
-
This function creates a new java.util.Date object, java.util.GregorianCalendar object, and java.util.TimeZone object. The Cylon's dst value is set based on the time zone's inDaylightTime() result. The minutes-based timeZone value of the Cylon is calcualted by dividing the zone's getRawOffset() by 60,000, while the string-based timeZone value is retrieved using the TimeZOne getDisplayName() call. The day, date, month, year, milliseconds, seconds, minutes and years values are pulled from the calendar object and then error checked before being stored.
-
public void produceDevices()
-
A wrapper function for calling all other device related producers. The calling Cylon's LinkedLists's for Device, Controllers, and Displays are all initialized at the start, and its detectedDeviceCount is set to the size of the detectedDevices list at the end of the function. Due to key functionality not being present until Android API 17, produceDisplayDevices() is not called unless if the current OS is detected to be running API 17+.
-
public void produceDeviceName()
-
This function sets the calling Cylon's deviceName field to the retrieved value from Android's android.os.Build.MODEL variable.
-
public void produceDisplayDevices()
-
Note: This code should only be run when on API level 17+ (Jelly Bean MR1). If the calling operating system passes this call, a new DisplayManager object is created via the Cylon's context field (using Context.getSystemService(Context.DISPLAY_SERVICE)). This manager then calls getDisplays() to populate an array of android.view.Display objects (this array is referred to as displaysies). A for loop is then run over the length of displaysies. Within this loop, a new Context object is created for each android.view.Display object. For each Display object, a new Device and com.mindaptiv.saul.Display is also created, and added into the calling Cylon's list of detected devices and detected displays list, with the displayIndex of the Device object set to that Display's location in the displays list to help map between the two objects representing the same monitor.
-
public void produceGPS()
-
This producer utilizes the Cylon's context field to retrieve a new LocationManager object from the current system. An ArrayList of type String is then populated with all of the location providers available to the LocationManager object. If the list contains a provider equal to the LocationManager's value for its GPS_PROVIDER field, a boolean is set based on if that provider is enabled, then a new Device object is created for the GPS functionality of the Device, and stored in the detectedDevices LinkedList of the calling Cylon.
-
public void produceInputDevices()
-
The InputDevice method getDeviceIds() is first called to retrieve an array of ids for all available/attached InputDevices to the current system. A second array, of type InputDevice, is then created based on the count of returned id's. A for loop is then run over the count of returned id's, initializing the InputDevice at each index of the array for each id found, as well as creating a new saul.mindaptiv.com.Device object is also created based on the new InputDevice object and added to the Cylon's list of Devices. If that Device object's type is determined to be 11 (the value associated with being a controller/gamepad), a new Controller is created based on the Device and InputDevice objects for that gamepad, and the Controller is inserted into the Cylon's controllers list (while the corresponding Device object's controllerIndex field is updated to match the index of the Controller object in the controllers list, to help map between the two lists for the two objects representing the same gamepad).
-
public void produceMemoryInfo()
-
The word size (osArchitecture) value of the Cylon is set to 0 by default and is later set in Saul.cpp. Using the system Context passed to the Cylon, an ActivityManager instance is created, which populates a new MemoryInfo object with specs on the system's memory. The producer then saves the total memory/available memory/low memory threshold values in bytes, as well as a true/false value for if the memory is running low at that point in execution.
-
public void produceAvatar()
-
This producer creates a cursor object just like the username producer, but querying a Uri with the withAppendedPath() method, skimming through various Data and CommonDataKinds constants. The Cursor then loops through all of its positions, if a position matches the mime_type value, if the getString() method for the PHOTO constant is not null, the string is copied into the picturePath field, otherwise the picturePath field is set to a default value. Finally, the cursor is closed before the method returns.
-
public void producePrintingDevices()
-
Currently unused/commented out. A preliminary function for creating a discovery session for printers is in place but has not passed testing/fails. Requires further development/testing.
-
public void produceProcessorInfo()
-
This function sets the Cylon's architecture value to the result of System.getProperty("os.arch"), with a default value of "0" if nothing is located. Variables that were present in the original cylonStruct that could not be retrieved in the Java/Android API's are set to 0 as a default/placeholder. To retrieve the hertz of the CPU, a RandomAccessFile is created that reads from the file handler for "cpuinfo_max_freq". When reading is completed, teh file is closed, and the value is converted from Kilohertz to Hertz (with a default value of 0.0f if any exceptions are thrown). An inner-class, CpuFilter (based on FileFilter interface), is used to inspect the files found in the directory "sys/devices/system/cpu/", with the filter applied, the code counts how many resulting files are available and uses this count to set the number of cores/processorCount for the calling Cylon. If an exception occurs, the value defaults to 1.
-
public void produceSensors()
-
This producer utilizes the Cylon's context field to retrieve a new SensorManager object from the current system. The manager then populates a List of type android.hardware.Sensor objects with all of the sensors available at run-time. The list is then iterated over, each sensor is checked if it is the default for its given type on the device, and then both the sensor and the confirmation of default/not default are used to create new Device and new com.mindaptiv.saul.Sensor objects. The two objects are then stored in their respective LinkedLists for the calling Cylon, and are mapped to each other via the Device object's sensorsIndex field.
-
pubic void produceStorageDevices()
-
This function probes the availability of paths with various system environment variables traditionally tied to storage for Android devices. If nothing is found for Emulated AND External storage, the standard sdcard0 path is stored in a HashSet keeping track of available storage drive paths. If nothing is found for Emulated BUT something is present for External storage, the value of the System variable "EXTERNAL_STORAGE" is stored in the HashSet.
If Emulated storage IS detected, the raw user ID is set depending on the platform, an empty string for devices running on Jellybean or earlier. The raw user ID is set to either the value of the last folder found in the absolute path of the external storage directory OR an empty String if the last folder's name is found to not be a digit. TextUtils is then used to probe the existence of directories at the user ID, if nothing is found, the System's value for "EMULATED_STORAGE_TARGET" is added to the HashSet. Otherwise, the value of "EMULATED_STORAGE_TARGET" is concatenated with a directory separator and the user ID.
For secondary storage, if a drive is detected, all available secondary paths are collected and added to the HashSet.
The HashSet is then converted into a String Array, and a loop is run on the contents of the Array. For each String, a new StatFs (file system) object is created, and then inspected to detect if the path is the default storage drive and if the path is for emulated storage. Additional data retrieved for the path includes the total and available storage sizes for the storage space in bytes. Finally, a new Device object and a new Storage object are created, mapped to each other via the Device's storageIndex field, and stored in their respective LinkedLists of the Cylon. -
public void produceSystemRumble()
-
This producer utilizes the Cylon's context field to retrieve a new Vibrator object from the current system. If the object's hasVibrator() method equates to true, a new Device object is created for the rumbler and stored in the Cylon's detectedDevices LinkedList.
-
public void produceUsbDevices()
-
This producer utilizes the Cylon's context field to retrieve a UsbManager object. The UsbManager then populates a HashMap of type String, UsbDevice containing all of the available USB devices. The producer then traverses through the HashMap and tries to retrieve the size of any volumes attached via USB, and converts the appropriate data to Storage and Device objects. If the UsbDevice has no size, then the function skips to the next entry in the Map.
-
private void produceUsername()
-
This producer uses the Cylon's Application member variable to retrieve a ContentResolver object, and then queries the ContactsContract.Profile object of the device for its CONTENT_URI field, storing this data in a Cursor object. If the Cursor's count value is positive, the Cursor is moved to the first value and the username is retrieved from the appropriate column using the DISPLAY_NAME_PRIMARY key. The value is then copied into the Cylon's username field. If the Cursor's count is not a positive integer, the Cylon's username is given a default value of "0". At the end of the call, the Cursor object is closed just before returning.
-
private void produceMidiInfo()
-
This producer first checks to make sure the device is running at least Android M. If the logic checks out, a check is run to determine if the device supports Midi, and when true a MidiManager is created. All available Midi devices are then pulled into an array and listeners are set for when a Midi device attaches/detaches from the host device. A for loop is then run over the size of the array, with no actions taken (pending testing results).
###Handlers
-
public boolean handleKeyEvent(KeyEvent event)
-
This function should be called by the dispatchKeyEvent() method of the main activity class of any app that uses the Saul package. The function is used for detecting the current state of a given gamepad. The event's device ID is compared to the device ID of all controllers found in the Cylon's list of available gamepads. If a button is being pressed (ACTION_DOWN/ACTION_MULTIPLE), the corresponding bit to that button is set to 1, and the bit is reset to 0 if the button is being released (ACTION_UP) after previously being detected to be pressed. After executing all of the if logic, the function returns true to the calling Activity class. If no matching controller was found, the function returns false.
-
public boolean handleMotionEvent(KeyEvent event)
-
This function should be called by the onGenericMotionEvent() method of the main activity class of any app that uses the Saul package. The function is used for detecting the current state of a gamepad's joysticks and triggers. If one of these input mechanisms is moved, the value for the controller's appropriate thumbstick or trigger field will be set. If no matching controller was found, the function returns false.
###Logging
-
public void testLog()
-
This function is used primarily for debugging the project via LogCat in eclipse, etc. Using the android.util.Log class, the function logs the values for all the fields of the Cylon, including all of its various detected device objects.
-
public void produceSystemRumble()
-
This testing function causes the device to vibrate according to the number of storage drives it has access to (currently between 1 and 3) as a quick way to get feedback on if your new storage drive is being recognized by Saul.
###Updating
- public void updateSaul()
- This function updates the memory and time fields of the Cylon calling it, and checks to see if all of the permissions requests have been answered. If all requests have been answered and the Cylon has not already logged its contents, it produces a log using testLog() and raises the logged flag to true before returning.
###File Filter
- public boolean accept(File pathname)
- This function belongs to the inner-class of produceProcessorInfo(), CpuFilter (which implements the FileFilter interface). This method checks if the path to the file matches the pattern "cpu[0-9]+", and returns true if yes, and false otherwise.
##Device.java ###Constructor
-
public Device(InputDevice idvice)
-
This constructor builds a new Device based on a provided InputDevice. The controller/display index values are both set to 0, but may be changed later in a producer function call from a Cylon object. The device's name field is grabbed from idvice's getName() method, while the id field is grabbed from the getId() function. If the current system is on KitKat or later, the vendorID is retrieved using getVendorId() from the idvice object, otherwise the value is set to 0. Several "boolean" integer values that are held over from other Final Five platforms are initialized to 0 (with the exception of isEnabled, which is set to 1). The idvice object's returning value for getSources() is then inspected using bit-wise operations and if-logic to determine the nature of the device to set its deviceType field based on the capabilities retrieved in the sources mask.
-
public Device(android.view.Display display)
-
This constructor builds a new Device object using an android.view.Display object. The device's displayIndex is again set to 0, but may be changed later at run-time to map to an appropriate index in a Cylon's displays list. More unavailable fields are set to 0 (with isEnabled again set to 1). The device's name is set to the display's getName() value, and the id the set to the display's getDisplayId() value. Since this constructor is specifically based on Display objects, the deviceType is defaulted to 8 (the value mapped to display for the Device class). If the id value is found to be equal to the value of android.view.Display.DEFAULT_DISPLAY, the isDefault "boolean" is set to 1, otherwise, it is defaulted to 0.
-
public Device(String path, boolean isDefault)
-
This constructor builds a new Device object using a path to a storage location and a boolean value denoting the path is the default storage location for the system. The device's storageIndex field is set to 0, but may change later in run-time to map to an appropriate index in the Cylon's storages list. More unavailable fields are set to default values unavailable in this context (storage devices). The deviceType is hard coded to 17, the Final Five mapping for storage devices. Finally the isDefault value is set depending on the value of the boolean argument passed into the constructor.
-
public Device()
-
This constructor builds a new Device object for the system rumble/vibrate motor. The name is hard coded to "System Rumble Service" and the deviceType is hard coded to 18, the Final Five mapping for rumble devices. All other fields are set to default values.
-
public Device(boolean enabled)
-
This constructor builds a new Device object using a boolean denoting if the system's GPS provider service is enabled. The deviceType is hard coded to 7, the Final Five mapping for location aware devices. The name field is hard coded to "System GPS Service", and the isEnabled field is set depending on the value of the boolean passed into the constructor. All other fields are set to default values.
-
public Device(android.hardware.Sensor sensor, Integer defaulty)
-
This constructor builds a new Device object using an Android Sensor and Integer value for the sensor's status as the default for its given type on the current system. The sensorsIndex field is zeroed out, but may change later in run-time to map to a Sensor in the calling Cylon's sensors' LinkedList. The deviceType field is hard coded to 19, the Final Five mapping for sensor device. The name field is retrieved via the Android Sensor's getName() method, and the isDefault value is set to the defaulty field's value. All other fields are set to default values.
-
public Device(int id, CameraInfo info)
-
This constructor builds a new Device object using an int and CameraInfo object. The deviceType is hard coded to 5, the Final Five value for video capture device. The panelLocation value is set based on the value of the info argument's facing field, and the orientation field is copied from the same field of the info object. The name field is set to the value "Camera " concatenated with the passed in id argument, which is also used for the id field of the Device. All other fields are set to default values.
-
public Device(int id, CameraCharacteristics info, String name)
-
This constructor builds a new Device using an int, String and CameraCharacteristics (for Lollipop and later devices). The deviceType field is hard coded to 5, the Final Five mapping for video capture. If the device is running Lollipop or newer, the panelLocation field is set based on the LENS_FACING field of the info argument, and the orientation is set based on the SENSOR_ORIENTATION field of the info argument. The name is hard coded to "Camera " concatenated with the name argument, and the id field is copied from the id argument. All other fields are set to default values.
-
public Device(BluetoothAdapter adapter)
-
This constructor builds a new Device using the BluetoothAdapter class. Since the way we retrieve the adapter is via the getDefaultAdapter() method in Cylon.java, the isDefault field is set to 1. The value of isEnabled is set based on the value of the adapter's isEnabled() method. The name field is copied from the adapter's getName() method, while the id field is copied from the adapter's getAddress() method. The deviceType is hard coded to 20, the Final Five mapping for Bluetooth Radio. All other fields are set to default values.
-
public Device(FingerprintManager manager)
-
This constructor builds a new Device using the FingerprintManager class. All fields are set to default values, with deviceType being set to SENSOR_TYPE, name being set to "Fingerprint Manager", and the id_int being set to the hashcode of the manager argument.
-
public Device(MidiDeviceInfo info)
-
This constructor builds a new Device using the MidiDeviceInfo class. All fields are set to default values with some exceptions. The deviceType is set to 30, for MIDI_TYPE, after a version check to verify that the code is being run in Android M or later, the id is set based on the ID of the info argument. If run on an earlier version of Android id, vendorID and name default to regular values. Other functionality for this constructor is pending test results with actual devices.
##Controller.java ###Constructor
- public Controller(Device superDevice, InptuDevice idevice)
- This constructor initializes a new Controller object. The superDevice field is set from the superDevice argument passed in. The buttons and packetNumber fields are both initialized to 0, while the userIndex (if the current operating system is detected to be KitKat/API 19 or later) is set using the idvice objec'ts getControllerNumber() method. Otherwise, the userIndex is defaulted to 0.
##Display.java ###Constructor
- public Display(android.view.Display source, Context displayContext, Device device)
- This constructor builds a display object based on a Device, android Display, and the Context of said android Display. The superDevice field is set to the corresponding device argument. Since stereoscopic 3D is not a widespread Android API value yet, the value is currently defaulted to 0 for the isStereoscopicEnabled field. A new Configuration object is then created using the displayContext's getResources().getConfiguration() call, and a new int is created calling the source argument's getRotation() method. The value of rotation and configuration are then compared to determine and set the nativeRotation, currentRotation, and rotationPreference of the new Display device. Additionally, a new DisplayMetrics object is created, and the source argument's API 17+ (Jelly Bean MR1) call getRealMetrics() is made to populate the metrics object. The now filled metrics object is used to set the Display's DPI and scale variables.
##Sensor.java ###Constructor
- public Sensor(android.hardware.Sensor sensor, Device device)
- This constructor builds a com.mindaptiv.saul.Sensor (henceforth referred to as Sensor) object using Android's own Sensor class (henceforth referred to as the sensor argument) and a Device object to map to. The superDevice field is tied to the device argument to complete the mapping for the Sensor (the Device's sensorsIndex field will be used for the other half of the mapping). The rest of the fields are filled using the sensor argument's getter functions. For fields that are only available on certain platforms (i.e. fifoMaxEventCount), the fields are set using getters, or filled with default values if the API level does not support the newer calls.
##Storage.java ###Constructor
- public Storage(Device suprah, String location, long available, long total, boolean emulated)
- This constructor builds a new Storage object using Device, String, boolean, and two long values. All five of these arguments have their values copied into the fields of the Storage object before returning.
##Midi.java ###Constructor
-
public Midi(MidiDeviceInfo info, Device superaDevice)
-
This constructor builds a new Midi object using the Device and MidiDeviceInfo values. The infoType, inCount, outCount, and ports fields are pulled directly from the info argument, while the String fields are grabbed using a Bundle object and the getProperties() method on the info argument.
-
public Midi()
-
This constructor builds a dummy Midi object with default values and a dummy MidiPort in its ports list.
#Native Code ##Native.c ###Test Examples
- void Java_com_mindaptiv_saul_Cylon_helloLog (JNIEnv env, jobject this, jstring logThis)*
- This method acts as an example for passing data from native code to Java. This method will log to logcat when called on the Java side of the project.
##Saul.cpp ###Converters
-
void GetJStringContent(JNIEnv AEnv, jstring AStr, std::string &ARes)*
-
This method takes in a given jstring (Java String representation in native code) and C++ std::string and converts the jstring's contents to UTF Chars and stores them in the std::string.
-
*deviceStruct buildDevice(JNIEnv env, jobject device)
-
This method takes a given jobject (meant to be a Device class object, otherwise the method will fail), then copy, convert, and store all of the Device data into a native deviceStruct.
-
displayStruct buildDisplay(JNIEnv env, jobject display)*
-
This method takes a given jobject (meant to be a Display class object, otherwise the method will fail), then copy, convert, and store all of the Display data into a native displayStruct.
-
controllerStruct buildController(JNIEnv env, jobject controller)*
-
This method takes a given jobject (meant to be a Controller class object, otherwise the method will fail), then copy, convert, and store all of the Controller data into a native controllerStruct.
-
storageStruct buildStorage(JNIEnv env, jobject storage)*
-
This method takes a given jobject (meant to be a Storage class object, otherwise the method will fail), then copy, convert, and store all of the Storage data into a native storageStruct.
-
sensorStruct buildSensor(JNIEnv env, jobject sensor)*
-
This method takes a given jobject (meant to be a Sensor class object, otherwise the method will fail), then copy, convert, and store all of the Sensor data into a native sensorStruct.
-
*midiPortStruct buildMidiPort(JNIEnv env, jobject midiPort)
-
This method takes a given jobject (meant to be a MidiPort class object, otherwise the method will fail), then copy, convert and store all of the MidiPort's data into a native midiPortStruct.
-
*midiStruct buildMidi(JNIEnv env, jobject midi)
-
This method takes a given jobject (meant to be a Midi class object, otherwise the method will fail), then copy, convert and store all of the Midi's data into a native midiStruct.
-
JNIEXPORT jstring JNICALL Java_com_mindaptiv_saul_Cylon_buildCylon(JNIEnv env, jobject obj, jobject saul)*
-
This method takes a given jobject (meant to be a Cylon class object, otherwise the method will fail), then copy, convert, and store all of the Cylon data into a native cylonStruct. Additionally, this method will grab data that could only be retrieved in native code, like the word size/osArchitecture field. The method will finally return back to the Java side of the project with a String value based on the username field of the Cylon data that was passed over to signify that the conversion was successful.
-
JNIEXPORT jstring JNICALL Java_com_mindaptiv_saul_Cylon_updateController(JNIEnv env, jobject obj, jint controllerIndex, jobject controller)*
-
This method is called on the Android side of the code and executes natively whenever a motion event or key event is fire for a tracked gamepad/controller for the current Cylon, IFF the Cylon has already been converted to a cylonStruct. The code is almost identical to buildController(), in that it grabs the updated values of the Controller object and maps it to the appropriate controllerStruct's fields.
-
void produceJniLog()
-
This method prints out the fields of the cylonStruct testCylon in Saul.cpp via the Android logging method.