├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── microntek │ │ └── threecats │ │ └── autovolume │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ ├── android │ │ │ └── microntek │ │ │ │ ├── CarManageCallback.java │ │ │ │ ├── CarManager.java │ │ │ │ ├── ICarManageCallback.java │ │ │ │ ├── ICarService.java │ │ │ │ ├── IRTable.java │ │ │ │ └── MTCData.java │ │ └── com │ │ │ └── microntek │ │ │ └── threecats │ │ │ └── autovolume │ │ │ ├── AutoVolumeBooter.java │ │ │ ├── CanBusDriver.java │ │ │ ├── CanBusReceiver.java │ │ │ ├── CarVolume.java │ │ │ ├── MainActivity.java │ │ │ ├── TestVolActivity.java │ │ │ ├── VolumeActivity.java │ │ │ └── VolumeService.java │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_arrow_drop_down_white_24dp.png │ │ └── ic_arrow_drop_up_white_24dp.png │ │ ├── drawable-mdpi │ │ ├── ic_arrow_drop_down_white_24dp.png │ │ └── ic_arrow_drop_up_white_24dp.png │ │ ├── drawable-xhdpi │ │ ├── ic_arrow_drop_down_white_24dp.png │ │ └── ic_arrow_drop_up_white_24dp.png │ │ ├── drawable-xxhdpi │ │ ├── ic_arrow_drop_down_white_24dp.png │ │ └── ic_arrow_drop_up_white_24dp.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_arrow_drop_down_white_24dp.png │ │ └── ic_arrow_drop_up_white_24dp.png │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout-nodpi │ │ ├── activity_test_vol.xml │ │ └── main.xml │ │ ├── layout │ │ ├── overlay.xml │ │ └── volume_activity.xml │ │ ├── mipmap-hdpi │ │ └── autovol.png │ │ ├── mipmap-mdpi │ │ └── autovol.png │ │ ├── mipmap-xhdpi │ │ └── autovol.png │ │ ├── mipmap-xxhdpi │ │ └── autovol.png │ │ ├── mipmap-xxxhdpi │ │ └── autovol.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── microntek │ └── threecats │ └── autovolume │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | /.idea/caches 7 | /.idea/codeStyles 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion '27.0.3' 6 | defaultConfig { 7 | applicationId "com.microntek.threecats.autovolume" 8 | minSdkVersion 21 9 | targetSdkVersion 22 10 | versionCode 4 11 | versionName "1.2.1" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.0' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', { 27 | exclude group: 'com.android.support', module: 'support-annotations' 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/microntek/threecats/autovolume/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.microntek.threecats.autovolume", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 39 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/android/microntek/CarManageCallback.java: -------------------------------------------------------------------------------- 1 | package android.microntek; 2 | 3 | import android.microntek.ICarManageCallback.Stub; 4 | import android.os.Bundle; 5 | import android.os.RemoteException; 6 | 7 | public class CarManageCallback extends Stub { 8 | public void onStatusChanged(String type, Bundle bundle) throws RemoteException { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/android/microntek/CarManager.java: -------------------------------------------------------------------------------- 1 | package android.microntek; 2 | 3 | import android.microntek.ICarService.Stub; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.IBinder; 7 | import android.os.Message; 8 | 9 | import java.lang.reflect.InvocationTargetException; 10 | import java.lang.reflect.Method; 11 | 12 | public class CarManager { 13 | public static final int MSG_ON_STATUS = -1; 14 | private static final String TAG = "MtcCarManager"; 15 | private CarManageCallback mCarManageCallback; 16 | private ICarService mCarService; 17 | private Handler mHandler; 18 | private String mType; 19 | 20 | class C05991 extends CarManageCallback { 21 | C05991() { 22 | } 23 | 24 | public void onStatusChanged(String type, Bundle bundle) { 25 | if (CarManager.this.mType.contains(type)) { 26 | try { 27 | Message msg = Message.obtain(CarManager.this.mHandler, (int) CarManager.MSG_ON_STATUS); 28 | msg.obj = type; 29 | msg.setData(bundle); 30 | CarManager.this.mHandler.sendMessage(msg); 31 | } catch (Exception e) { 32 | } 33 | } 34 | } 35 | } 36 | 37 | public CarManager() { 38 | this.mCarManageCallback = new C05991(); 39 | if (this.mCarService == null) { 40 | this.mCarService = Stub.asInterface(getCarService()); 41 | } 42 | } 43 | 44 | private static IBinder getCarService() { 45 | try { 46 | Class localClass = Class.forName("android.os.ServiceManager"); 47 | Method getService = localClass.getMethod("getService", new Class[] {String.class}); 48 | 49 | if(getService != null) { 50 | return (IBinder)getService.invoke(localClass, new Object[]{"carservice"}); 51 | } 52 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 53 | e.printStackTrace(); 54 | } 55 | 56 | return null; 57 | } 58 | 59 | public void attach(Handler handler, String type) { 60 | if (this.mHandler == null && handler != null && type != null) { 61 | this.mHandler = handler; 62 | this.mType = type; 63 | try { 64 | this.mCarService.registerCallback(this.mCarManageCallback); 65 | } catch (Exception e) { 66 | } 67 | } 68 | } 69 | 70 | public void detach() { 71 | if (this.mHandler != null) { 72 | try { 73 | this.mCarService.unregisterCallback(this.mCarManageCallback); 74 | } catch (Exception e) { 75 | } 76 | this.mHandler = null; 77 | } 78 | } 79 | 80 | public void putState(String key, boolean value) { 81 | try { 82 | this.mCarService.putBooleanState(key, value); 83 | } catch (Exception e) { 84 | } 85 | } 86 | 87 | public void putState(String key, byte value) { 88 | try { 89 | this.mCarService.putByteState(key, value); 90 | } catch (Exception e) { 91 | } 92 | } 93 | 94 | public void putState(String key, int value) { 95 | try { 96 | this.mCarService.putIntState(key, value); 97 | } catch (Exception e) { 98 | } 99 | } 100 | 101 | public void putState(String key, String value) { 102 | try { 103 | this.mCarService.putStringState(key, value); 104 | } catch (Exception e) { 105 | } 106 | } 107 | 108 | public void putState(String key, byte[] value) { 109 | try { 110 | this.mCarService.putByteArraryState(key, value); 111 | } catch (Exception e) { 112 | } 113 | } 114 | 115 | public void putState(String key, int[] value) { 116 | try { 117 | this.mCarService.putIntArraryState(key, value); 118 | } catch (Exception e) { 119 | } 120 | } 121 | 122 | public void putState(String key, String[] value) { 123 | try { 124 | this.mCarService.putStringArraryState(key, value); 125 | } catch (Exception e) { 126 | } 127 | } 128 | 129 | public boolean getBooleanState(String key) { 130 | try { 131 | return this.mCarService.getBooleanState(key); 132 | } catch (Exception e) { 133 | return false; 134 | } 135 | } 136 | 137 | public byte getByteState(String key) { 138 | try { 139 | return this.mCarService.getByteState(key); 140 | } catch (Exception e) { 141 | return (byte) 0; 142 | } 143 | } 144 | 145 | public int getIntState(String key) { 146 | try { 147 | return this.mCarService.getIntState(key); 148 | } catch (Exception e) { 149 | return 0; 150 | } 151 | } 152 | 153 | public String getStringState(String key) { 154 | try { 155 | return this.mCarService.getStringState(key); 156 | } catch (Exception e) { 157 | return null; 158 | } 159 | } 160 | 161 | public byte[] getByteArrayState(String key) { 162 | try { 163 | return this.mCarService.getByteArrayState(key); 164 | } catch (Exception e) { 165 | return null; 166 | } 167 | } 168 | 169 | public int[] getIntArrayState(String key) { 170 | try { 171 | return this.mCarService.getIntArrayState(key); 172 | } catch (Exception e) { 173 | return null; 174 | } 175 | } 176 | 177 | public String[] getStringArrayState(String key) { 178 | try { 179 | return this.mCarService.getStringArrayState(key); 180 | } catch (Exception e) { 181 | return null; 182 | } 183 | } 184 | 185 | public void setParameters(String par) { 186 | try { 187 | this.mCarService.setParameters(par); 188 | } catch (Exception e) { 189 | } 190 | } 191 | 192 | public String getParameters(String par) { 193 | try { 194 | return this.mCarService.getParameters(par); 195 | } catch (Exception e) { 196 | return null; 197 | } 198 | } 199 | 200 | public void putDataChanage(String type, String state) { 201 | try { 202 | this.mCarService.putDataChanage(type, state); 203 | } catch (Exception e) { 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /app/src/main/java/android/microntek/ICarManageCallback.java: -------------------------------------------------------------------------------- 1 | package android.microntek; 2 | 3 | import android.os.Binder; 4 | import android.os.Bundle; 5 | import android.os.IBinder; 6 | import android.os.IInterface; 7 | import android.os.Parcel; 8 | import android.os.RemoteException; 9 | 10 | public interface ICarManageCallback extends IInterface { 11 | 12 | public static abstract class Stub extends Binder implements ICarManageCallback { 13 | private static final String DESCRIPTOR = "android.microntek.ICarManageCallback"; 14 | static final int TRANSACTION_onStatusChanged = 1; 15 | 16 | private static class Proxy implements ICarManageCallback { 17 | private IBinder mRemote; 18 | 19 | Proxy(IBinder remote) { 20 | this.mRemote = remote; 21 | } 22 | 23 | public IBinder asBinder() { 24 | return this.mRemote; 25 | } 26 | 27 | public String getInterfaceDescriptor() { 28 | return Stub.DESCRIPTOR; 29 | } 30 | 31 | public void onStatusChanged(String type, Bundle bundle) throws RemoteException { 32 | Parcel _data = Parcel.obtain(); 33 | Parcel _reply = Parcel.obtain(); 34 | try { 35 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 36 | _data.writeString(type); 37 | if (bundle != null) { 38 | _data.writeInt(Stub.TRANSACTION_onStatusChanged); 39 | bundle.writeToParcel(_data, 0); 40 | } else { 41 | _data.writeInt(0); 42 | } 43 | this.mRemote.transact(Stub.TRANSACTION_onStatusChanged, _data, _reply, 0); 44 | _reply.readException(); 45 | } finally { 46 | _reply.recycle(); 47 | _data.recycle(); 48 | } 49 | } 50 | } 51 | 52 | public Stub() { 53 | attachInterface(this, DESCRIPTOR); 54 | } 55 | 56 | public static ICarManageCallback asInterface(IBinder obj) { 57 | if (obj == null) { 58 | return null; 59 | } 60 | IInterface iin = obj.queryLocalInterface(DESCRIPTOR); 61 | if (iin == null || !(iin instanceof ICarManageCallback)) { 62 | return new Proxy(obj); 63 | } 64 | return (ICarManageCallback) iin; 65 | } 66 | 67 | public IBinder asBinder() { 68 | return this; 69 | } 70 | 71 | public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { 72 | switch (code) { 73 | case TRANSACTION_onStatusChanged /*1*/: 74 | Bundle bundle; 75 | data.enforceInterface(DESCRIPTOR); 76 | String _arg0 = data.readString(); 77 | if (data.readInt() != 0) { 78 | bundle = (Bundle) Bundle.CREATOR.createFromParcel(data); 79 | } else { 80 | bundle = null; 81 | } 82 | onStatusChanged(_arg0, bundle); 83 | reply.writeNoException(); 84 | return true; 85 | case IBinder.INTERFACE_TRANSACTION /*1598968902*/: 86 | reply.writeString(DESCRIPTOR); 87 | return true; 88 | default: 89 | return super.onTransact(code, data, reply, flags); 90 | } 91 | } 92 | } 93 | 94 | void onStatusChanged(String str, Bundle bundle) throws RemoteException; 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/android/microntek/ICarService.java: -------------------------------------------------------------------------------- 1 | package android.microntek; 2 | 3 | import android.os.Binder; 4 | import android.os.IBinder; 5 | import android.os.IInterface; 6 | import android.os.Parcel; 7 | import android.os.RemoteException; 8 | 9 | public interface ICarService extends IInterface { 10 | 11 | public static abstract class Stub extends Binder implements ICarService { 12 | private static final String DESCRIPTOR = "android.microntek.ICarService"; 13 | static final int TRANSACTION_getBooleanState = 8; 14 | static final int TRANSACTION_getByteArrayState = 12; 15 | static final int TRANSACTION_getByteState = 9; 16 | static final int TRANSACTION_getIntArrayState = 13; 17 | static final int TRANSACTION_getIntState = 10; 18 | static final int TRANSACTION_getParameters = 18; 19 | static final int TRANSACTION_getStringArrayState = 14; 20 | static final int TRANSACTION_getStringState = 11; 21 | static final int TRANSACTION_putBooleanState = 1; 22 | static final int TRANSACTION_putByteArraryState = 5; 23 | static final int TRANSACTION_putByteState = 2; 24 | static final int TRANSACTION_putDataChanage = 19; 25 | static final int TRANSACTION_putIntArraryState = 6; 26 | static final int TRANSACTION_putIntState = 3; 27 | static final int TRANSACTION_putStringArraryState = 7; 28 | static final int TRANSACTION_putStringState = 4; 29 | static final int TRANSACTION_registerCallback = 15; 30 | static final int TRANSACTION_setParameters = 17; 31 | static final int TRANSACTION_unregisterCallback = 16; 32 | 33 | private static class Proxy implements ICarService { 34 | private IBinder mRemote; 35 | 36 | Proxy(IBinder remote) { 37 | this.mRemote = remote; 38 | } 39 | 40 | public IBinder asBinder() { 41 | return this.mRemote; 42 | } 43 | 44 | public String getInterfaceDescriptor() { 45 | return Stub.DESCRIPTOR; 46 | } 47 | 48 | public void putBooleanState(String key, boolean value) throws RemoteException { 49 | int i = Stub.TRANSACTION_putBooleanState; 50 | Parcel _data = Parcel.obtain(); 51 | Parcel _reply = Parcel.obtain(); 52 | try { 53 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 54 | _data.writeString(key); 55 | if (!value) { 56 | i = 0; 57 | } 58 | _data.writeInt(i); 59 | this.mRemote.transact(Stub.TRANSACTION_putBooleanState, _data, _reply, 0); 60 | _reply.readException(); 61 | } finally { 62 | _reply.recycle(); 63 | _data.recycle(); 64 | } 65 | } 66 | 67 | public void putByteState(String key, byte value) throws RemoteException { 68 | Parcel _data = Parcel.obtain(); 69 | Parcel _reply = Parcel.obtain(); 70 | try { 71 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 72 | _data.writeString(key); 73 | _data.writeByte(value); 74 | this.mRemote.transact(Stub.TRANSACTION_putByteState, _data, _reply, 0); 75 | _reply.readException(); 76 | } finally { 77 | _reply.recycle(); 78 | _data.recycle(); 79 | } 80 | } 81 | 82 | public void putIntState(String key, int value) throws RemoteException { 83 | Parcel _data = Parcel.obtain(); 84 | Parcel _reply = Parcel.obtain(); 85 | try { 86 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 87 | _data.writeString(key); 88 | _data.writeInt(value); 89 | this.mRemote.transact(Stub.TRANSACTION_putIntState, _data, _reply, 0); 90 | _reply.readException(); 91 | } finally { 92 | _reply.recycle(); 93 | _data.recycle(); 94 | } 95 | } 96 | 97 | public void putStringState(String key, String value) throws RemoteException { 98 | Parcel _data = Parcel.obtain(); 99 | Parcel _reply = Parcel.obtain(); 100 | try { 101 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 102 | _data.writeString(key); 103 | _data.writeString(value); 104 | this.mRemote.transact(Stub.TRANSACTION_putStringState, _data, _reply, 0); 105 | _reply.readException(); 106 | } finally { 107 | _reply.recycle(); 108 | _data.recycle(); 109 | } 110 | } 111 | 112 | public void putByteArraryState(String key, byte[] value) throws RemoteException { 113 | Parcel _data = Parcel.obtain(); 114 | Parcel _reply = Parcel.obtain(); 115 | try { 116 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 117 | _data.writeString(key); 118 | _data.writeByteArray(value); 119 | this.mRemote.transact(Stub.TRANSACTION_putByteArraryState, _data, _reply, 0); 120 | _reply.readException(); 121 | } finally { 122 | _reply.recycle(); 123 | _data.recycle(); 124 | } 125 | } 126 | 127 | public void putIntArraryState(String key, int[] value) throws RemoteException { 128 | Parcel _data = Parcel.obtain(); 129 | Parcel _reply = Parcel.obtain(); 130 | try { 131 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 132 | _data.writeString(key); 133 | _data.writeIntArray(value); 134 | this.mRemote.transact(Stub.TRANSACTION_putIntArraryState, _data, _reply, 0); 135 | _reply.readException(); 136 | } finally { 137 | _reply.recycle(); 138 | _data.recycle(); 139 | } 140 | } 141 | 142 | public void putStringArraryState(String key, String[] value) throws RemoteException { 143 | Parcel _data = Parcel.obtain(); 144 | Parcel _reply = Parcel.obtain(); 145 | try { 146 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 147 | _data.writeString(key); 148 | _data.writeStringArray(value); 149 | this.mRemote.transact(Stub.TRANSACTION_putStringArraryState, _data, _reply, 0); 150 | _reply.readException(); 151 | } finally { 152 | _reply.recycle(); 153 | _data.recycle(); 154 | } 155 | } 156 | 157 | public boolean getBooleanState(String key) throws RemoteException { 158 | Parcel _data = Parcel.obtain(); 159 | Parcel _reply = Parcel.obtain(); 160 | try { 161 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 162 | _data.writeString(key); 163 | this.mRemote.transact(Stub.TRANSACTION_getBooleanState, _data, _reply, 0); 164 | _reply.readException(); 165 | boolean _result = _reply.readInt() != 0; 166 | _reply.recycle(); 167 | _data.recycle(); 168 | return _result; 169 | } catch (Throwable th) { 170 | _reply.recycle(); 171 | _data.recycle(); 172 | } 173 | 174 | return false; 175 | } 176 | 177 | public byte getByteState(String key) throws RemoteException { 178 | Parcel _data = Parcel.obtain(); 179 | Parcel _reply = Parcel.obtain(); 180 | try { 181 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 182 | _data.writeString(key); 183 | this.mRemote.transact(Stub.TRANSACTION_getByteState, _data, _reply, 0); 184 | _reply.readException(); 185 | byte _result = _reply.readByte(); 186 | return _result; 187 | } finally { 188 | _reply.recycle(); 189 | _data.recycle(); 190 | } 191 | } 192 | 193 | public int getIntState(String key) throws RemoteException { 194 | Parcel _data = Parcel.obtain(); 195 | Parcel _reply = Parcel.obtain(); 196 | try { 197 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 198 | _data.writeString(key); 199 | this.mRemote.transact(Stub.TRANSACTION_getIntState, _data, _reply, 0); 200 | _reply.readException(); 201 | int _result = _reply.readInt(); 202 | return _result; 203 | } finally { 204 | _reply.recycle(); 205 | _data.recycle(); 206 | } 207 | } 208 | 209 | public String getStringState(String key) throws RemoteException { 210 | Parcel _data = Parcel.obtain(); 211 | Parcel _reply = Parcel.obtain(); 212 | try { 213 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 214 | _data.writeString(key); 215 | this.mRemote.transact(Stub.TRANSACTION_getStringState, _data, _reply, 0); 216 | _reply.readException(); 217 | String _result = _reply.readString(); 218 | return _result; 219 | } finally { 220 | _reply.recycle(); 221 | _data.recycle(); 222 | } 223 | } 224 | 225 | public byte[] getByteArrayState(String key) throws RemoteException { 226 | Parcel _data = Parcel.obtain(); 227 | Parcel _reply = Parcel.obtain(); 228 | try { 229 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 230 | _data.writeString(key); 231 | this.mRemote.transact(Stub.TRANSACTION_getByteArrayState, _data, _reply, 0); 232 | _reply.readException(); 233 | byte[] _result = _reply.createByteArray(); 234 | return _result; 235 | } finally { 236 | _reply.recycle(); 237 | _data.recycle(); 238 | } 239 | } 240 | 241 | public int[] getIntArrayState(String key) throws RemoteException { 242 | Parcel _data = Parcel.obtain(); 243 | Parcel _reply = Parcel.obtain(); 244 | try { 245 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 246 | _data.writeString(key); 247 | this.mRemote.transact(Stub.TRANSACTION_getIntArrayState, _data, _reply, 0); 248 | _reply.readException(); 249 | int[] _result = _reply.createIntArray(); 250 | return _result; 251 | } finally { 252 | _reply.recycle(); 253 | _data.recycle(); 254 | } 255 | } 256 | 257 | public String[] getStringArrayState(String key) throws RemoteException { 258 | Parcel _data = Parcel.obtain(); 259 | Parcel _reply = Parcel.obtain(); 260 | try { 261 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 262 | _data.writeString(key); 263 | this.mRemote.transact(Stub.TRANSACTION_getStringArrayState, _data, _reply, 0); 264 | _reply.readException(); 265 | String[] _result = _reply.createStringArray(); 266 | return _result; 267 | } finally { 268 | _reply.recycle(); 269 | _data.recycle(); 270 | } 271 | } 272 | 273 | public void registerCallback(ICarManageCallback callback) throws RemoteException { 274 | IBinder iBinder = null; 275 | Parcel _data = Parcel.obtain(); 276 | Parcel _reply = Parcel.obtain(); 277 | try { 278 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 279 | if (callback != null) { 280 | iBinder = callback.asBinder(); 281 | } 282 | _data.writeStrongBinder(iBinder); 283 | this.mRemote.transact(Stub.TRANSACTION_registerCallback, _data, _reply, 0); 284 | _reply.readException(); 285 | } finally { 286 | _reply.recycle(); 287 | _data.recycle(); 288 | } 289 | } 290 | 291 | public void unregisterCallback(ICarManageCallback callback) throws RemoteException { 292 | IBinder iBinder = null; 293 | Parcel _data = Parcel.obtain(); 294 | Parcel _reply = Parcel.obtain(); 295 | try { 296 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 297 | if (callback != null) { 298 | iBinder = callback.asBinder(); 299 | } 300 | _data.writeStrongBinder(iBinder); 301 | this.mRemote.transact(Stub.TRANSACTION_unregisterCallback, _data, _reply, 0); 302 | _reply.readException(); 303 | } finally { 304 | _reply.recycle(); 305 | _data.recycle(); 306 | } 307 | } 308 | 309 | public int setParameters(String par) throws RemoteException { 310 | Parcel _data = Parcel.obtain(); 311 | Parcel _reply = Parcel.obtain(); 312 | try { 313 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 314 | _data.writeString(par); 315 | this.mRemote.transact(Stub.TRANSACTION_setParameters, _data, _reply, 0); 316 | _reply.readException(); 317 | int _result = _reply.readInt(); 318 | return _result; 319 | } finally { 320 | _reply.recycle(); 321 | _data.recycle(); 322 | } 323 | } 324 | 325 | public String getParameters(String par) throws RemoteException { 326 | Parcel _data = Parcel.obtain(); 327 | Parcel _reply = Parcel.obtain(); 328 | try { 329 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 330 | _data.writeString(par); 331 | this.mRemote.transact(Stub.TRANSACTION_getParameters, _data, _reply, 0); 332 | _reply.readException(); 333 | String _result = _reply.readString(); 334 | return _result; 335 | } finally { 336 | _reply.recycle(); 337 | _data.recycle(); 338 | } 339 | } 340 | 341 | public void putDataChanage(String type, String state) throws RemoteException { 342 | Parcel _data = Parcel.obtain(); 343 | Parcel _reply = Parcel.obtain(); 344 | try { 345 | _data.writeInterfaceToken(Stub.DESCRIPTOR); 346 | _data.writeString(type); 347 | _data.writeString(state); 348 | this.mRemote.transact(Stub.TRANSACTION_putDataChanage, _data, _reply, 0); 349 | _reply.readException(); 350 | } finally { 351 | _reply.recycle(); 352 | _data.recycle(); 353 | } 354 | } 355 | } 356 | 357 | public Stub() { 358 | attachInterface(this, DESCRIPTOR); 359 | } 360 | 361 | public static ICarService asInterface(IBinder obj) { 362 | if (obj == null) { 363 | return null; 364 | } 365 | IInterface iin = obj.queryLocalInterface(DESCRIPTOR); 366 | if (iin == null || !(iin instanceof ICarService)) { 367 | return new Proxy(obj); 368 | } 369 | return (ICarService) iin; 370 | } 371 | 372 | public IBinder asBinder() { 373 | return this; 374 | } 375 | 376 | public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { 377 | int _result; 378 | String _result2; 379 | switch (code) { 380 | case TRANSACTION_putBooleanState /*1*/: 381 | data.enforceInterface(DESCRIPTOR); 382 | putBooleanState(data.readString(), data.readInt() != 0); 383 | reply.writeNoException(); 384 | return true; 385 | case TRANSACTION_putByteState /*2*/: 386 | data.enforceInterface(DESCRIPTOR); 387 | putByteState(data.readString(), data.readByte()); 388 | reply.writeNoException(); 389 | return true; 390 | case TRANSACTION_putIntState /*3*/: 391 | data.enforceInterface(DESCRIPTOR); 392 | putIntState(data.readString(), data.readInt()); 393 | reply.writeNoException(); 394 | return true; 395 | case TRANSACTION_putStringState /*4*/: 396 | data.enforceInterface(DESCRIPTOR); 397 | putStringState(data.readString(), data.readString()); 398 | reply.writeNoException(); 399 | return true; 400 | case TRANSACTION_putByteArraryState /*5*/: 401 | data.enforceInterface(DESCRIPTOR); 402 | putByteArraryState(data.readString(), data.createByteArray()); 403 | reply.writeNoException(); 404 | return true; 405 | case TRANSACTION_putIntArraryState /*6*/: 406 | data.enforceInterface(DESCRIPTOR); 407 | putIntArraryState(data.readString(), data.createIntArray()); 408 | reply.writeNoException(); 409 | return true; 410 | case TRANSACTION_putStringArraryState /*7*/: 411 | data.enforceInterface(DESCRIPTOR); 412 | putStringArraryState(data.readString(), data.createStringArray()); 413 | reply.writeNoException(); 414 | return true; 415 | case TRANSACTION_getBooleanState /*8*/: 416 | data.enforceInterface(DESCRIPTOR); 417 | boolean _result3 = getBooleanState(data.readString()); 418 | reply.writeNoException(); 419 | reply.writeInt(_result3 ? TRANSACTION_putBooleanState : 0); 420 | return true; 421 | case TRANSACTION_getByteState /*9*/: 422 | data.enforceInterface(DESCRIPTOR); 423 | byte _result4 = getByteState(data.readString()); 424 | reply.writeNoException(); 425 | reply.writeByte(_result4); 426 | return true; 427 | case TRANSACTION_getIntState /*10*/: 428 | data.enforceInterface(DESCRIPTOR); 429 | _result = getIntState(data.readString()); 430 | reply.writeNoException(); 431 | reply.writeInt(_result); 432 | return true; 433 | case TRANSACTION_getStringState /*11*/: 434 | data.enforceInterface(DESCRIPTOR); 435 | _result2 = getStringState(data.readString()); 436 | reply.writeNoException(); 437 | reply.writeString(_result2); 438 | return true; 439 | case TRANSACTION_getByteArrayState /*12*/: 440 | data.enforceInterface(DESCRIPTOR); 441 | byte[] _result5 = getByteArrayState(data.readString()); 442 | reply.writeNoException(); 443 | reply.writeByteArray(_result5); 444 | return true; 445 | case TRANSACTION_getIntArrayState /*13*/: 446 | data.enforceInterface(DESCRIPTOR); 447 | int[] _result6 = getIntArrayState(data.readString()); 448 | reply.writeNoException(); 449 | reply.writeIntArray(_result6); 450 | return true; 451 | case TRANSACTION_getStringArrayState /*14*/: 452 | data.enforceInterface(DESCRIPTOR); 453 | String[] _result7 = getStringArrayState(data.readString()); 454 | reply.writeNoException(); 455 | reply.writeStringArray(_result7); 456 | return true; 457 | case TRANSACTION_registerCallback /*15*/: 458 | data.enforceInterface(DESCRIPTOR); 459 | registerCallback(android.microntek.ICarManageCallback.Stub.asInterface(data.readStrongBinder())); 460 | reply.writeNoException(); 461 | return true; 462 | case TRANSACTION_unregisterCallback /*16*/: 463 | data.enforceInterface(DESCRIPTOR); 464 | unregisterCallback(android.microntek.ICarManageCallback.Stub.asInterface(data.readStrongBinder())); 465 | reply.writeNoException(); 466 | return true; 467 | case TRANSACTION_setParameters /*17*/: 468 | data.enforceInterface(DESCRIPTOR); 469 | _result = setParameters(data.readString()); 470 | reply.writeNoException(); 471 | reply.writeInt(_result); 472 | return true; 473 | case TRANSACTION_getParameters /*18*/: 474 | data.enforceInterface(DESCRIPTOR); 475 | _result2 = getParameters(data.readString()); 476 | reply.writeNoException(); 477 | reply.writeString(_result2); 478 | return true; 479 | case TRANSACTION_putDataChanage /*19*/: 480 | data.enforceInterface(DESCRIPTOR); 481 | putDataChanage(data.readString(), data.readString()); 482 | reply.writeNoException(); 483 | return true; 484 | case IBinder.INTERFACE_TRANSACTION /*1598968902*/: 485 | reply.writeString(DESCRIPTOR); 486 | return true; 487 | default: 488 | return super.onTransact(code, data, reply, flags); 489 | } 490 | } 491 | } 492 | 493 | boolean getBooleanState(String str) throws RemoteException; 494 | 495 | byte[] getByteArrayState(String str) throws RemoteException; 496 | 497 | byte getByteState(String str) throws RemoteException; 498 | 499 | int[] getIntArrayState(String str) throws RemoteException; 500 | 501 | int getIntState(String str) throws RemoteException; 502 | 503 | String getParameters(String str) throws RemoteException; 504 | 505 | String[] getStringArrayState(String str) throws RemoteException; 506 | 507 | String getStringState(String str) throws RemoteException; 508 | 509 | void putBooleanState(String str, boolean z) throws RemoteException; 510 | 511 | void putByteArraryState(String str, byte[] bArr) throws RemoteException; 512 | 513 | void putByteState(String str, byte b) throws RemoteException; 514 | 515 | void putDataChanage(String str, String str2) throws RemoteException; 516 | 517 | void putIntArraryState(String str, int[] iArr) throws RemoteException; 518 | 519 | void putIntState(String str, int i) throws RemoteException; 520 | 521 | void putStringArraryState(String str, String[] strArr) throws RemoteException; 522 | 523 | void putStringState(String str, String str2) throws RemoteException; 524 | 525 | void registerCallback(ICarManageCallback iCarManageCallback) throws RemoteException; 526 | 527 | int setParameters(String str) throws RemoteException; 528 | 529 | void unregisterCallback(ICarManageCallback iCarManageCallback) throws RemoteException; 530 | } 531 | -------------------------------------------------------------------------------- /app/src/main/java/android/microntek/IRTable.java: -------------------------------------------------------------------------------- 1 | package android.microntek; 2 | 3 | public class IRTable { 4 | public static final int IR_AB = 363; 5 | public static final int IR_AF = 334; 6 | public static final int IR_AJX_ENTER = 313; 7 | public static final int IR_AJX_EXIT = 314; 8 | public static final int IR_AMS = 338; 9 | public static final int IR_AMS_RPT = 271; 10 | public static final int IR_ANGLE = 269; 11 | public static final int IR_ANSWER = 316; 12 | public static final int IR_ANSWER_HANGUP = 327; 13 | public static final int IR_APS = 306; 14 | public static final int IR_AUDIO = 282; 15 | public static final int IR_AUDIO_ST = 322; 16 | public static final int IR_AVIN = 319; 17 | public static final int IR_AVM = 342; 18 | public static final int IR_BACK = 308; 19 | public static final int IR_BACKLIGHT = 347; 20 | public static final int IR_BACKSPACE = 369; 21 | public static final int IR_BAND = 364; 22 | public static final int IR_BL = 332; 23 | public static final int IR_BLDOWN = 357; 24 | public static final int IR_BLUP = 356; 25 | public static final int IR_BL_ONOFF = 13; 26 | public static final int IR_BND = 349; 27 | public static final int IR_BND_SYS = 259; 28 | public static final int IR_BT = 304; 29 | public static final int IR_CAPTURESCREEN = 339; 30 | public static final int IR_CAR_INFO = 512; 31 | public static final int IR_CAR_SPEED = 367; 32 | public static final int IR_CLOCK = 359; 33 | public static final int IR_DIMMER = 325; 34 | public static final int IR_DISPLAY = 361; 35 | public static final int IR_DOWN = 268; 36 | public static final int IR_DSP = 360; 37 | public static final int IR_DTV = 320; 38 | public static final int IR_DVD = 296; 39 | public static final int IR_DVD_AUDIO = 354; 40 | public static final int IR_ECONNECT = 343; 41 | public static final int IR_EJECT = 295; 42 | public static final int IR_ENTER = 264; 43 | public static final int IR_ENTER_APS = 323; 44 | public static final int IR_EQ = 303; 45 | public static final int IR_EQS = 318; 46 | public static final int IR_FB = 301; 47 | public static final int IR_FCAM = 333; 48 | public static final int IR_FF = 302; 49 | public static final int IR_FUNC = 315; 50 | public static final int IR_GOTO = 294; 51 | public static final int IR_GPS = 305; 52 | public static final int IR_HANGUP = 317; 53 | public static final int IR_HOME = 310; 54 | public static final int IR_IPOD = 337; 55 | public static final int IR_LED = 358; 56 | public static final int IR_LEFT = 263; 57 | public static final int IR_LOC = 351; 58 | public static final int IR_LOC_RDM = 275; 59 | public static final int IR_LUD = 298; 60 | public static final int IR_MENU = 309; 61 | public static final int IR_MODE = 256; 62 | public static final int IR_MUSIC = 331; 63 | public static final int IR_MUTE = 258; 64 | public static final int IR_N0 = 292; 65 | public static final int IR_N1 = 283; 66 | public static final int IR_N10 = 293; 67 | public static final int IR_N2 = 284; 68 | public static final int IR_N3 = 285; 69 | public static final int IR_N4 = 286; 70 | public static final int IR_N5 = 287; 71 | public static final int IR_N6 = 288; 72 | public static final int IR_N7 = 289; 73 | public static final int IR_N8 = 290; 74 | public static final int IR_N9 = 291; 75 | public static final int IR_NEXT = 300; 76 | public static final int IR_NS = 346; 77 | public static final int IR_NX = 345; 78 | public static final int IR_OSD = 280; 79 | public static final int IR_PBC = 279; 80 | public static final int IR_PLAY_PAUSE = 257; 81 | public static final int IR_PLUS = 368; 82 | public static final int IR_PRESET = 329; 83 | public static final int IR_PREV = 299; 84 | public static final int IR_PRGM = 328; 85 | public static final int IR_PROG = 371; 86 | public static final int IR_PS = 324; 87 | public static final int IR_PWR = 2048; 88 | public static final int IR_RADIO = 297; 89 | public static final int IR_RADIO_BND = 353; 90 | public static final int IR_RDM = 352; 91 | public static final int IR_RECENT = 365; 92 | public static final int IR_RIGHT = 265; 93 | public static final int IR_RPT = 370; 94 | public static final int IR_SEEKDOWN = 276; 95 | public static final int IR_SEEKUP = 278; 96 | public static final int IR_SEL = 277; 97 | public static final int IR_SET = 321; 98 | public static final int IR_SETUP = 266; 99 | public static final int IR_SLOW = 270; 100 | public static final int IR_SPEECH = 326; 101 | public static final int IR_ST = 348; 102 | public static final int IR_STEP = 307; 103 | public static final int IR_STOP = 267; 104 | public static final int IR_ST_PROG = 272; 105 | public static final int IR_SUBT = 262; 106 | public static final int IR_SYNC_BT = 362; 107 | public static final int IR_SYS = 350; 108 | public static final int IR_TA = 335; 109 | public static final int IR_TITLE = 261; 110 | public static final int IR_TONE = 330; 111 | public static final int IR_TUNEDOWN = 311; 112 | public static final int IR_TUNEUP = 312; 113 | public static final int IR_UP = 260; 114 | public static final int IR_VIDEO = 336; 115 | public static final int IR_VOICE = 366; 116 | public static final int IR_VOLDOWN = 281; 117 | public static final int IR_VOLUP = 273; 118 | public static final int IR_VOL_SLIDE = 14; 119 | public static final int IR_YZE_ANSWER = 341; 120 | public static final int IR_YZE_CALL = 340; 121 | public static final int IR_YZS_SPEECH = 344; 122 | public static final int IR_ZOOM = 274; 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/android/microntek/MTCData.java: -------------------------------------------------------------------------------- 1 | package android.microntek; 2 | 3 | public class MTCData { 4 | public static final int MAX_BALANCE = 28; 5 | public static final int MAX_EQ = 20; 6 | public static final int af = 22; 7 | public static final int atvmode = 11; 8 | public static final int avinAudioOnly = 26; 9 | public static final int backgroundvideo = 17; 10 | public static final int backscreenMode = 29; 11 | public static final int backviewvol = 8; 12 | public static final int barbacklight = 16; 13 | public static final int bareject = 15; 14 | public static final int barvolume = 14; 15 | public static final int carLogoDisable = 27; 16 | public static final int carrecloc = 12; 17 | public static final int drvingsafe = 2; 18 | public static final int dvrphotodisable = 23; 19 | public static final int gpsbackvolume = 25; 20 | public static final int gpsmix = 5; 21 | public static final int gpsphonevol = 24; 22 | public static final int gpssmonitor = 3; 23 | public static final int gpsswitch = 4; 24 | public static final int gpstime = 13; 25 | public static final int instruction = 10; 26 | public static final int kernelConfig = 28; 27 | public static final int[][] music_stytle_data; 28 | public static final int[][] music_stytle_data9; 29 | public static final int musicautoplay = 6; 30 | public static final int muticamera = 1; 31 | public static final int nozhja = 9; 32 | public static final int otherui = 0; 33 | public static final int screenclock = 18; 34 | public static final int screenshootloc = 21; 35 | public static final int screentimeout = 19; 36 | public static final int time_24 = 7; 37 | public static final int videogesture = 20; 38 | 39 | static { 40 | int[][] iArr = new int[musicautoplay][]; 41 | iArr[otherui] = new int[]{screenclock, backviewvol, screenclock}; 42 | iArr[muticamera] = new int[]{atvmode, screenclock, nozhja}; 43 | iArr[drvingsafe] = new int[]{barbacklight, musicautoplay, backgroundvideo}; 44 | iArr[gpssmonitor] = new int[]{screenclock, musicautoplay, screenclock}; 45 | iArr[gpsswitch] = new int[]{instruction, instruction, instruction}; 46 | iArr[gpsmix] = new int[]{backviewvol, barbacklight, backviewvol}; 47 | music_stytle_data = iArr; 48 | iArr = new int[musicautoplay][]; 49 | iArr[otherui] = new int[]{videogesture, screenclock, barbacklight, nozhja, musicautoplay, nozhja, barbacklight, screenclock, videogesture}; 50 | iArr[muticamera] = new int[]{nozhja, atvmode, gpstime, backgroundvideo, videogesture, backgroundvideo, atvmode, nozhja, time_24}; 51 | iArr[drvingsafe] = new int[]{videogesture, barbacklight, carrecloc, instruction, musicautoplay, drvingsafe, barvolume, backgroundvideo, videogesture}; 52 | iArr[gpssmonitor] = new int[]{videogesture, screenclock, barbacklight, backviewvol, drvingsafe, backviewvol, barbacklight, screenclock, videogesture}; 53 | iArr[gpsswitch] = new int[]{instruction, instruction, instruction, instruction, instruction, instruction, instruction, instruction, instruction}; 54 | iArr[gpsmix] = new int[]{gpsmix, backviewvol, atvmode, barvolume, backgroundvideo, barvolume, atvmode, backviewvol, gpsmix}; 55 | music_stytle_data9 = iArr; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/AutoVolumeBooter.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | public class AutoVolumeBooter extends BroadcastReceiver { 8 | @Override 9 | public void onReceive(Context context, Intent intent) { 10 | Intent i = new Intent(context, VolumeService.class); 11 | context.startService(i); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/CanBusDriver.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.microntek.CarManager; 4 | import android.os.Handler; 5 | import android.util.Log; 6 | 7 | public class CanBusDriver { 8 | private static final String TAG = CanBusDriver.class.getSimpleName(); 9 | 10 | private static final int POLL_DELAY = 500; 11 | 12 | private CarManager carManager; 13 | private Handler handler; 14 | private Runnable runnable; 15 | 16 | public CanBusDriver() { 17 | carManager = new CarManager(); 18 | handler = new Handler(); 19 | runnable = new Runnable() { 20 | @Override 21 | public void run() { 22 | requestCarData(); 23 | handler.postDelayed(this, POLL_DELAY); 24 | } 25 | }; 26 | handler.postDelayed(runnable, POLL_DELAY); 27 | } 28 | 29 | public void stop() { 30 | handler.removeCallbacks(runnable); 31 | } 32 | 33 | public void setParams(String str) { 34 | Log.d(TAG, "Set Params: [" + str + "]"); 35 | this.carManager.setParameters(str); 36 | } 37 | 38 | public String getParams(String str) { 39 | Log.d(TAG, "Get Params: [" + str + "]"); 40 | return this.carManager.getParameters(str); 41 | } 42 | 43 | void requestCarData() { 44 | jt((byte)65, (byte)2); 45 | } 46 | 47 | /** voodoo incantation starts here **/ 48 | private void jt(byte b, byte b2) { 49 | ju((byte) -112, new byte[]{b, b2}, 2); 50 | } 51 | 52 | private void ju(byte b, byte[] bArr, int i) { 53 | int i2 = 0; 54 | byte[] bArr2 = new byte[(i + 4)]; 55 | bArr2[0] = (byte) 46; 56 | bArr2[1] = b; 57 | bArr2[2] = (byte) (i & 255); 58 | int i3 = (short) (bArr2[1] + bArr2[2]); 59 | while (i2 < i) { 60 | bArr2[i2 + 3] = bArr[i2]; 61 | i3 = (short) (i3 + bArr2[i2 + 3]); 62 | i2++; 63 | } 64 | bArr2[i + 3] = (byte) ((i3 & 255) ^ 255); 65 | jv(bArr2); 66 | } 67 | 68 | private void jv(byte[] bArr) { 69 | int length = bArr.length; 70 | String str = ""; 71 | for (int i = 0; i < length; i++) { 72 | str = str + jx(bArr[i] & 255); 73 | if (i < length - 1) { 74 | str = str + ","; 75 | } 76 | } 77 | setParams("canbus_rsp=" + str); 78 | } 79 | 80 | private String jx(int i) { 81 | int i2 = i / 10; 82 | int i3 = i % 10; 83 | return i2 == 0 ? "" + i3 : "" + i2 + i3; 84 | } 85 | 86 | /** voodoo incantation end here **/ 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.IntentFilter; 7 | import android.os.Bundle; 8 | import android.util.Log; 9 | 10 | public class CanBusReceiver extends BroadcastReceiver { 11 | 12 | private static final String TAG = CanBusReceiver.class.getSimpleName(); 13 | 14 | public static final String REV = "rev"; // engine RPM - int 15 | public static final String SPEED = "speed"; // speed km/h - double 16 | public static final String BATT = "batt"; // battery - double 17 | public static final String TEMP = "temp"; // temperature - double 18 | public static final String DIST = "dist"; // total tistance km - int 19 | public static final String DEBUG = "debug"; // debugging info - string 20 | 21 | int received = 0; 22 | 23 | interface Callback { 24 | void receiveCanBus(Bundle bundle); 25 | Context getContext(); 26 | } 27 | 28 | Callback callback; 29 | 30 | private CanBusReceiver(Callback callback) { 31 | this.callback = callback; 32 | } 33 | 34 | public static CanBusReceiver RegisterCarReceiver(Callback callback) { 35 | Context context = callback.getContext(); 36 | CanBusReceiver newCanBusReceiver = new CanBusReceiver(callback); 37 | context.registerReceiver(newCanBusReceiver, new IntentFilter("com.microntek.sync")); 38 | return newCanBusReceiver; 39 | } 40 | 41 | public static void UnregisterCarReceiver(CanBusReceiver oldCanBusReceiver) { 42 | oldCanBusReceiver.callback.getContext().unregisterReceiver(oldCanBusReceiver); 43 | } 44 | 45 | @Override 46 | public void onReceive(Context context, Intent intent) { 47 | Bundle bundle = new Bundle(); 48 | 49 | received++; 50 | Log.d(TAG, "Received: " + received); 51 | 52 | byte[] data = intent.getByteArrayExtra("syncdata"); 53 | 54 | StringBuilder debugStr = new StringBuilder(); 55 | debugStr.append("Received: ").append(received).append("\n"); 56 | debugStr.append("Action: ").append(intent.getAction()).append("\n"); 57 | if (data != null) { 58 | debugStr.append("Data Len: ").append(data.length).append("\n"); 59 | if (data.length > 0) { 60 | debugStr.append("Data: "); 61 | int i; 62 | for (i = 0; i < data.length - 1; ++i) { 63 | debugStr.append(data[i]).append(","); 64 | } 65 | debugStr.append(data[i]); 66 | } 67 | } 68 | bundle.putString(DEBUG, debugStr.toString()); 69 | 70 | if (data != null) { 71 | if (data.length > 13 && data[2] == 2) { 72 | 73 | int rev = (0xFF & data[3]) * 256 + (0xFF & data[4]); 74 | bundle.putInt(REV, rev); 75 | 76 | // don't allow erroneous high values when car is stopped 77 | // if RPM is 0 then speed will be set to 0 too so no loud surprises 78 | double speed = 0; 79 | if (rev > 0) { 80 | speed = ((0xFF & data[5]) * 256 + (0xFF & data[6])) * 0.01d; 81 | } 82 | bundle.putDouble(SPEED, speed); 83 | 84 | double battery = ((0xFF & data[7]) * 256 + (0xFF & data[8])) * 0.01d; 85 | bundle.putDouble(BATT, battery); 86 | 87 | double temp = (0xFF & data[9]) * 256 + (0xFF & data[10]); 88 | if (temp >= 32768) { 89 | temp -= 65536; 90 | } 91 | temp /= 10; 92 | bundle.putDouble(TEMP, temp); 93 | 94 | int distance = (0xFF & data[11]) * 65536 + (0xFF & data[12]) * 256 + (0xFF & data[13]); 95 | bundle.putInt(DIST, distance); 96 | 97 | } 98 | } 99 | 100 | callback.receiveCanBus(bundle); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/CarVolume.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.app.Activity; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | 9 | public class CarVolume { 10 | 11 | private static final String VOLUME_PARAMETER_NAME = "av_volume="; 12 | private static final String MUTE_PARAMETER_NAME = "av_mute="; 13 | private static final String MAX_VOLUME_PARAMETER_NAME = "cfg_maxvolume"; 14 | 15 | // public static final int DELAY = 500; 16 | 17 | boolean emulation = false; 18 | 19 | int emulatedVolume = 10; 20 | int emulatedMaxVolume = 35; 21 | 22 | /* 23 | Handler handler; 24 | Runnable runnable; 25 | */ 26 | 27 | BroadcastReceiver br; 28 | 29 | interface Callback { 30 | Activity getActivity(); 31 | void receiveVolume(int volume); 32 | CanBusDriver getCanBusDriver(); 33 | } 34 | 35 | Callback callback; 36 | 37 | public CarVolume(Callback callback) { 38 | this.callback = callback; 39 | } 40 | 41 | private void pollVolume() { 42 | int vol = getVolume(); 43 | callback.receiveVolume(vol); 44 | } 45 | 46 | public int getVolume() { 47 | if (emulation) { 48 | return emulatedVolume; 49 | } 50 | return android.provider.Settings.System.getInt(callback.getActivity().getContentResolver(),VOLUME_PARAMETER_NAME, emulatedVolume); 51 | } 52 | 53 | public int getMaxVolume() { 54 | if (emulation) { 55 | return emulatedMaxVolume; 56 | } 57 | return android.provider.Settings.System.getInt(callback.getActivity().getContentResolver(), MAX_VOLUME_PARAMETER_NAME, emulatedMaxVolume); 58 | } 59 | 60 | public void setVolume(int volume) { 61 | int maxVol = getMaxVolume(); 62 | if (volume > maxVol) { 63 | volume = maxVol; 64 | } 65 | if (volume < 0) { 66 | volume = 0; 67 | } 68 | if (emulation) { 69 | emulatedVolume = volume; 70 | return; 71 | } 72 | android.provider.Settings.System.putInt(callback.getActivity().getContentResolver(),VOLUME_PARAMETER_NAME, volume); 73 | 74 | if (paramVol) { 75 | if (callback.getCanBusDriver() != null) { 76 | int mtcVol = mtcGetRealVolume(volume, maxVol); 77 | callback.getCanBusDriver().setParams(VOLUME_PARAMETER_NAME + mtcVol); 78 | } 79 | } 80 | 81 | if (intentVol) { 82 | Intent intent = new Intent("com.microntek.VOLUME_CHANGED"); 83 | intent.putExtra("maxvolume", getMaxVolume()); 84 | intent.putExtra("volume", volume); 85 | intent.putExtra("threecats", true); 86 | callback.getActivity().sendBroadcast(intent); 87 | } 88 | } 89 | 90 | // ôóíêöèÿ èç android.microntek.service.MicrontekServer 91 | private int mtcGetRealVolume(int vol, int maxVol) 92 | { 93 | float perc = 100.0F * vol / maxVol; 94 | float att; 95 | if (perc < 20.0F) { 96 | att = perc * 3.0F / 2.0F; 97 | } else if (perc < 50.0F) { 98 | att = perc + 10.0F; 99 | } else { 100 | att = 20.0F + perc * 4.0F / 5.0F; 101 | } 102 | return (int)att; 103 | } 104 | 105 | public boolean paramVol = false; 106 | public boolean intentVol = false; 107 | 108 | public void start() { 109 | if (br == null) { 110 | br = new BroadcastReceiver() { 111 | @Override 112 | public void onReceive(Context context, Intent intent) { 113 | if (!intent.getBooleanExtra("threecats", false)) { 114 | int volume = intent.getIntExtra("volume", 5); 115 | callback.receiveVolume(volume); 116 | } 117 | } 118 | }; 119 | callback.getActivity().registerReceiver(br, new IntentFilter("com.microntek.VOLUME_CHANGED")); 120 | } 121 | 122 | /* 123 | if (handler == null) { 124 | handler = new Handler(); 125 | runnable = new Runnable() { 126 | @Override 127 | public void run() { 128 | pollVolume(); 129 | handler.postDelayed(this, DELAY); 130 | } 131 | }; 132 | handler.postDelayed(runnable, DELAY); 133 | } 134 | */ 135 | } 136 | 137 | public void stop() { 138 | if (br != null) { 139 | callback.getActivity().unregisterReceiver(br); 140 | br = null; 141 | } 142 | 143 | /* 144 | if (handler != null) { 145 | handler.removeCallbacks(runnable); 146 | handler = null; 147 | } 148 | */ 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.CheckBox; 9 | import android.widget.CompoundButton; 10 | import android.widget.ProgressBar; 11 | import android.widget.SeekBar; 12 | import android.widget.TextView; 13 | 14 | public class MainActivity extends Activity implements CanBusReceiver.Callback, CarVolume.Callback { 15 | 16 | public static final int MAX_REV = 5000; // RPM 17 | public static final int MAX_SPEED = 200; // km/h 18 | public static final int MAX_EFFECT = 11; // effect level 19 | 20 | private static final float REV_FACTOR = 1.0f; 21 | private static final float SPEED_FACTOR = 0.75f; 22 | 23 | private TextView debugReceiverView; 24 | private TextView debugDriverView; 25 | private TextView debugVolView; 26 | 27 | TextView revView; 28 | TextView speedView; 29 | TextView battView; 30 | TextView tempView; 31 | TextView distView; 32 | 33 | CheckBox checkBoxSend; 34 | CheckBox checkBoxReceive; 35 | CheckBox checkBoxParamVol; 36 | CheckBox checkBoxIntentVol; 37 | 38 | CanBusReceiver canBusReceiver; 39 | CanBusDriver canBusDriver; 40 | CarVolume carVolume; 41 | 42 | SeekBar revBar; 43 | boolean revBarChanging; 44 | SeekBar speedBar; 45 | boolean speedBarChanging; 46 | 47 | SeekBar effectBar; 48 | SeekBar volumeBar; 49 | boolean volumeBarChanging; 50 | ProgressBar staticVolumeBar; 51 | 52 | private int speed; 53 | private int rev; 54 | private int effect; 55 | private int volume; 56 | private int staticVolume; 57 | 58 | private int volMax; 59 | 60 | TextView effectView; 61 | TextView volumeView; 62 | TextView staticVolumeView; 63 | 64 | @Override 65 | protected void onCreate(Bundle savedInstanceState) { 66 | super.onCreate(savedInstanceState); 67 | setContentView(R.layout.main); 68 | 69 | carVolume = new CarVolume(this); 70 | 71 | debugReceiverView = (TextView) findViewById(R.id.debugReceiverView); 72 | debugDriverView = (TextView) findViewById(R.id.debugDriverView); 73 | revView = (TextView) findViewById(R.id.revView); 74 | speedView = (TextView) findViewById(R.id.speedView); 75 | battView = (TextView) findViewById(R.id.battView); 76 | tempView = (TextView) findViewById(R.id.tempView); 77 | distView = (TextView) findViewById(R.id.distView); 78 | 79 | checkBoxSend = (CheckBox) findViewById(R.id.checkBoxSend); 80 | checkBoxSend.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 81 | @Override 82 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 83 | switchSend(b); 84 | } 85 | }); 86 | 87 | checkBoxReceive = (CheckBox) findViewById(R.id.checkBoxReceive); 88 | checkBoxReceive.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 89 | @Override 90 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 91 | switchReceive(b); 92 | } 93 | }); 94 | 95 | checkBoxParamVol = (CheckBox) findViewById(R.id.checkBoxParamVol); 96 | checkBoxParamVol.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 97 | @Override 98 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 99 | carVolume.paramVol = b; 100 | } 101 | }); 102 | carVolume.paramVol = checkBoxParamVol.isChecked(); 103 | 104 | checkBoxIntentVol = (CheckBox) findViewById(R.id.checkBoxIntentVol); 105 | checkBoxIntentVol.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 106 | @Override 107 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 108 | carVolume.intentVol = b; 109 | } 110 | }); 111 | carVolume.intentVol = checkBoxIntentVol.isChecked(); 112 | 113 | revBar = (SeekBar) findViewById(R.id.revBar); 114 | revBar.setMax(MAX_REV); 115 | revBar.setProgress(rev); 116 | revBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 117 | @Override 118 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 119 | if (fromUser) { 120 | setRev(progress); 121 | } 122 | } 123 | 124 | @Override 125 | public void onStartTrackingTouch(SeekBar seekBar) { 126 | revBarChanging = true; 127 | } 128 | 129 | @Override 130 | public void onStopTrackingTouch(SeekBar seekBar) { 131 | revBarChanging = false; 132 | } 133 | }); 134 | 135 | speedBar = (SeekBar) findViewById(R.id.speedBar); 136 | speedBar.setMax(MAX_SPEED); 137 | speedBar.setProgress(speed); 138 | speedBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 139 | @Override 140 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 141 | if (fromUser) { 142 | setSpeed(progress); 143 | } 144 | } 145 | 146 | @Override 147 | public void onStartTrackingTouch(SeekBar seekBar) { 148 | speedBarChanging = true; 149 | } 150 | 151 | @Override 152 | public void onStopTrackingTouch(SeekBar seekBar) { 153 | speedBarChanging = false; 154 | } 155 | }); 156 | 157 | effect = getSharedPreferences("main", 0).getInt("effect", 0); 158 | 159 | effectBar = (SeekBar) findViewById(R.id.effectBar); 160 | effectBar.setMax(MAX_EFFECT); 161 | effectBar.setProgress(effect); 162 | effectBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 163 | @Override 164 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 165 | setEffect(progress); 166 | } 167 | 168 | @Override 169 | public void onStartTrackingTouch(SeekBar seekBar) { 170 | } 171 | 172 | @Override 173 | public void onStopTrackingTouch(SeekBar seekBar) { 174 | getSharedPreferences("main", 0).edit().putInt("effect", getEffect()).apply(); 175 | } 176 | }); 177 | 178 | effectView = (TextView) findViewById(R.id.effectView); 179 | 180 | 181 | volumeBar = (SeekBar) findViewById(R.id.volumeBar); 182 | volumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 183 | @Override 184 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 185 | if (fromUser) { 186 | setVolume(progress, true); 187 | } 188 | } 189 | 190 | @Override 191 | public void onStartTrackingTouch(SeekBar seekBar) { 192 | volumeBarChanging = true; 193 | } 194 | 195 | @Override 196 | public void onStopTrackingTouch(SeekBar seekBar) { 197 | volumeBarChanging = false; 198 | } 199 | }); 200 | 201 | volumeView = (TextView) findViewById(R.id.volumeView); 202 | 203 | staticVolumeBar = (ProgressBar) findViewById(R.id.staticVolumeBar); 204 | 205 | staticVolumeView = (TextView) findViewById(R.id.staticVolumeView); 206 | 207 | volMax = carVolume.getMaxVolume(); 208 | volume = carVolume.getVolume(); 209 | 210 | volumeBar.setMax(volMax); 211 | volumeBar.setProgress(volume); 212 | volumeView.setText("Volume: " + volume + " / " + volMax); 213 | 214 | staticVolumeBar.setMax(volMax); 215 | staticVolumeBar.setProgress(staticVolume); 216 | staticVolumeView.setText("Static Volume: " + staticVolume); 217 | 218 | debugVolView = (TextView) findViewById(R.id.debugVolView); 219 | } 220 | 221 | private void switchSend(boolean on) { 222 | if (on) { 223 | if (canBusDriver == null) { 224 | canBusDriver = new CanBusDriver(); 225 | } 226 | } else { 227 | if (canBusDriver != null) { 228 | canBusDriver.stop(); 229 | canBusDriver = null; 230 | } 231 | } 232 | } 233 | 234 | private void switchReceive(boolean on) { 235 | if (on) { 236 | if (canBusReceiver == null) { 237 | canBusReceiver = CanBusReceiver.RegisterCarReceiver(this); 238 | } 239 | } else { 240 | if (canBusReceiver != null) { 241 | CanBusReceiver.UnregisterCarReceiver(canBusReceiver); 242 | canBusReceiver = null; 243 | } 244 | } 245 | } 246 | 247 | @Override 248 | protected void onStart() { 249 | super.onStart(); 250 | switchSend(checkBoxSend.isChecked()); 251 | switchReceive(checkBoxReceive.isChecked()); 252 | carVolume.start(); 253 | } 254 | 255 | @Override 256 | protected void onStop() { 257 | super.onStop(); 258 | switchSend(false); 259 | switchReceive(false); 260 | carVolume.stop(); 261 | } 262 | 263 | @Override 264 | public void receiveCanBus(Bundle bundle) { 265 | String debug = bundle.getString(CanBusReceiver.DEBUG); 266 | if (debug != null) { 267 | debugReceiverView.setText(debug); 268 | } 269 | int rev = bundle.getInt(CanBusReceiver.REV, Integer.MIN_VALUE); 270 | if (rev != Integer.MIN_VALUE) { 271 | if (!revBarChanging) { 272 | setRev(rev); 273 | } 274 | } 275 | double speed = bundle.getDouble(CanBusReceiver.SPEED, Double.MIN_VALUE); 276 | if (speed != Double.MIN_VALUE) { 277 | if (!speedBarChanging) { 278 | setSpeed((int) speed); 279 | } 280 | } 281 | double batt = bundle.getDouble(CanBusReceiver.BATT, Double.MIN_VALUE); 282 | if (batt != Double.MIN_VALUE) { 283 | battView.setText("Battery: " + String.format("%.2f", batt) + " V"); 284 | } 285 | double temp = bundle.getDouble(CanBusReceiver.TEMP, Double.MIN_VALUE); 286 | if (temp != Double.MIN_VALUE) { 287 | tempView.setText("Temperature: " + String.format("%.1f", temp) + " C"); 288 | } 289 | int dist = bundle.getInt(CanBusReceiver.DIST, Integer.MIN_VALUE); 290 | if (dist != Integer.MIN_VALUE) { 291 | distView.setText("Total Distance: " + dist + " km"); 292 | } 293 | } 294 | 295 | @Override 296 | public Context getContext() { 297 | return this; 298 | } 299 | 300 | @Override 301 | public Activity getActivity() { 302 | return this; 303 | } 304 | 305 | @Override 306 | public void receiveVolume(int volume) { 307 | debugVolView.setText("Received Volume: " + volume); 308 | setVolume(volume, false); 309 | } 310 | 311 | @Override 312 | public CanBusDriver getCanBusDriver() { 313 | return canBusDriver; 314 | } 315 | 316 | public void testBroadcastCan(View view) { 317 | Intent bi = new Intent(); 318 | bi.setAction("com.microntek.sync"); 319 | byte[] data = new byte[20]; 320 | for (int i = 0; i < 20; ++i) { 321 | if (i == 2) { 322 | data[i] = 2; 323 | } else { 324 | data[i] = (byte) (Math.random() * 256 - 128); 325 | } 326 | } 327 | bi.putExtra("syncdata", data); 328 | sendBroadcast(bi); 329 | } 330 | 331 | int volCycle = 3; 332 | 333 | public void testBroadcastVol(View view) { 334 | if (volCycle++ > 5) { 335 | volCycle = 3; 336 | } 337 | Intent bi = new Intent(); 338 | bi.setAction("com.microntek.VOLUME_CHANGED"); 339 | bi.putExtra("volumemax", 30); 340 | bi.putExtra("volume", volCycle); 341 | sendBroadcast(bi); 342 | } 343 | 344 | public void setSpeed(int speed) { 345 | this.speed = speed; 346 | speedView.setText("Speed: " + speed + " km/h"); 347 | speedBar.setProgress(speed); 348 | setDynamicVolume(); 349 | } 350 | 351 | public int getSpeed() { 352 | return speed; 353 | } 354 | 355 | public void setRev(int rev) { 356 | this.rev = rev; 357 | revView.setText("Engine Revs: " + rev + " RPM"); 358 | revBar.setProgress(rev); 359 | setDynamicVolume(); 360 | } 361 | 362 | public int getRev() { 363 | return rev; 364 | } 365 | 366 | public void setEffect(int effect) { 367 | this.effect = effect; 368 | effectView.setText("Effect Level: " + effect); 369 | setDynamicVolume(); 370 | } 371 | 372 | public int getEffect() { 373 | return effect; 374 | } 375 | 376 | public void setVolume(int volume, boolean toCar) { 377 | if (volume != this.volume) { 378 | this.volume = volume; 379 | volumeView.setText("Volume: " + volume + " / " + volMax); 380 | volumeBar.setProgress(volume); 381 | if (toCar) { 382 | carVolume.setVolume(volume); 383 | } 384 | calculateStaticVolume(); 385 | } 386 | } 387 | 388 | public void setDynamicVolume() { 389 | int revSteps = 0; 390 | int speedSteps = 0; 391 | int newVolume = 0; 392 | if (effect != 0) { 393 | revSteps = (int) (rev / (REV_FACTOR * MAX_REV / effect)); 394 | speedSteps = (int) (speed / (SPEED_FACTOR * MAX_SPEED / effect)); 395 | newVolume = staticVolume + revSteps + speedSteps; 396 | if (newVolume > volMax) { 397 | newVolume = volMax; 398 | } 399 | } else { 400 | newVolume = staticVolume; 401 | } 402 | setVolume(newVolume, true); 403 | } 404 | 405 | public void calculateStaticVolume() { 406 | int revSteps = 0; 407 | int speedSteps = 0; 408 | if (effect != 0) { 409 | revSteps = (int) (rev / (REV_FACTOR * MAX_REV / effect)); 410 | speedSteps = (int) (speed / (SPEED_FACTOR * MAX_SPEED / effect)); 411 | staticVolume = volume - revSteps - speedSteps; 412 | if (staticVolume < 0) { 413 | staticVolume = 0; 414 | } 415 | } else { 416 | staticVolume = volume; 417 | } 418 | staticVolumeView.setText("Static Volume: " + staticVolume + " Rev: " + revSteps + " Speed: " + speedSteps); 419 | staticVolumeBar.setProgress(staticVolume); 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/TestVolActivity.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.microntek.CarManager; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.EditText; 10 | import android.widget.TextView; 11 | 12 | public class TestVolActivity extends Activity { 13 | private static final String TAG = TestVolActivity.class.getName(); 14 | 15 | TextView textView; 16 | EditText editText; 17 | CarManager carManager; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_test_vol); 23 | textView = (TextView)findViewById(R.id.textView); 24 | editText = (EditText)findViewById(R.id.editText); 25 | 26 | carManager = new CarManager(); 27 | } 28 | 29 | int inputVal() { 30 | return Integer.parseInt(editText.getText().toString()); 31 | } 32 | 33 | 34 | public void getVolume(View view) { 35 | int i = android.provider.Settings.System.getInt(getContentResolver(), "av_volume=", -1); 36 | textView.setText("Get Vol: " + i); 37 | } 38 | 39 | public void getMaxVol(View view) { 40 | Log.d(TAG, "getMaxVol()"); 41 | int i = android.provider.Settings.System.getInt(getContentResolver(), "cfg_maxvolume", -1); 42 | textView.setText("Get Max Vol: " + i); 43 | } 44 | 45 | 46 | public void testBroadcastVol(View view) { 47 | Log.d(TAG, "testBroadcastVol()"); 48 | Intent bi = new Intent(); 49 | bi.setAction("com.microntek.VOLUME_CHANGED"); 50 | bi.putExtra("maxvolume", 30); 51 | bi.putExtra("volume", inputVal()); 52 | sendBroadcast(bi); 53 | } 54 | 55 | public void testBroadcastCommandSet(View view) { 56 | Log.d(TAG, "testBroadcastCommandSet()"); 57 | Intent bi = new Intent(); 58 | bi.setAction("com.microntek.VOLUME_SET"); 59 | bi.putExtra("volume", inputVal()); 60 | sendBroadcast(bi); 61 | } 62 | 63 | public void testBroadcastCommandUp(View view) { 64 | Log.d(TAG, "testBroadcastCommandUp()"); 65 | Intent bi = new Intent(); 66 | bi.setAction("com.microntek.VOLUME_SET"); 67 | bi.putExtra("type", "add"); 68 | sendBroadcast(bi); 69 | } 70 | 71 | public void testBroadcastCommandDown(View view) { 72 | Log.d(TAG, "testBroadcastCommandDown()"); 73 | Intent bi = new Intent(); 74 | bi.setAction("com.microntek.VOLUME_SET"); 75 | bi.putExtra("type", "sub"); 76 | sendBroadcast(bi); 77 | } 78 | 79 | public void testSetVolSys(View view) { 80 | Log.d(TAG, "testSetVolSys()"); 81 | android.provider.Settings.System.putInt(getContentResolver(), "av_volume=", inputVal()); 82 | } 83 | 84 | public void testSetVolMtcd(View view) { 85 | Log.d(TAG, "testSetVolMtcd()"); 86 | int mtcVol = mtcGetRealVolume(inputVal(), 30); 87 | carManager.setParameters("av_volume=" + mtcVol); 88 | } 89 | 90 | private int mtcGetRealVolume(int vol, int maxVol) 91 | { 92 | float perc = 100.0F * vol / maxVol; 93 | float att; 94 | if (perc < 20.0F) { 95 | att = perc * 3.0F / 2.0F; 96 | } else if (perc < 50.0F) { 97 | att = perc + 10.0F; 98 | } else { 99 | att = 20.0F + perc * 4.0F / 5.0F; 100 | } 101 | return (int)att; 102 | } 103 | 104 | 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/VolumeActivity.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.ServiceConnection; 8 | import android.os.Bundle; 9 | import android.os.IBinder; 10 | import android.view.View; 11 | import android.widget.CheckBox; 12 | import android.widget.CompoundButton; 13 | import android.widget.ProgressBar; 14 | import android.widget.SeekBar; 15 | import android.widget.TextView; 16 | 17 | public class VolumeActivity extends Activity implements VolumeService.UICallback { 18 | 19 | VolumeService mService = null; 20 | 21 | SeekBar seekBarEffect; 22 | TextView textViewEffect; 23 | TextView textViewEffectMax; 24 | 25 | ProgressBar progressBarVolume; 26 | TextView textViewVolume; 27 | TextView textViewVolumeMax; 28 | 29 | ProgressBar progressBarOutput; 30 | TextView textViewOutput; 31 | TextView textViewOutputMax; 32 | 33 | SeekBar seekBarRev; 34 | TextView textViewRev; 35 | TextView textViewRevMax; 36 | 37 | SeekBar seekBarSpeed; 38 | TextView textViewSpeed; 39 | TextView textViewSpeedMax; 40 | 41 | CheckBox checkBoxMonitor; 42 | 43 | @Override 44 | protected void onCreate(Bundle savedInstanceState) { 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.volume_activity); 47 | } 48 | 49 | void setupRevUI() { 50 | seekBarRev = (SeekBar)findViewById(R.id.seekBarRev); 51 | textViewRev = (TextView)findViewById(R.id.textViewRev); 52 | textViewRevMax = (TextView)findViewById(R.id.textViewRevMax); 53 | 54 | int rev = mService.getRev(); 55 | int revMax = mService.getRevMax(); 56 | 57 | seekBarRev.setMax(revMax); 58 | seekBarRev.setProgress(rev); 59 | textViewRev.setText("" + rev + " RPM"); 60 | textViewRevMax.setText("" + revMax + " RPM"); 61 | 62 | seekBarRev.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 63 | @Override 64 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 65 | if (fromUser) { 66 | textViewRev.setText("" + progress + " RPM"); 67 | mService.setRev(progress); 68 | } 69 | } 70 | 71 | @Override 72 | public void onStartTrackingTouch(SeekBar seekBar) { 73 | mService.setRevBarChanging(true); 74 | } 75 | 76 | @Override 77 | public void onStopTrackingTouch(SeekBar seekBar) { 78 | mService.setRevBarChanging(false); 79 | } 80 | }); 81 | } 82 | 83 | void setupSpeedUI() { 84 | seekBarSpeed = (SeekBar)findViewById(R.id.seekBarSpeed); 85 | textViewSpeed = (TextView)findViewById(R.id.textViewSpeed); 86 | textViewSpeedMax = (TextView)findViewById(R.id.textViewSpeedMax); 87 | 88 | int speed = mService.getSpeed(); 89 | int speedMax = mService.getSpeedMax(); 90 | 91 | seekBarSpeed.setMax(speedMax); 92 | seekBarSpeed.setProgress(speed); 93 | textViewSpeed.setText("" + speed + " km/h"); 94 | textViewSpeedMax.setText("" + speedMax + "km/h"); 95 | 96 | seekBarSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 97 | @Override 98 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 99 | if (fromUser) { 100 | textViewSpeed.setText("" + progress + " km/h"); 101 | mService.setSpeed(progress); 102 | } 103 | } 104 | 105 | @Override 106 | public void onStartTrackingTouch(SeekBar seekBar) { 107 | mService.setSpeedBarChanging(true); 108 | } 109 | 110 | @Override 111 | public void onStopTrackingTouch(SeekBar seekBar) { 112 | mService.setSpeedBarChanging(false); 113 | } 114 | }); 115 | } 116 | 117 | void setupVolumeUI() { 118 | progressBarVolume = (ProgressBar)findViewById(R.id.progressBarVolume); 119 | textViewVolume = (TextView)findViewById(R.id.textViewVolume); 120 | textViewVolumeMax = (TextView)findViewById(R.id.textViewVolumeMax); 121 | 122 | int volume = mService.getVolume(); 123 | int volumeMax = mService.getVolumeMax(); 124 | 125 | progressBarVolume.setMax(volumeMax); 126 | progressBarVolume.setProgress(volume); 127 | textViewVolume.setText("" + volume); 128 | textViewVolumeMax.setText("" + volumeMax); 129 | } 130 | 131 | void setupOutputUI() { 132 | progressBarOutput = (ProgressBar)findViewById(R.id.progressBarOutput); 133 | textViewOutput = (TextView)findViewById(R.id.textViewOutput); 134 | textViewOutputMax = (TextView)findViewById(R.id.textViewOutputMax); 135 | 136 | int volume = mService.getVolume(); 137 | int volumeMax = mService.getVolumeMax(); 138 | 139 | int output = VolumeService.mtcGetRealVolume(volume, volumeMax); 140 | 141 | progressBarOutput.setMax(100); 142 | progressBarOutput.setProgress(output); 143 | textViewOutput.setText("" + output + " %"); 144 | textViewOutputMax.setText("100 %"); 145 | } 146 | 147 | void setupEffectUI() { 148 | seekBarEffect = (SeekBar)findViewById(R.id.seekBarEffect); 149 | textViewEffect = (TextView)findViewById(R.id.textViewEffect); 150 | textViewEffectMax = (TextView)findViewById(R.id.textViewEffectMax); 151 | 152 | seekBarEffect.setMax(mService.getEffectMax()); 153 | seekBarEffect.setProgress(mService.getEffect()); 154 | textViewEffect.setText("" + mService.getEffect()); 155 | textViewEffectMax.setText("" + mService.getEffectMax()); 156 | 157 | seekBarEffect.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 158 | @Override 159 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 160 | mService.setEffect(progress); 161 | textViewEffect.setText("" + progress); 162 | Intent i = new Intent(VolumeActivity.this, VolumeService.class); 163 | startService(i); 164 | } 165 | 166 | @Override 167 | public void onStartTrackingTouch(SeekBar seekBar) { 168 | 169 | } 170 | 171 | @Override 172 | public void onStopTrackingTouch(SeekBar seekBar) { 173 | 174 | } 175 | }); 176 | 177 | Intent i = new Intent(VolumeActivity.this, VolumeService.class); 178 | startService(i); 179 | } 180 | 181 | void setupMonitorUI() { 182 | checkBoxMonitor = (CheckBox)findViewById(R.id.checkBoxMonitor); 183 | checkBoxMonitor.setChecked(mService.getMonitor()); 184 | checkBoxMonitor.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 185 | @Override 186 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 187 | mService.setMonitor(isChecked); 188 | } 189 | }); 190 | } 191 | 192 | @Override 193 | protected void onStart() { 194 | super.onStart(); 195 | Intent intent = new Intent(this, VolumeService.class); 196 | bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 197 | } 198 | 199 | @Override 200 | protected void onStop() { 201 | super.onStop(); 202 | if (mService != null) { 203 | mService.unregister(); 204 | unbindService(mConnection); 205 | } 206 | } 207 | 208 | @Override 209 | protected void onDestroy() { 210 | super.onDestroy(); 211 | mConnection = null; 212 | } 213 | 214 | private ServiceConnection mConnection = new ServiceConnection() { 215 | @Override 216 | public void onServiceConnected(ComponentName name, IBinder binder) { 217 | mService = ((VolumeService.VolumeBinder)binder).getService(); 218 | 219 | setupEffectUI(); 220 | setupVolumeUI(); 221 | setupOutputUI(); 222 | setupRevUI(); 223 | setupSpeedUI(); 224 | setupMonitorUI(); 225 | 226 | mService.register(VolumeActivity.this); 227 | } 228 | 229 | @Override 230 | public void onServiceDisconnected(ComponentName name) { 231 | mService = null; 232 | } 233 | }; 234 | 235 | @Override 236 | public void updateVolume(int volume, int volumeMax) { 237 | progressBarVolume.setMax(volumeMax); 238 | progressBarVolume.setProgress(volume); 239 | textViewVolume.setText("" + volume); 240 | textViewVolumeMax.setText("" + volumeMax); 241 | } 242 | 243 | @Override 244 | public void updateOutput(int output) { 245 | progressBarOutput.setProgress(output); 246 | textViewOutput.setText("" + output + " %"); 247 | } 248 | 249 | @Override 250 | public void updateSpeed(int speed) { 251 | seekBarSpeed.setProgress(speed); 252 | textViewSpeed.setText("" + speed + " km/h"); 253 | } 254 | 255 | @Override 256 | public void updateRev(int rev) { 257 | seekBarRev.setProgress(rev); 258 | textViewRev.setText("" + rev + " RPM"); 259 | } 260 | 261 | /////////// ----- TEST HERE 262 | 263 | int volCycle = 3; 264 | 265 | public void testBroadcastVol(View view) { 266 | if (volCycle++ > 5) { 267 | volCycle = 3; 268 | } 269 | Intent bi = new Intent(); 270 | bi.setAction("com.microntek.VOLUME_CHANGED"); 271 | bi.putExtra("volumemax", 30); 272 | bi.putExtra("volume", volCycle); 273 | sendBroadcast(bi); 274 | } 275 | 276 | public void testBroadcastCan(View view) { 277 | Intent bi = new Intent(); 278 | bi.setAction("com.microntek.sync"); 279 | byte[] data = new byte[20]; 280 | for (int i = 0; i < 20; ++i) { 281 | if (i == 2) { 282 | data[i] = 2; 283 | } else { 284 | data[i] = (byte) (Math.random() * 256 - 128); 285 | } 286 | } 287 | bi.putExtra("syncdata", data); 288 | sendBroadcast(bi); 289 | } 290 | 291 | 292 | 293 | } 294 | -------------------------------------------------------------------------------- /app/src/main/java/com/microntek/threecats/autovolume/VolumeService.java: -------------------------------------------------------------------------------- 1 | package com.microntek.threecats.autovolume; 2 | 3 | import android.app.Service; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.graphics.PixelFormat; 9 | import android.microntek.CarManager; 10 | import android.os.Binder; 11 | import android.os.Bundle; 12 | import android.os.Handler; 13 | import android.os.IBinder; 14 | import android.provider.Settings; 15 | import android.util.Log; 16 | import android.view.Gravity; 17 | import android.view.LayoutInflater; 18 | import android.view.View; 19 | import android.view.WindowManager; 20 | import android.widget.ImageView; 21 | import android.widget.TextView; 22 | 23 | public class VolumeService extends Service implements CanBusReceiver.Callback { 24 | private static final int MAX_REV = 5000; // RPM 25 | private static final int MAX_SPEED = 200; // km/h 26 | private static final int MAX_EFFECT = 9; // effect level 27 | 28 | private static final float REV_FACTOR = 2.0f; 29 | private static final float SPEED_FACTOR = 0.75f; 30 | private static final float EFFECT_AMP = 6.0f; 31 | private static final int TOLERANCE = 1; // tolerance in output volume 32 | 33 | private static final String VOLUME_PARAMETER_NAME = "av_volume="; 34 | private static final String MUTE_PARAMETER_NAME = "av_mute="; 35 | private static final String MAX_VOLUME_PARAMETER_NAME = "cfg_maxvolume="; 36 | private static final String VOLUME_CHANGED = "com.microntek.VOLUME_CHANGED"; 37 | private static final String TAG = VolumeService.class.getSimpleName(); 38 | 39 | private CarManager carManager = null; 40 | private BroadcastReceiver volumeReceiver = null; 41 | private CanBusReceiver canBusReceiver; 42 | private CanBusDriver canBusDriver; 43 | 44 | private int rev; 45 | private int speed; 46 | private boolean revBarChanging; 47 | private boolean speedBarChanging; 48 | 49 | public int getEffect() { 50 | return effect; 51 | } 52 | 53 | public void setEffect(int effect) { 54 | this.effect = effect; 55 | getSharedPreferences("main", 0).edit().putInt("effect", effect).apply(); 56 | resetHysteresis(); 57 | setDynamicOutput(getVolume(), getVolumeMax()); 58 | } 59 | 60 | int effect; 61 | 62 | public boolean getMonitor() { 63 | return monitor; 64 | } 65 | 66 | public void setMonitor(boolean monitor) { 67 | this.monitor = monitor; 68 | getSharedPreferences("main", 0).edit().putBoolean("monitor", monitor).apply(); 69 | } 70 | 71 | boolean monitor; 72 | 73 | public int getEffectMax() { 74 | return MAX_EFFECT; 75 | } 76 | 77 | public boolean getMute() { 78 | return "true".equals(carManager.getParameters(MUTE_PARAMETER_NAME)); 79 | } 80 | 81 | public int getVolume() { 82 | return Settings.System.getInt(getContentResolver(),VOLUME_PARAMETER_NAME, 0); 83 | } 84 | 85 | public int getVolumeMax() { 86 | return Settings.System.getInt(getContentResolver(),MAX_VOLUME_PARAMETER_NAME, 30); 87 | } 88 | 89 | public int getRev() { 90 | return rev; 91 | } 92 | 93 | public int getSpeed() { 94 | return speed; 95 | } 96 | 97 | public int getRevMax() { 98 | return MAX_REV; 99 | } 100 | 101 | public int getSpeedMax() { 102 | return MAX_SPEED; 103 | } 104 | 105 | private int calculateGain() { 106 | if (effect == 0) { 107 | return 0; 108 | } else { 109 | int revSteps = (int) (rev / (REV_FACTOR * MAX_REV / effect / EFFECT_AMP)); 110 | int speedSteps = (int) (speed / (SPEED_FACTOR * MAX_SPEED / effect / EFFECT_AMP)); 111 | return revSteps + speedSteps; 112 | } 113 | } 114 | 115 | @Override 116 | public void receiveCanBus(Bundle bundle) { 117 | int rev = bundle.getInt(CanBusReceiver.REV, Integer.MIN_VALUE); 118 | if (rev != Integer.MIN_VALUE) { 119 | if (!revBarChanging) { 120 | if (muiCallback != null) { 121 | muiCallback.updateRev(this.rev); 122 | } 123 | setRev(rev); 124 | } 125 | } 126 | double speed = bundle.getDouble(CanBusReceiver.SPEED, Double.MIN_VALUE); 127 | if (speed != Double.MIN_VALUE) { 128 | if (!speedBarChanging) { 129 | if (muiCallback != null) { 130 | muiCallback.updateSpeed(this.speed); 131 | } 132 | setSpeed((int) speed); 133 | } 134 | } 135 | } 136 | 137 | @Override 138 | public Context getContext() { 139 | return this; 140 | } 141 | 142 | public void setRevBarChanging(boolean revBarChanging) { 143 | this.revBarChanging = revBarChanging; 144 | } 145 | 146 | public void setSpeedBarChanging(boolean speedBarChanging) { 147 | this.speedBarChanging = speedBarChanging; 148 | } 149 | 150 | public void setSpeed(int speed) { 151 | this.speed = speed; 152 | setDynamicOutput(getVolume(), getVolumeMax()); 153 | } 154 | 155 | public void setRev(int rev) { 156 | this.rev = rev; 157 | setDynamicOutput(getVolume(), getVolumeMax()); 158 | } 159 | 160 | class VolumeBinder extends Binder { 161 | VolumeService getService() { 162 | return VolumeService.this; 163 | } 164 | } 165 | 166 | private final IBinder mBinder = new VolumeBinder(); 167 | 168 | @Override 169 | public int onStartCommand(Intent intent, int flags, int startId) { 170 | if (effect == 0) { 171 | stopSelf(); 172 | } 173 | return START_STICKY; 174 | } 175 | 176 | @Override 177 | public IBinder onBind(Intent intent) { 178 | return mBinder; 179 | } 180 | 181 | @Override 182 | public void onCreate() { 183 | super.onCreate(); 184 | 185 | Log.d(TAG, "Service is UP!"); 186 | 187 | effect = getSharedPreferences("main", 0).getInt("effect", 0); 188 | monitor = getSharedPreferences("main", 0).getBoolean("monitor", false); 189 | 190 | volumeReceiver = new BroadcastReceiver() { 191 | @Override 192 | public void onReceive(Context context, Intent intent) { 193 | int volume = intent.getIntExtra("volume", 0); 194 | int volumeMax = intent.getIntExtra("volumemax", 30); 195 | if (muiCallback != null) { 196 | muiCallback.updateVolume(volume, volumeMax); 197 | } 198 | setDynamicOutput(volume, volumeMax); 199 | } 200 | }; 201 | registerReceiver(volumeReceiver, new IntentFilter(VOLUME_CHANGED)); 202 | 203 | carManager = new CarManager(); 204 | 205 | canBusReceiver = CanBusReceiver.RegisterCarReceiver(this); 206 | 207 | canBusDriver = new CanBusDriver(); 208 | 209 | initOVerlay(); 210 | } 211 | 212 | @Override 213 | public void onDestroy() { 214 | super.onDestroy(); 215 | 216 | Log.d(TAG, "Service is DOWN!"); 217 | 218 | unregisterReceiver(volumeReceiver); 219 | 220 | CanBusReceiver.UnregisterCarReceiver(canBusReceiver); 221 | 222 | canBusDriver.stop(); 223 | 224 | h.removeCallbacks(r); 225 | } 226 | 227 | interface UICallback { 228 | void updateVolume(int volume, int volumeMax); 229 | void updateOutput(int output); 230 | void updateSpeed(int speed); 231 | void updateRev(int rev); 232 | } 233 | 234 | UICallback muiCallback = null; 235 | 236 | public void register(UICallback uiCallback) { 237 | muiCallback = uiCallback; 238 | resetHysteresis(); 239 | setDynamicOutput(getVolume(), getVolumeMax()); 240 | } 241 | 242 | public void unregister() { 243 | muiCallback = null; 244 | } 245 | 246 | public static int mtcGetRealVolume(int vol, int maxVol) 247 | { 248 | float perc = 100.0F * vol / maxVol; 249 | float att; 250 | if (perc < 20.0F) { 251 | att = perc * 3.0F / 2.0F; 252 | } else if (perc < 50.0F) { 253 | att = perc + 10.0F; 254 | } else { 255 | att = 20.0F + perc * 4.0F / 5.0F; 256 | } 257 | return (int)att; 258 | } 259 | 260 | void setDynamicOutput(int volume, int volumeMax) { 261 | if (!getMute()) { 262 | int output = mtcGetRealVolume(volume, volumeMax); 263 | int gain = calculateGain(); 264 | output += gain; 265 | if (output > 100) { 266 | output = 100; 267 | } 268 | setOutput(output); 269 | } 270 | } 271 | 272 | View overlayView; 273 | TextView overlayText; 274 | ImageView overlayUp; 275 | ImageView overlayDown; 276 | WindowManager.LayoutParams overlayParams; 277 | boolean overlayOn; 278 | WindowManager wm; 279 | Runnable r; 280 | Handler h = new Handler(); 281 | private static final int OVERLAY_TIME = 1000; 282 | 283 | void initOVerlay() { 284 | LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(LAYOUT_INFLATER_SERVICE); 285 | overlayView = inflater.inflate(R.layout.overlay, null, false); 286 | overlayText = (TextView)overlayView.findViewById(R.id.overlayText); 287 | overlayUp = (ImageView)overlayView.findViewById(R.id.overlayUp); 288 | overlayDown = (ImageView)overlayView.findViewById(R.id.overlayDown); 289 | 290 | overlayParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); 291 | overlayParams.alpha = 0.7F; 292 | overlayParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; 293 | overlayParams.x = 0; 294 | overlayParams.y = 0; 295 | overlayParams.width = 120; 296 | overlayParams.height = 120; 297 | 298 | wm = (WindowManager)getSystemService(WINDOW_SERVICE); 299 | 300 | r = new Runnable() { 301 | @Override 302 | public void run() { 303 | if (overlayOn) { 304 | wm.removeView(overlayView); 305 | overlayOn = false; 306 | } 307 | } 308 | 309 | }; 310 | 311 | } 312 | 313 | void showOverlay() { 314 | if (!overlayOn) { 315 | overlayOn = true; 316 | wm.addView(overlayView, overlayParams); 317 | } 318 | overlayText.setText("" + currentOutput + "%"); 319 | if (lastOutputDelta == 0) { 320 | overlayUp.setVisibility(View.INVISIBLE); 321 | overlayDown.setVisibility(View.INVISIBLE); 322 | } else if (lastOutputDelta > 0){ 323 | overlayUp.setVisibility(View.VISIBLE); 324 | overlayDown.setVisibility(View.INVISIBLE); 325 | } else { 326 | overlayUp.setVisibility(View.INVISIBLE); 327 | overlayDown.setVisibility(View.VISIBLE); 328 | } 329 | h.removeCallbacks(r); 330 | h.postDelayed(r, OVERLAY_TIME); 331 | } 332 | 333 | private int currentOutput = -1; 334 | private int lastOutputDelta = 0; 335 | 336 | void resetHysteresis() { 337 | currentOutput = -1; 338 | lastOutputDelta = 0; 339 | } 340 | 341 | private void setOutput(int output) { 342 | if (output != currentOutput) { 343 | boolean absorb = false; 344 | if (lastOutputDelta > 0 && output < currentOutput && output >= currentOutput - TOLERANCE) { 345 | absorb = true; 346 | } else if (lastOutputDelta < 0 && output > currentOutput && output <= currentOutput + TOLERANCE) { 347 | absorb = true; 348 | } 349 | if (!absorb) { 350 | if (currentOutput != -1) { 351 | lastOutputDelta = output - currentOutput; 352 | } 353 | currentOutput = output; 354 | if (monitor) { 355 | showOverlay(); 356 | } 357 | 358 | if (muiCallback != null) { 359 | muiCallback.updateOutput(output); 360 | } 361 | carManager.setParameters(VOLUME_PARAMETER_NAME + output); 362 | } 363 | } 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_arrow_drop_down_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-hdpi/ic_arrow_drop_down_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_arrow_drop_up_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-hdpi/ic_arrow_drop_up_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_arrow_drop_down_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-mdpi/ic_arrow_drop_down_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_arrow_drop_up_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-mdpi/ic_arrow_drop_up_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_arrow_drop_down_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-xhdpi/ic_arrow_drop_down_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_arrow_drop_up_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-xhdpi/ic_arrow_drop_up_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_drop_up_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-xxhdpi/ic_arrow_drop_up_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_down_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_down_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_up_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumburake/AutoVolume/b7501beb208aba8d1f832cf86e4fe8bd14fae1e1/app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_up_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 17 | 22 | 27 | 32 | 37 | 42 | 47 | 52 | 57 | 62 | 67 | 72 | 77 | 82 | 87 | 92 | 97 | 102 | 107 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /app/src/main/res/layout-nodpi/activity_test_vol.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 22 | 23 |