gts4lv-common: Implement audio rotation handler app×service
Change-Id: Ibc053edf1fa7e797f6457dfead416b177da57ab6
This commit is contained in:
17
AudioRotationMonitor/Android.mk
Normal file
17
AudioRotationMonitor/Android.mk
Normal file
@@ -0,0 +1,17 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := AudioRotationMonitor
|
||||
LOCAL_CERTIFICATE := platform
|
||||
LOCAL_PRIVATE_PLATFORM_APIS := true
|
||||
|
||||
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||
30
AudioRotationMonitor/AndroidManifest.xml
Normal file
30
AudioRotationMonitor/AndroidManifest.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.lineageos.audiorotationmonitor"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
android:sharedUserId="android.uid.system">
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="21"
|
||||
android:targetSdkVersion="21" />
|
||||
|
||||
<application
|
||||
android:label="AudioRotationMonitor"
|
||||
android:persistent="true">
|
||||
|
||||
<receiver android:name="org.lineageos.audiorotationmonitor.BootCompletedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="org.lineageos.audiorotationmonitor.DisplayListenerService"
|
||||
android:permission="AudioRotationMonitorService">
|
||||
</service>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
3
AudioRotationMonitor/proguard.flags
Normal file
3
AudioRotationMonitor/proguard.flags
Normal file
@@ -0,0 +1,3 @@
|
||||
-keep class org.lineageos.audiorotationmonitor.* {
|
||||
*;
|
||||
}
|
||||
14
AudioRotationMonitor/service/Android.mk
Normal file
14
AudioRotationMonitor/service/Android.mk
Normal file
@@ -0,0 +1,14 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := set-audio-rotation
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_INIT_RC := set-audio-rotation.rc
|
||||
LOCAL_SRC_FILES := \
|
||||
set-audio-rotation.cpp
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libtinyalsa
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
78
AudioRotationMonitor/service/set-audio-rotation.cpp
Normal file
78
AudioRotationMonitor/service/set-audio-rotation.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "set-audio-rotation"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <tinyalsa/asoundlib.h>
|
||||
|
||||
constexpr int SLOT_POSITIONS_0[] = { 1, 0, 1, 2, 0, 1, 0, 1 };
|
||||
constexpr int SLOT_POSITIONS_1[] = { 1, 0, 1, 2, 0, 1, 0, 1 };
|
||||
constexpr int SLOT_POSITIONS_2[] = { 0, 1, 0, 1, 1, 0, 1, 2 };
|
||||
constexpr int SLOT_POSITIONS_3[] = { 0, 1, 0, 1, 1, 0, 1, 2 };
|
||||
|
||||
void setMixerValueByName(mixer *mixer, const char *name, int value) {
|
||||
const auto ctl = mixer_get_ctl_by_name(mixer, name);
|
||||
|
||||
if (ctl == nullptr) {
|
||||
LOG(ERROR) << "Failed to find mixer ctl for " << name;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mixer_ctl_set_value(ctl, 0, value) < 0) {
|
||||
LOG(ERROR) << "Failed to set ctl value " << value << " for " << name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void setSlotPositions(const int *values) {
|
||||
const auto mixer = mixer_open(0);
|
||||
|
||||
if (mixer == nullptr) {
|
||||
LOG(ERROR) << "Failed to open mixer";
|
||||
return;
|
||||
}
|
||||
|
||||
setMixerValueByName(mixer, "FL ASPRX1 Slot Position", values[0]);
|
||||
setMixerValueByName(mixer, "FL ASPRX2 Slot Position", values[1]);
|
||||
setMixerValueByName(mixer, "FR ASPRX1 Slot Position", values[2]);
|
||||
setMixerValueByName(mixer, "FR ASPRX2 Slot Position", values[3]);
|
||||
setMixerValueByName(mixer, "RL ASPRX1 Slot Position", values[4]);
|
||||
setMixerValueByName(mixer, "RL ASPRX2 Slot Position", values[5]);
|
||||
setMixerValueByName(mixer, "RR ASPRX1 Slot Position", values[6]);
|
||||
setMixerValueByName(mixer, "RR ASPRX2 Slot Position", values[7]);
|
||||
|
||||
mixer_close(mixer);
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "0") == 0) {
|
||||
setSlotPositions(SLOT_POSITIONS_0);
|
||||
} else if (strcmp(argv[1], "1") == 0) {
|
||||
setSlotPositions(SLOT_POSITIONS_1);
|
||||
} else if (strcmp(argv[1], "2") == 0) {
|
||||
setSlotPositions(SLOT_POSITIONS_2);
|
||||
} else if (strcmp(argv[1], "3") == 0) {
|
||||
setSlotPositions(SLOT_POSITIONS_3);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
2
AudioRotationMonitor/service/set-audio-rotation.rc
Normal file
2
AudioRotationMonitor/service/set-audio-rotation.rc
Normal file
@@ -0,0 +1,2 @@
|
||||
on property:sys.audio.rotation=*
|
||||
exec - root audio -- /system/bin/set-audio-rotation ${sys.audio.rotation}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.lineageos.audiorotationmonitor;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public class BootCompletedReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "AudioRotationMonitor";
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, Intent intent) {
|
||||
Log.d(TAG, "Starting");
|
||||
context.startService(new Intent(context, DisplayListenerService.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.lineageos.audiorotationmonitor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class DisplayListener implements DisplayManager.DisplayListener {
|
||||
private static final boolean DEBUG = true;
|
||||
private static final String TAG = "DisplayListener";
|
||||
|
||||
private static final String AUDIO_ROTATION_PROP = "sys.audio.rotation";
|
||||
|
||||
private Context mContext;
|
||||
private Handler mHandler;
|
||||
|
||||
private DisplayManager mDisplayManager;
|
||||
private WindowManager mWindowManager;
|
||||
|
||||
private final Object mRotationLock = new Object();
|
||||
private int mDeviceRotation = Surface.ROTATION_0;
|
||||
|
||||
public DisplayListener(Context context) {
|
||||
mContext = context;
|
||||
mHandler = new Handler();
|
||||
|
||||
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) {
|
||||
if (DEBUG) Log.d(TAG, "onDisplayAdded");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
if (DEBUG) Log.d(TAG, "onDisplayRemoved");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayChanged(int displayId) {
|
||||
if (DEBUG) Log.d(TAG, "onDisplayChanged");
|
||||
updateOrientation();
|
||||
}
|
||||
|
||||
private void updateOrientation() {
|
||||
// Even though we're responding to device orientation events,
|
||||
// use display rotation so audio stays in sync with video/dialogs
|
||||
int newRotation = mWindowManager.getDefaultDisplay().getRotation();
|
||||
|
||||
synchronized (mRotationLock) {
|
||||
if (newRotation != mDeviceRotation) {
|
||||
mDeviceRotation = newRotation;
|
||||
SystemProperties.set(AUDIO_ROTATION_PROP, String.valueOf(mDeviceRotation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
if (DEBUG) Log.d(TAG, "Enabling");
|
||||
mDisplayManager.registerDisplayListener(this, mHandler);
|
||||
updateOrientation();
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
if (DEBUG) Log.d(TAG, "Disabling");
|
||||
mDisplayManager.unregisterDisplayListener(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.lineageos.audiorotationmonitor;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
public class DisplayListenerService extends Service {
|
||||
private static final String TAG = "DisplayListenerService";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private DisplayListener mDisplayListener;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
if (DEBUG) Log.d(TAG, "Creating service");
|
||||
mDisplayListener = new DisplayListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (DEBUG) Log.d(TAG, "Starting service");
|
||||
mDisplayListener.enable();
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (DEBUG) Log.d(TAG, "Destroying service");
|
||||
mDisplayListener.disable();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -153,6 +153,8 @@ VENDOR_SECURITY_PATCH := 2018-08-05
|
||||
|
||||
# SELinux
|
||||
include device/qcom/sepolicy/sepolicy.mk
|
||||
|
||||
BOARD_PLAT_PRIVATE_SEPOLICY_DIR += $(COMMON_PATH)/sepolicy/private
|
||||
BOARD_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/vendor
|
||||
|
||||
# Soong Namespaces
|
||||
|
||||
11
gts4lv.mk
11
gts4lv.mk
@@ -52,23 +52,24 @@ PRODUCT_PACKAGES += \
|
||||
|
||||
# Audio
|
||||
PRODUCT_PACKAGES += \
|
||||
android.hardware.audio@2.0-impl \
|
||||
android.hardware.audio@4.0-impl \
|
||||
android.hardware.audio@2.0-service \
|
||||
android.hardware.audio.effect@2.0-impl \
|
||||
android.hardware.audio.effect@4.0-impl \
|
||||
android.hardware.audio@2.0-impl \
|
||||
android.hardware.audio@2.0-service \
|
||||
android.hardware.audio@4.0-impl \
|
||||
android.hardware.soundtrigger@2.0-impl:32 \
|
||||
android.hardware.soundtrigger@2.1-impl \
|
||||
audio.primary.sdm710:32 \
|
||||
audio.r_submix.default \
|
||||
audio.usb.default \
|
||||
AudioRotationMonitor \
|
||||
cplay \
|
||||
libaudioroute \
|
||||
libqcompostprocbundle \
|
||||
libqcomvisualizer \
|
||||
libqcomvoiceprocessing \
|
||||
libvolumelistener \
|
||||
cplay \
|
||||
|
||||
set-audio-rotation \
|
||||
|
||||
PRODUCT_COPY_FILES += \
|
||||
$(LOCAL_PATH)/audio/audio_effects_common.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects_common.conf \
|
||||
|
||||
2
sepolicy/private/file_contexts
Normal file
2
sepolicy/private/file_contexts
Normal file
@@ -0,0 +1,2 @@
|
||||
# Binaries
|
||||
/system/bin/set-audio-rotation u:object_r:set-audio-rotation_exec:s0
|
||||
1
sepolicy/private/property_contexts
Normal file
1
sepolicy/private/property_contexts
Normal file
@@ -0,0 +1 @@
|
||||
sys.audio.rotation u:object_r:exported_system_prop:s0
|
||||
8
sepolicy/private/set-audio-rotation.te
Normal file
8
sepolicy/private/set-audio-rotation.te
Normal file
@@ -0,0 +1,8 @@
|
||||
type set-audio-rotation, domain, coredomain;
|
||||
type set-audio-rotation_exec, exec_type, file_type;
|
||||
|
||||
init_daemon_domain(set-audio-rotation)
|
||||
|
||||
# Allow set-audio-rotation to read and write to audio_device
|
||||
allow set-audio-rotation audio_device:dir r_dir_perms;
|
||||
allow set-audio-rotation audio_device:chr_file rw_file_perms;
|
||||
Reference in New Issue
Block a user