├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── snaggly │ │ └── ksw_toolkit │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── aidl │ │ └── com │ │ │ ├── snaggly │ │ │ └── ksw_toolkit │ │ │ │ ├── IAdvancedBrightnessControl.aidl │ │ │ │ ├── IAutoTimeListener.aidl │ │ │ │ ├── IKSWToolKitService.aidl │ │ │ │ ├── IMcuListener.aidl │ │ │ │ └── ISystemOptionsControl.aidl │ │ │ └── wits │ │ │ └── pms │ │ │ ├── ICmdListener.aidl │ │ │ ├── IContentObserver.aidl │ │ │ ├── IPowerManagerAppService.aidl │ │ │ └── custom │ │ │ ├── ICallBack.aidl │ │ │ └── ICallBackController.aidl │ ├── ic_launcher-playstore.png │ ├── ic_launcher_wabes-playstore.png │ ├── ic_launcher_wabes_round-playstore.png │ ├── java │ │ ├── com │ │ │ └── snaggly │ │ │ │ └── ksw_toolkit │ │ │ │ ├── core │ │ │ │ ├── config │ │ │ │ │ ├── ConfigData.kt │ │ │ │ │ ├── ConfigManager.kt │ │ │ │ │ └── beans │ │ │ │ │ │ ├── AdvancedBrightness.kt │ │ │ │ │ │ ├── EventManager.kt │ │ │ │ │ │ └── SystemOptions.kt │ │ │ │ └── service │ │ │ │ │ ├── adb │ │ │ │ │ └── AdbServiceConnection.kt │ │ │ │ │ └── helper │ │ │ │ │ ├── CoreServiceClient.kt │ │ │ │ │ └── ServiceAliveCheck.kt │ │ │ │ ├── gui │ │ │ │ ├── AdbShell.kt │ │ │ │ ├── AdvancedBrightness.kt │ │ │ │ ├── ConfigImportExport.kt │ │ │ │ ├── EventManager.kt │ │ │ │ ├── EventManagerSelectAction.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── McuListener.kt │ │ │ │ ├── SystemTwaks.kt │ │ │ │ ├── ToolKit.kt │ │ │ │ └── viewmodels │ │ │ │ │ ├── AdbShellViewModel.kt │ │ │ │ │ ├── ConfigImportExportViewModel.kt │ │ │ │ │ ├── EventManagerSelectActionViewModel.kt │ │ │ │ │ ├── EventManagerViewModel.kt │ │ │ │ │ ├── MainActivityViewModel.kt │ │ │ │ │ ├── McuListenerViewModel.kt │ │ │ │ │ ├── SystemTwaksViewModel.kt │ │ │ │ │ └── ToolKitViewModel.kt │ │ │ │ └── util │ │ │ │ ├── adapters │ │ │ │ ├── ListTypeAdapter.kt │ │ │ │ └── McuEventRVAdapter.kt │ │ │ │ ├── adb │ │ │ │ ├── AdbManager.kt │ │ │ │ └── ShellObserver.kt │ │ │ │ ├── github │ │ │ │ ├── AssetMetaData.kt │ │ │ │ ├── AuthorMetaData.kt │ │ │ │ ├── DownloadController.kt │ │ │ │ ├── GitHubRelease.kt │ │ │ │ └── VersionTag.kt │ │ │ │ ├── list │ │ │ │ ├── ListType.kt │ │ │ │ ├── app │ │ │ │ │ ├── AppInfo.kt │ │ │ │ │ └── AppsLister.kt │ │ │ │ ├── eventtype │ │ │ │ │ ├── EventManagerTypes.kt │ │ │ │ │ └── EventMode.kt │ │ │ │ ├── keyevent │ │ │ │ │ ├── KeyCode.kt │ │ │ │ │ └── KeyEvent.kt │ │ │ │ ├── mcu │ │ │ │ │ ├── McuCommandsEnum.kt │ │ │ │ │ ├── McuCommandsList.kt │ │ │ │ │ └── McuEventData.kt │ │ │ │ └── tasker │ │ │ │ │ ├── TakserTaskInfo.kt │ │ │ │ │ └── TaskerTaskLister.kt │ │ │ │ └── reflection │ │ │ │ └── KSWSettings.kt │ │ └── net │ │ │ └── dinglisch │ │ │ └── android │ │ │ └── taskerm │ │ │ ├── ActionCodes.java │ │ │ └── TaskerIntent.java │ └── res │ │ ├── anim │ │ ├── enter_from_buttom.xml │ │ ├── enter_from_top.xml │ │ ├── leave_to_buttom.xml │ │ ├── leave_to_top.xml │ │ ├── slide_enter_right_left.xml │ │ └── slide_exit_right_left.xml │ │ ├── color │ │ ├── main_btn_selector.xml │ │ ├── main_btn_text_selector.xml │ │ ├── main_info_btn_selector.xml │ │ ├── radio_selector.xml │ │ ├── red_btn_selector.xml │ │ ├── spinner_color.xml │ │ ├── spinner_dropdown_color.xml │ │ └── switch_selector.xml │ │ ├── drawable-anydpi │ │ └── ic_stat_name.xml │ │ ├── drawable-hdpi │ │ └── ic_stat_name.png │ │ ├── drawable-mdpi │ │ └── ic_stat_name.png │ │ ├── drawable-v24 │ │ ├── ic_aux.png │ │ ├── ic_dtv.png │ │ ├── ic_dvr.png │ │ ├── ic_launcher_foreground.xml │ │ ├── icon_fcam.png │ │ ├── id7_sys_factory_bg.png │ │ └── nbt_src_icon_carinfo.png │ │ ├── drawable-xhdpi │ │ └── ic_stat_name.png │ │ ├── drawable-xxhdpi │ │ └── ic_stat_name.png │ │ ├── drawable │ │ ├── baseline_indeterminate_check_box_24.xml │ │ ├── baseline_map_36.xml │ │ ├── baseline_music_video_36.xml │ │ ├── border.xml │ │ ├── border_focused.xml │ │ ├── border_pressed.xml │ │ ├── border_selector.xml │ │ ├── btn_1_car.png │ │ ├── btn_1_car_cl.png │ │ ├── btn_1_car_hl.png │ │ ├── btn_2_radio.png │ │ ├── btn_2_radio_cl.png │ │ ├── btn_2_radio_hl.png │ │ ├── btn_3_front_cam.png │ │ ├── btn_3_front_cam_cl.png │ │ ├── btn_3_front_cam_hl.png │ │ ├── btn_4_aux.png │ │ ├── btn_4_aux_cl.png │ │ ├── btn_4_aux_hl.png │ │ ├── btn_5_dvr.png │ │ ├── btn_5_dvr_cl.png │ │ ├── btn_5_dvr_hl.png │ │ ├── btn_6_dvd.png │ │ ├── btn_6_dvd_cl.png │ │ ├── btn_6_dvd_hl.png │ │ ├── btn_7_tv.png │ │ ├── btn_7_tv_cl.png │ │ ├── btn_7_tv_hl.png │ │ ├── btn_aux.xml │ │ ├── btn_car.xml │ │ ├── btn_dvd.xml │ │ ├── btn_dvr.xml │ │ ├── btn_front_cam.xml │ │ ├── btn_radio.xml │ │ ├── btn_selector.xml │ │ ├── btn_tv.xml │ │ ├── ic_baseline_brightness_high_64.xml │ │ ├── ic_baseline_brightness_low_64.xml │ │ ├── ic_baseline_cable_64.xml │ │ ├── ic_baseline_calculate_36.xml │ │ ├── ic_baseline_calendar_today_36.xml │ │ ├── ic_baseline_call_36.xml │ │ ├── ic_baseline_call_end_36.xml │ │ ├── ic_baseline_camera_alt_64.xml │ │ ├── ic_baseline_center_focus_weak_36.xml │ │ ├── ic_baseline_cloud_download_24.xml │ │ ├── ic_baseline_cloud_upload_24.xml │ │ ├── ic_baseline_code_36.xml │ │ ├── ic_baseline_contacts_36.xml │ │ ├── ic_baseline_email_36.xml │ │ ├── ic_baseline_file_copy_36.xml │ │ ├── ic_baseline_filter_center_focus_24.xml │ │ ├── ic_baseline_flip_to_front_36.xml │ │ ├── ic_baseline_home_24.xml │ │ ├── ic_baseline_info_24.xml │ │ ├── ic_baseline_keyboard_arrow_down_36.xml │ │ ├── ic_baseline_keyboard_arrow_left_36.xml │ │ ├── ic_baseline_keyboard_arrow_right_36.xml │ │ ├── ic_baseline_keyboard_arrow_up_36.xml │ │ ├── ic_baseline_keyboard_backspace_36.xml │ │ ├── ic_baseline_library_music_36.xml │ │ ├── ic_baseline_live_tv_64.xml │ │ ├── ic_baseline_play_arrow_36.xml │ │ ├── ic_baseline_radio_64.xml │ │ ├── ic_baseline_radio_button_checked_24.xml │ │ ├── ic_baseline_radio_button_checked_highlighted_24.xml │ │ ├── ic_baseline_radio_button_unchecked_24.xml │ │ ├── ic_baseline_radio_button_unchecked_highlighted_24.xml │ │ ├── ic_baseline_record_voice_over_36.xml │ │ ├── ic_baseline_settings_24.xml │ │ ├── ic_baseline_settings_input_component_64.xml │ │ ├── ic_baseline_settings_suggest_24.xml │ │ ├── ic_baseline_skip_next_36.xml │ │ ├── ic_baseline_skip_previous_36.xml │ │ ├── ic_baseline_stop_36.xml │ │ ├── ic_baseline_videocam_64.xml │ │ ├── ic_baseline_volume_down_36.xml │ │ ├── ic_baseline_volume_mute_36.xml │ │ ├── ic_baseline_volume_off_36.xml │ │ ├── ic_baseline_volume_up_36.xml │ │ ├── ic_baseline_web_asset_off_64.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ksw_id7_btn_pressed.png │ │ ├── ksw_id7_itme_select_bg_focused.png │ │ ├── ksw_id7_itme_select_bg_normal.png │ │ ├── ksw_id7_itme_select_bg_pressed.png │ │ └── radio_selector.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── adb_shell_fragment.xml │ │ ├── adv_brightness_fragment.xml │ │ ├── apps_view_list.xml │ │ ├── config_fragment.xml │ │ ├── dummy_list.xml │ │ ├── event_manager_fragment.xml │ │ ├── event_manager_select_action_fragment.xml │ │ ├── mcu_event.xml │ │ ├── mcu_listener_fragment.xml │ │ ├── spinner_dropdown_layout.xml │ │ ├── spinner_layout.xml │ │ ├── system_twaks_fragment.xml │ │ └── toolkit_fragment.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ ├── ic_launcher_round.xml │ │ ├── ic_launcher_wabes.xml │ │ └── ic_launcher_wabes_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_background_wabes.png │ │ ├── ic_launcher_round.png │ │ ├── ic_launcher_wabes_round.png │ │ └── ic_launcher_wabes_round_background.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_background_wabes.png │ │ ├── ic_launcher_round.png │ │ ├── ic_launcher_wabes_round.png │ │ └── ic_launcher_wabes_round_background.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_background_wabes.png │ │ ├── ic_launcher_round.png │ │ ├── ic_launcher_wabes_round.png │ │ └── ic_launcher_wabes_round_background.png │ │ ├── mipmap-xxhdpi │ │ ├── green_button.png │ │ ├── grey_button.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_background_wabes.png │ │ ├── ic_launcher_round.png │ │ ├── ic_launcher_wabes_round.png │ │ ├── ic_launcher_wabes_round_background.png │ │ └── red_button.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_background_wabes.png │ │ ├── ic_launcher_round.png │ │ ├── ic_launcher_wabes_round.png │ │ └── ic_launcher_wabes_round_background.png │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── mcuSources.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ └── file_provider_paths.xml │ └── test │ └── java │ └── com │ └── snaggly │ └── ksw_toolkit │ └── ExampleUnitTest.kt ├── build.gradle ├── enigma-backup └── .gitignore ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images └── screenshot-eventmanager.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | local.properties 3 | .DS_Store 4 | .idea/* 5 | .gradle/* 6 | build/* 7 | enigma-backup/* 8 | app/release/* 9 | app/debug/* 10 | app/build/* 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Attention: This repository is hereby declared as no longer maintained. 2 | The successor, a more feature-rich version, is now accessible at the following link: https://play.google.com/store/apps/details?id=tech.snaggle.ksw_toolkit. This updated version has been meticulously developed from the ground up with an emphasis on stability and the seamless integration of new functionalities. Although this repository is no longer actively maintained, it remains available for the submission of any arising issues. 3 | 4 | # KSW-ToolKit 5 | 6 | ![screenshot](/images/screenshot-eventmanager.png) 7 | 8 | KSW-ToolKit is an extension to your KSW Android screen. Once the service is installed, it will hijack the original McuService and will work as replacement which you can highly customize. This service allows you to remap your buttons to invoke various Android keystrokes, start any App of your desire or invoke various MCU hardware commands like switching sources or tuning the brightness. The service also bypasses various inconveniances the original McuService caused, like not hearing your Android when you're in OEM side, keeping your Apps open when you switch sources or generally having the Android react faster to your hardware inputs. 9 | 10 | ...in short KSW-ToolKit 11 | ## Features: 12 | * Rich customizability 13 | * Remapping of your hardware buttons 14 | * Automatic Day/Night switching 15 | * Auto Volumes 16 | * Sound Restorer to keep sound running on OEM side 17 | * Enables extra hardware buttons* 18 | * Built in ADB Shell to manipulate and have more control over your Android 19 | * And much more to discover... 20 | 21 | *This is the "Media-Button Hack". It will depend on the car and MCU model you have. In BMWs for example this hack will allow the Tel and Media/CD button on your iDrive to also get triggered as Phone and MODE event in Android. Check MCU Listener if this hack works for you. 22 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdkVersion 32 8 | buildToolsVersion "30.0.3" 9 | 10 | defaultConfig { 11 | applicationId "com.snaggly.wits.ksw_toolkit.client" 12 | minSdkVersion 28 13 | targetSdkVersion 32 14 | versionCode 1 15 | versionName "1.2" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled true 23 | shrinkResources true 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | kotlinOptions { 32 | jvmTarget = '1.8' 33 | } 34 | buildFeatures { 35 | aidl true 36 | } 37 | namespace 'com.snaggly.ksw_toolkit' 38 | } 39 | 40 | dependencies { 41 | implementation 'com.google.code.gson:gson:2.8.6' 42 | implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.30" 43 | implementation 'androidx.appcompat:appcompat:1.3.1' 44 | implementation 'com.google.android.material:material:1.4.0' 45 | implementation 'androidx.constraintlayout:constraintlayout:2.1.1' 46 | implementation 'androidx.preference:preference-ktx:1.1.1' 47 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 48 | implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' 49 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' 50 | implementation "androidx.recyclerview:recyclerview:1.2.1" 51 | implementation "androidx.recyclerview:recyclerview-selection:1.1.0" 52 | implementation 'com.github.KswCarProject:McuCommunicator:1.0.2' 53 | testImplementation 'junit:junit:4.13.2' 54 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 55 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 56 | } -------------------------------------------------------------------------------- /app/gradle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Snaggly/KSW-ToolKit/cd4f2a88a04ac21ec6c814eec942c36859afc510/app/gradle.properties -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keep class com.snaggly.ksw_toolkit.core.config.ConfigData {*;} 24 | -keep class com.snaggly.ksw_toolkit.core.config.beans.** {*;} 25 | -keep class com.snaggly.ksw_toolkit.util.list.eventtype.EventManagerTypes {*;} 26 | -keep class com.snaggly.ksw_toolkit.util.list.eventtype.EventMode {*;} 27 | -keep class com.snaggly.ksw_toolkit.util.list.keyevent.KeyCode {*;} 28 | -keep class com.snaggly.ksw_toolkit.util.list.mcu.McuCommandsList {*;} 29 | -keep class com.snaggly.ksw_toolkit.util.github.** {*;} 30 | -keep class com.snaggly.ksw_toolkit.IKSWToolKitService {*;} 31 | -keep class com.snaggly.ksw_toolkit.IMcuListener {*;} 32 | -keep class com.snaggly.ksw_toolkit.IAdvancedBrightnessControl {*;} 33 | -keep class com.snaggly.ksw_toolkit.IAutoTimeListener {*;} 34 | -keep class com.snaggly.ksw_toolkit.ISystemOptionsControl {*;} 35 | -keep class net.dinglisch.android.taskerm.** {*;} 36 | -keep class projekt.auto.mcu.** {*;} 37 | -keep class * implements android.os.Parcelable { 38 | public static final android.os.Parcelable$Creator *; 39 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/snaggly/ksw_toolkit/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import org.junit.Assert 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * @see [Testing documentation](http://d.android.com/tools/testing) 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 20 | Assert.assertEquals("com.snaggly.ksw_toolkit", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 39 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/snaggly/ksw_toolkit/IAdvancedBrightnessControl.aidl: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit; 2 | 3 | import com.snaggly.ksw_toolkit.IAutoTimeListener; 4 | 5 | interface IAdvancedBrightnessControl { 6 | boolean getAdvBri_IsTimeBased(); 7 | void setAdvBri_IsTimeBased(boolean value); 8 | boolean getAdvBri_IsUSBBased(); 9 | void setAdvBri_IsUSBBased(boolean value); 10 | String getAdvBri_SunriseAt(); 11 | void setAdvBri_SunriseAt(String value); 12 | String getAdvBri_SunsetAt(); 13 | void setAdvBri_SunsetAt(String value); 14 | boolean getAdvBri_Autotimes(); 15 | void setAdvBri_Autotimes(boolean value); 16 | int getAdvBri_DaylightBri(); 17 | void setAdvBri_DaylightBri(int value); 18 | int getAdvBri_DaylightHLBri(); 19 | void setAdvBri_DaylightHLBri(int value); 20 | int getAdvBri_NightBri(); 21 | void setAdvBri_NightBri(int value); 22 | int getAdvBri_NightHLBri(); 23 | void setAdvBri_NightHLBri(int value); 24 | 25 | void registerAutoTimeListener(IAutoTimeListener listener); 26 | void unregisterAutoTimeListener(IAutoTimeListener listener); 27 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/snaggly/ksw_toolkit/IAutoTimeListener.aidl: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit; 2 | 3 | interface IAutoTimeListener { 4 | void updateAutoTime(String sunrise, String sunset); 5 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/snaggly/ksw_toolkit/IKSWToolKitService.aidl: -------------------------------------------------------------------------------- 1 | // IKSWToolKitService.aidl 2 | package com.snaggly.ksw_toolkit; 3 | 4 | import com.snaggly.ksw_toolkit.IMcuListener; 5 | import com.snaggly.ksw_toolkit.ISystemOptionsControl; 6 | import com.snaggly.ksw_toolkit.IAdvancedBrightnessControl; 7 | 8 | interface IKSWToolKitService { 9 | boolean sendMcuCommand(int cmdType, in byte[] data); 10 | 11 | boolean changeBtnConfig(int btnType, int cmdType, String cmdValue); 12 | void setDefaultBtnLayout(); 13 | 14 | String getConfig(); 15 | boolean setConfig(String configJson); 16 | 17 | boolean registerMcuListener(IMcuListener listener); 18 | boolean unregisterMcuListener(IMcuListener listener); 19 | 20 | ISystemOptionsControl getSystemOptionsController(); 21 | IAdvancedBrightnessControl getAdvancedBrightnessController(); 22 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/snaggly/ksw_toolkit/IMcuListener.aidl: -------------------------------------------------------------------------------- 1 | // IMcuListener.aidl 2 | package com.snaggly.ksw_toolkit; 3 | 4 | interface IMcuListener { 5 | void updateMcu(String eventName, int cmdType, in byte[] data); 6 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/snaggly/ksw_toolkit/ISystemOptionsControl.aidl: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit; 2 | 3 | interface ISystemOptionsControl { 4 | int getNightBrightnessLevel(); 5 | void setNightBrightnessLevel(int value); 6 | 7 | boolean getTabletMode(); 8 | void setTabletMode(boolean value); 9 | 10 | boolean getStartAtBoot(); 11 | void setStartAtBoot(boolean value); 12 | 13 | boolean getHijackCS(); 14 | void setHijackCS(boolean value); 15 | 16 | boolean getSoundRestorer(); 17 | void setSoundRestorer(boolean value); 18 | 19 | boolean getAutoTheme(); 20 | void setAutoTheme(boolean value); 21 | 22 | boolean getAutoVolume(); 23 | void setAutoVolume(boolean value); 24 | 25 | boolean getRetainVolume(); 26 | void setRetainVolume(boolean value); 27 | 28 | boolean getLogMcuEvent(); 29 | void setLogMcuEvent(boolean value); 30 | 31 | boolean getInterceptMcuCommand(); 32 | void setInterceptMcuCommand(boolean value); 33 | 34 | boolean getExtraMediaButtonHandle(); 35 | void setExtraMediaButtonHandle(boolean value); 36 | 37 | boolean getNightBrightness(); 38 | void setNightBrightness(boolean value); 39 | 40 | String getMcuPath(); 41 | boolean setMcuPath(String path); 42 | 43 | boolean getHideStartMessage(); 44 | void setHideStartMessage(boolean value); 45 | 46 | boolean getDecoupleNAVBtn(); 47 | void setDecoupleNAVBtn(boolean value); 48 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/wits/pms/ICmdListener.aidl: -------------------------------------------------------------------------------- 1 | package com.wits.pms; 2 | 3 | interface ICmdListener { 4 | boolean handleCommand(String str); 5 | void updateStatusInfo(String str); 6 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/wits/pms/IContentObserver.aidl: -------------------------------------------------------------------------------- 1 | package com.wits.pms; 2 | 3 | interface IContentObserver { 4 | void onChange(); 5 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/wits/pms/IPowerManagerAppService.aidl: -------------------------------------------------------------------------------- 1 | package com.wits.pms; 2 | 3 | interface IPowerManagerAppService { 4 | boolean sendCommand(String str); 5 | boolean sendStatus(String str); 6 | void registerCmdListener(com.wits.pms.ICmdListener iCmdListener); 7 | void unregisterCmdListener(com.wits.pms.ICmdListener iCmdListener); 8 | void registerObserver(String str, com.wits.pms.IContentObserver iContentObserver); 9 | void unregisterObserver(com.wits.pms.IContentObserver iContentObserver); 10 | boolean getStatusBoolean(String str); 11 | int getStatusInt(String str); 12 | String getStatusString(String str); 13 | int getSettingsInt(String str); 14 | String getSettingsString(String str); 15 | void setSettingsInt(String str, int i); 16 | void setSettingsString(String str, String str2); 17 | void addIntStatus(String str, int i); 18 | void addBooleanStatus(String str, boolean z); 19 | void addStringStatus(String str, String str2); 20 | void saveJsonConfig(String str, String str2); 21 | String getJsonConfig(String str); 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/wits/pms/custom/ICallBack.aidl: -------------------------------------------------------------------------------- 1 | package com.wits.pms.custom; 2 | 3 | interface ICallBack { 4 | void onReverse(int z); 5 | void onLRReverse(int i); 6 | void onRRadar(int i, int i2, int i3, int i4, int i5); 7 | void onFRadar(int i, int i2, int i3, int i4, int i5); 8 | void onAngle(int i); 9 | void onDoor(boolean z, boolean z2, boolean z3, boolean z4, boolean z5, boolean z6); 10 | void onAcc(boolean z); 11 | } -------------------------------------------------------------------------------- /app/src/main/aidl/com/wits/pms/custom/ICallBackController.aidl: -------------------------------------------------------------------------------- 1 | package com.wits.pms.custom; 2 | 3 | interface ICallBackController { 4 | void setICallBack(com.wits.pms.custom.ICallBack iCallBack); 5 | com.wits.pms.custom.ICallBack getICallBack(); 6 | } -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Snaggly/KSW-ToolKit/cd4f2a88a04ac21ec6c814eec942c36859afc510/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher_wabes-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Snaggly/KSW-ToolKit/cd4f2a88a04ac21ec6c814eec942c36859afc510/app/src/main/ic_launcher_wabes-playstore.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher_wabes_round-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Snaggly/KSW-ToolKit/cd4f2a88a04ac21ec6c814eec942c36859afc510/app/src/main/ic_launcher_wabes_round-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/config/ConfigData.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.config 2 | 3 | import com.snaggly.ksw_toolkit.core.config.beans.AdvancedBrightness 4 | import com.snaggly.ksw_toolkit.core.config.beans.EventManager 5 | import com.snaggly.ksw_toolkit.core.config.beans.SystemOptions 6 | import com.snaggly.ksw_toolkit.util.list.eventtype.EventManagerTypes 7 | 8 | data class ConfigData( 9 | var systemOptions: SystemOptions, 10 | var eventManagers : HashMap, 11 | var advancedBrightness: AdvancedBrightness 12 | ) 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/config/ConfigManager.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.config 2 | 3 | import com.google.gson.Gson 4 | import com.snaggly.ksw_toolkit.core.config.beans.SystemOptions 5 | import com.snaggly.ksw_toolkit.core.service.helper.CoreServiceClient 6 | import java.io.* 7 | 8 | class ConfigManager private constructor() { 9 | companion object { 10 | private val gson = Gson() 11 | 12 | fun getConfigFromJson(json : String) : ConfigData{ 13 | return gson.fromJson(json, ConfigData::class.java) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/config/beans/AdvancedBrightness.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.config.beans 2 | 3 | class AdvancedBrightness ( 4 | var isTimeBasedEnabled: Boolean?, 5 | var isUSBBasedEnabled: Boolean?, 6 | var sunriseAt: String?, 7 | var sunsetAt: String?, 8 | var autoTimes: Boolean?, 9 | var daylightBrightness: Int?, 10 | var daylightHLBrightness: Int?, 11 | var nightBrightnessLevel: Int?, 12 | var nightHLBrightnessLevel: Int? 13 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/config/beans/EventManager.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.config.beans 2 | 3 | import com.snaggly.ksw_toolkit.util.list.eventtype.EventMode 4 | 5 | class EventManager(var eventMode: EventMode, var keyCode: Int, var appName: String, 6 | var mcuCommandMode: Int, var taskerTaskName: String 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/config/beans/SystemOptions.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.config.beans 2 | 3 | class SystemOptions( 4 | var startAtBoot: Boolean? = false, 5 | var hijackCS: Boolean? = false, 6 | var soundRestorer: Boolean? = false, 7 | var autoTheme: Boolean? = false, 8 | var autoVolume: Boolean? = false, 9 | var retainVolume: Boolean? = false, 10 | var logMcuEvent: Boolean? = true, 11 | var interceptMcuCommand: Boolean? = true, 12 | var extraMediaButtonHandle: Boolean? = false, 13 | var nightBrightness: Boolean? = false, 14 | var nightBrightnessLevel: Int? = 65, 15 | var mcuPath: String? = "", 16 | var tabletMode: Boolean? = false, 17 | var hideStartMessage: Boolean? = false, 18 | var decoupleNAVBtn: Boolean? 19 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/service/adb/AdbServiceConnection.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.service.adb 2 | 3 | import android.content.Context 4 | import com.snaggly.ksw_toolkit.core.service.helper.CoreServiceClient 5 | import com.snaggly.ksw_toolkit.util.adb.AdbManager 6 | 7 | object AdbServiceConnection { 8 | fun stopKsw(context: Context) { 9 | AdbManager.sendCommand("am stopservice --user 0 com.wits.pms/com.wits.pms.mcu.McuService\nappops set com.wits.pms SYSTEM_ALERT_WINDOW deny", context) 10 | } 11 | 12 | fun startKsw(context: Context) { 13 | AdbManager.sendCommand("am startservice --user 0 com.wits.pms/com.wits.pms.mcu.McuService\nappops set com.wits.pms SYSTEM_ALERT_WINDOW allow", context) 14 | } 15 | 16 | fun startThisService(context: Context) { 17 | AdbManager.sendCommand("am startservice --user 0 ${CoreServiceClient.packageName}/${CoreServiceClient.className}", context) 18 | //AdbManager.sendCommand("am startservice --user 0 com.snaggly.wits.ksw_toolkit.service/com.snaggly.ksw_toolkit.core.service.CoreService", context) 19 | } 20 | 21 | fun stopThisService(context: Context) { 22 | AdbManager.sendCommand("am stopservice --user 0 ${CoreServiceClient.packageName}/${CoreServiceClient.className}", context) 23 | } 24 | 25 | fun sendKeyEvent(code: Int, context: Context) { 26 | AdbManager.sendCommand("input keyevent $code", context) 27 | } 28 | 29 | fun startApp(appId: String, context: Context) { 30 | AdbManager.sendCommand("monkey -p $appId -c android.intent.category.LAUNCHER 1", context) 31 | } 32 | 33 | fun sendCommand(command: String, context: Context) { 34 | AdbManager.sendCommand("$command\n", context) 35 | } 36 | 37 | fun checkIfThisServiceIsAlive(context: Context) { 38 | AdbManager.sendCommand("dumpsys activity services ${CoreServiceClient.packageName} | grep \"ServiceRecord\" | awk '{print $4}' | sed 's/.$//'", context) 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/core/service/helper/ServiceAliveCheck.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.core.service.helper 2 | 3 | import android.content.Context 4 | import androidx.lifecycle.Observer 5 | import com.snaggly.ksw_toolkit.core.service.adb.AdbServiceConnection 6 | import com.snaggly.ksw_toolkit.util.adb.AdbManager 7 | import com.snaggly.ksw_toolkit.util.adb.ShellObserver 8 | import java.util.* 9 | import kotlin.collections.ArrayList 10 | 11 | object ServiceAliveCheck { 12 | val serviceAliveObservers = LinkedList>() 13 | 14 | fun checkIfServiceIsAlive(context: Context) { 15 | AdbManager.connect(context) 16 | AdbManager.registerShellListener( object : ShellObserver { 17 | override fun update(newLines: ArrayList) { 18 | var isRunning = false 19 | for (line in newLines) { 20 | if (line.contains("${CoreServiceClient.packageName}/${CoreServiceClient.className}")) { 21 | isRunning = true 22 | break 23 | } 24 | } 25 | if (isRunning || newLines.size > 1) { 26 | AdbManager.unregisterShellListener() 27 | serviceAliveObservers.forEach { 28 | it.onChanged(isRunning) 29 | } 30 | } 31 | } 32 | }, context) 33 | AdbServiceConnection.checkIfThisServiceIsAlive(context) 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/gui/AdbShell.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.gui 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.ArrayAdapter 8 | import android.widget.Button 9 | import android.widget.ListView 10 | import android.widget.Toast 11 | import androidx.fragment.app.Fragment 12 | import androidx.lifecycle.ViewModelProvider 13 | import com.google.android.material.textfield.TextInputEditText 14 | import com.snaggly.ksw_toolkit.R 15 | import com.snaggly.ksw_toolkit.util.adb.ShellObserver 16 | import com.snaggly.ksw_toolkit.gui.viewmodels.AdbShellViewModel 17 | import com.snaggly.ksw_toolkit.util.adb.AdbManager 18 | 19 | class AdbShell : Fragment() { 20 | 21 | private val adbShellObserver = object : ShellObserver { 22 | override fun update(newLines: ArrayList) { 23 | requireActivity().runOnUiThread { 24 | newLines.forEach { 25 | adbLines[0] += it 26 | } 27 | listAdapter.notifyDataSetChanged() 28 | } 29 | } 30 | } 31 | 32 | companion object { 33 | fun newInstance() = AdbShell() 34 | } 35 | 36 | private lateinit var viewModel: AdbShellViewModel 37 | private lateinit var shellListView: ListView 38 | private lateinit var textInput: TextInputEditText 39 | private lateinit var sendButton: Button 40 | private lateinit var listAdapter: ArrayAdapter 41 | private val adbLines : ArrayList = arrayListOf("") 42 | 43 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 44 | savedInstanceState: Bundle?): View? { 45 | return inflater.inflate(R.layout.adb_shell_fragment, container, false) 46 | } 47 | 48 | override fun onActivityCreated(savedInstanceState: Bundle?) { 49 | super.onActivityCreated(savedInstanceState) 50 | viewModel = ViewModelProvider(this).get(AdbShellViewModel::class.java) 51 | initElements() 52 | initClickEvent() 53 | } 54 | 55 | override fun onStart() { 56 | super.onStart() 57 | sendButton.requestFocus() 58 | initList() 59 | try { 60 | AdbManager.registerShellListener(adbShellObserver, requireContext()) 61 | } 62 | catch (e : Exception) { 63 | Toast.makeText(requireContext(), "Could not start Service", Toast.LENGTH_LONG).show() 64 | } 65 | } 66 | 67 | override fun onResume() { 68 | super.onResume() 69 | adbLines[0] = "" 70 | listAdapter.notifyDataSetChanged() 71 | } 72 | 73 | override fun onStop() { 74 | super.onStop() 75 | try { 76 | AdbManager.unregisterShellListener() 77 | } 78 | catch (e : Exception) {} 79 | } 80 | 81 | private fun initElements() { 82 | shellListView = requireView().findViewById(R.id.adbShellStdoutListView) 83 | textInput = requireView().findViewById(R.id.adbEditText) 84 | sendButton = requireView().findViewById(R.id.adbSend) 85 | } 86 | 87 | private fun initList() { 88 | listAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, adbLines) 89 | shellListView.adapter = listAdapter 90 | } 91 | 92 | private fun initClickEvent() { 93 | sendButton.setOnClickListener { 94 | AdbManager.sendCommand(textInput.text.toString(), requireContext()) 95 | textInput.setText("") 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/gui/ConfigImportExport.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.gui 2 | 3 | import android.app.AlertDialog 4 | import android.content.Intent 5 | import androidx.lifecycle.ViewModelProvider 6 | import android.os.Bundle 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.view.WindowManager 11 | import android.widget.Button 12 | import android.widget.Toast 13 | import androidx.activity.result.ActivityResultLauncher 14 | import androidx.activity.result.contract.ActivityResultContract 15 | import androidx.activity.result.contract.ActivityResultContracts 16 | import androidx.fragment.app.Fragment 17 | import com.snaggly.ksw_toolkit.R 18 | import com.snaggly.ksw_toolkit.gui.viewmodels.ConfigImportExportViewModel 19 | import com.snaggly.ksw_toolkit.util.adb.AdbManager 20 | 21 | class ConfigImportExport(private val getContent: ActivityResultLauncher, 22 | private val createDocument: ActivityResultLauncher) : Fragment() { 23 | private lateinit var importExportViewModel: ConfigImportExportViewModel 24 | private lateinit var importConfigBtn: Button 25 | private lateinit var exportConfigBtn: Button 26 | private lateinit var restartBtn: Button 27 | 28 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 29 | savedInstanceState: Bundle?): View? { 30 | 31 | return inflater.inflate(R.layout.config_fragment, container, false) 32 | } 33 | 34 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 35 | super.onViewCreated(view, savedInstanceState) 36 | importExportViewModel = ViewModelProvider(this).get(ConfigImportExportViewModel::class.java) 37 | initBtns() 38 | initBtnClicks() 39 | } 40 | 41 | private fun initBtns() { 42 | importConfigBtn = requireView().findViewById(R.id.importConfigBtn) 43 | exportConfigBtn = requireView().findViewById(R.id.exportConfigBtn) 44 | restartBtn = requireView().findViewById(R.id.restartSystemBtn) 45 | } 46 | 47 | private fun initBtnClicks() { 48 | importConfigBtn.setOnClickListener { 49 | try { 50 | getContent.launch("*/*") 51 | } catch (exception: Exception) { 52 | val alertExc = AlertDialog.Builder(activity, R.style.alertDialogNight).setTitle("KSW-ToolKit-Config") 53 | .setMessage("Unable to import!\n\n$exception").create() 54 | alertExc.show() 55 | } 56 | } 57 | 58 | exportConfigBtn.setOnClickListener { 59 | try { 60 | createDocument.launch("KSW-ToolKit.json") 61 | } catch (exception: Exception) { 62 | val alertExc = AlertDialog.Builder(activity, R.style.alertDialogNight).setTitle("KSW-ToolKit-Config") 63 | .setMessage("Unable to export!\n\n$exception").create() 64 | alertExc.show() 65 | } 66 | } 67 | 68 | restartBtn.setOnClickListener { 69 | try { 70 | AdbManager.sendCommand("reboot", requireContext()) 71 | } catch (exception: Exception) { 72 | val alertExc = AlertDialog.Builder(activity, R.style.alertDialogNight).setTitle("KSW-ToolKit-Config") 73 | .setMessage("Unable to restart!\n\n${exception.stackTrace}").create() 74 | alertExc.show() 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /app/src/main/java/com/snaggly/ksw_toolkit/gui/McuListener.kt: -------------------------------------------------------------------------------- 1 | package com.snaggly.ksw_toolkit.gui 2 | 3 | import androidx.lifecycle.ViewModelProvider 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.MenuItem 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.Button 10 | import android.widget.TextView 11 | import androidx.fragment.app.Fragment 12 | import androidx.recyclerview.widget.LinearLayoutManager 13 | import androidx.recyclerview.widget.RecyclerView 14 | import com.google.android.material.textfield.TextInputEditText 15 | import com.snaggly.ksw_toolkit.IMcuListener 16 | import com.snaggly.ksw_toolkit.R 17 | import com.snaggly.ksw_toolkit.core.service.helper.CoreServiceClient 18 | import com.snaggly.ksw_toolkit.gui.viewmodels.McuListenerViewModel 19 | import com.snaggly.ksw_toolkit.util.list.mcu.McuData 20 | import java.lang.NumberFormatException 21 | 22 | class McuListener(private val coreServiceClient: CoreServiceClient) : Fragment() { 23 | 24 | private lateinit var viewModel: McuListenerViewModel 25 | private lateinit var mcuEventRV: RecyclerView 26 | private lateinit var mcuEventFilterRV: RecyclerView 27 | 28 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 29 | savedInstanceState: Bundle?): View? { 30 | return inflater.inflate(R.layout.mcu_listener_fragment, container, false) 31 | } 32 | 33 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 34 | super.onViewCreated(view, savedInstanceState) 35 | viewModel = ViewModelProvider(this).get(McuListenerViewModel::class.java) 36 | initElements() 37 | } 38 | 39 | override fun onResume() { 40 | super.onResume() 41 | coreServiceClient.coreService?.registerMcuListener(mcuObserver) 42 | } 43 | 44 | override fun onPause() { 45 | coreServiceClient.coreService?.unregisterMcuListener(mcuObserver) 46 | super.onPause() 47 | } 48 | 49 | override fun onContextItemSelected(item: MenuItem): Boolean { 50 | if (item.itemId == 1) { 51 | viewModel.getLastSelectedEvent()?.let { addFilterElement(it) } 52 | } 53 | return super.onContextItemSelected(item) 54 | } 55 | 56 | private fun addFilterElement(mcuData: McuData) { 57 | if (!viewModel.mcuFilter.contains(mcuData)) 58 | viewModel.mcuFilter.add(mcuData) 59 | viewModel.addFilterEntryToAdapter(mcuData) 60 | } 61 | 62 | private fun initElements() { 63 | mcuEventRV = requireView().findViewById(R.id.McuEventsRV); 64 | mcuEventRV.layoutManager = LinearLayoutManager(context) 65 | mcuEventRV.adapter = viewModel.getMcuEventAdapter() 66 | 67 | mcuEventFilterRV = requireView().findViewById(R.id.filterListRV); 68 | mcuEventFilterRV.layoutManager = LinearLayoutManager(context) 69 | mcuEventFilterRV.adapter = viewModel.getMcuEventFilterAdapter() 70 | 71 | val filterNoticeTV = requireView().findViewById(R.id.noFiltersNoticeTV).apply { 72 | viewModel.filterListChangedObserver = { 73 | visibility = if (mcuEventFilterRV.visibility == View.GONE || viewModel.mcuFilter.size > 0) 74 | View.GONE 75 | else 76 | View.VISIBLE 77 | } 78 | } 79 | 80 | requireView().findViewById