Merge "Adding the on-device captions service toggle into the volume rocker."
This commit is contained in:
@@ -5589,6 +5589,15 @@ public final class Settings {
|
||||
|
||||
private static final Validator ALLOW_MOCK_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR;
|
||||
|
||||
/**
|
||||
* Setting to indicate that on device captions are enabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled";
|
||||
|
||||
private static final Validator ODI_CAPTIONS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
|
||||
|
||||
/**
|
||||
* On Android 8.0 (API level 26) and higher versions of the platform,
|
||||
* a 64-bit number (expressed as a hexadecimal string), unique to
|
||||
@@ -8950,6 +8959,7 @@ public final class Settings {
|
||||
VALIDATORS.put(SILENCE_TIMER_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
|
||||
VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
|
||||
VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
|
||||
VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3513,6 +3513,12 @@
|
||||
-->
|
||||
<string name="config_defaultAttentionService" translatable="false"></string>
|
||||
|
||||
<!-- The component name for the system-wide captions service.
|
||||
This service must be trusted, as it controls part of the UI of the volume bar.
|
||||
Example: "com.android.captions/.SystemCaptionsService"
|
||||
-->
|
||||
<string name="config_defaultSystemCaptionsService" translatable="false"></string>
|
||||
|
||||
<!-- The package name for the incident report approver app.
|
||||
This app is usually PermissionController or an app that replaces it. When
|
||||
a bugreport or incident report with EXPLICT-level sharing flags is going to be
|
||||
|
||||
@@ -3382,6 +3382,7 @@
|
||||
<java-symbol type="string" name="config_defaultAppPredictionService" />
|
||||
<java-symbol type="string" name="config_defaultContentSuggestionsService" />
|
||||
<java-symbol type="string" name="config_defaultAttentionService" />
|
||||
<java-symbol type="string" name="config_defaultSystemCaptionsService" />
|
||||
|
||||
<java-symbol type="string" name="notification_channel_foreground_service" />
|
||||
<java-symbol type="string" name="foreground_service_app_in_background" />
|
||||
|
||||
@@ -58,6 +58,10 @@ public interface VolumeDialogController {
|
||||
void userActivity();
|
||||
void getState();
|
||||
|
||||
boolean areCaptionsEnabled();
|
||||
void setCaptionsEnabled(boolean isEnabled);
|
||||
void getCaptionsComponentState();
|
||||
|
||||
@ProvidesInterface(version = StreamState.VERSION)
|
||||
public static final class StreamState {
|
||||
public static final int VERSION = 1;
|
||||
@@ -186,5 +190,6 @@ public interface VolumeDialogController {
|
||||
void onScreenOff();
|
||||
void onShowSafetyWarning(int flags);
|
||||
void onAccessibilityModeChanged(Boolean showA11yStream);
|
||||
void onCaptionComponentStateChanged(Boolean isComponentEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
24
packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
Normal file
24
packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2019 The Android Open Source 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M20,4C21.1,4 22,4.9 22,6L22,18C22,19.1 21.1,20 20,20L4,20C2.9,20 2,19.1 2,18L2,6C2,4.9 2.9,4 4,4L20,4ZM20,18L20,6L4,6L4,18L20,18ZM6,10L8,10L8,12L6,12L6,10ZM6,14L14,14L14,16L6,16L6,14ZM16,14L18,14L18,16L16,16L16,14ZM10,10L18,10L18,12L10,12L10,10Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2019 The Android Open Source 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M16.9675,14L18,14L18,15.0275L16.9675,14ZM20,17.0176L20,6L8.9281,6L6.9182,4L20,4C21.1,4 22,4.9 22,6L22,18C22,18.2949 21.9353,18.5755 21.8194,18.8281L20,17.0176ZM12.9478,10L18,10L18,12L14.9576,12L12.9478,10ZM1.2823,0.8824L22.8489,22.4489L21.6337,23.6641L17.9696,20L4,20C2.9,20 2,19.1 2,18L2,6C2,5.4577 2.2188,4.964 2.5724,4.6028L0.0672,2.0975L1.2823,0.8824ZM13.9696,16L6,16L6,14L11.9696,14L8,10.0304L8,12L6,12L6,10L7.9696,10L4,6.0304L4,18L15.9696,18L13.9696,16Z"/>
|
||||
</vector>
|
||||
@@ -98,5 +98,27 @@
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/odi_captions"
|
||||
android:layout_width="@dimen/volume_dialog_caption_size"
|
||||
android:layout_height="@dimen/volume_dialog_caption_size"
|
||||
android:layout_marginTop="@dimen/volume_dialog_spacer"
|
||||
android:translationZ="@dimen/volume_dialog_elevation"
|
||||
android:layout_gravity="right"
|
||||
android:clipToPadding="false"
|
||||
android:visibility="gone"
|
||||
android:background="@drawable/rounded_bg_full">
|
||||
<com.android.keyguard.AlphaOptimizedImageButton
|
||||
android:id="@+id/odi_captions_icon"
|
||||
android:src="@drawable/ic_volume_odi_captions_disabled"
|
||||
style="@style/VolumeButtons"
|
||||
android:background="@drawable/rounded_ripple"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:tint="@color/accent_tint_color_selector"
|
||||
android:layout_gravity="center"
|
||||
android:soundEffectsEnabled="false" />
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
@@ -336,6 +336,8 @@
|
||||
|
||||
<dimen name="volume_dialog_ringer_size">64dp</dimen>
|
||||
|
||||
<dimen name="volume_dialog_caption_size">64dp</dimen>
|
||||
|
||||
<dimen name="volume_dialog_tap_target_size">48dp</dimen>
|
||||
|
||||
<dimen name="volume_dialog_spacer">4dp</dimen>
|
||||
|
||||
@@ -55,6 +55,7 @@ public class Events {
|
||||
public static final int EVENT_RINGER_TOGGLE = 18; // (ringer_mode)
|
||||
public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool)
|
||||
public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool)
|
||||
public static final int EVENT_ODI_CAPTIONS_CLICK = 21;
|
||||
|
||||
private static final String[] EVENT_TAGS = {
|
||||
"show_dialog",
|
||||
@@ -77,7 +78,8 @@ public class Events {
|
||||
"zen_mode_config_changed",
|
||||
"ringer_toggle",
|
||||
"show_usb_overheat_alarm",
|
||||
"dismiss_usb_overheat_alarm"
|
||||
"dismiss_usb_overheat_alarm",
|
||||
"odi_captions_click"
|
||||
};
|
||||
|
||||
public static final int DISMISS_REASON_UNKNOWN = 0;
|
||||
@@ -90,6 +92,7 @@ public class Events {
|
||||
public static final int DISMISS_STREAM_GONE = 7;
|
||||
public static final int DISMISS_REASON_OUTPUT_CHOOSER = 8;
|
||||
public static final int DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED = 9;
|
||||
public static final int DISMISS_REASON_ODI_CAPTIONS_CLICKED = 10;
|
||||
public static final String[] DISMISS_REASONS = {
|
||||
"unknown",
|
||||
"touch_outside",
|
||||
@@ -100,7 +103,8 @@ public class Events {
|
||||
"done_clicked",
|
||||
"a11y_stream_changed",
|
||||
"output_chooser",
|
||||
"usb_temperature_below_threshold"
|
||||
"usb_temperature_below_threshold",
|
||||
"odi_captions_clicked"
|
||||
};
|
||||
|
||||
public static final int SHOW_REASON_UNKNOWN = 0;
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.Condition;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
@@ -270,6 +271,22 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
|
||||
mWorker.sendEmptyMessage(W.GET_STATE);
|
||||
}
|
||||
|
||||
public boolean areCaptionsEnabled() {
|
||||
int currentValue = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ODI_CAPTIONS_ENABLED, 0);
|
||||
return currentValue == 1;
|
||||
}
|
||||
|
||||
public void setCaptionsEnabled(boolean isEnabled) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ODI_CAPTIONS_ENABLED, isEnabled ? 1 : 0);
|
||||
}
|
||||
|
||||
public void getCaptionsComponentState() {
|
||||
if (mDestroyed) return;
|
||||
mWorker.sendEmptyMessage(W.GET_CAPTIONS_COMPONENT_STATE);
|
||||
}
|
||||
|
||||
public void notifyVisible(boolean visible) {
|
||||
if (mDestroyed) return;
|
||||
mWorker.obtainMessage(W.NOTIFY_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
|
||||
@@ -365,6 +382,38 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
|
||||
}
|
||||
}
|
||||
|
||||
private void onGetCaptionsComponentStateW() {
|
||||
try {
|
||||
String componentNameString = mContext.getString(
|
||||
com.android.internal.R.string.config_defaultSystemCaptionsService);
|
||||
if (TextUtils.isEmpty(componentNameString)) {
|
||||
// component doesn't exist
|
||||
mCallbacks.onCaptionComponentStateChanged(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (D.BUG) {
|
||||
Log.i(TAG, String.format(
|
||||
"isCaptionsServiceEnabled componentNameString=%s", componentNameString));
|
||||
}
|
||||
|
||||
ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
|
||||
if (componentName == null) {
|
||||
mCallbacks.onCaptionComponentStateChanged(false);
|
||||
return;
|
||||
}
|
||||
|
||||
PackageManager packageManager = mContext.getPackageManager();
|
||||
mCallbacks.onCaptionComponentStateChanged(
|
||||
packageManager.getComponentEnabledSetting(componentName)
|
||||
== PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG,
|
||||
"isCaptionsServiceEnabled failed to check for captions component", ex);
|
||||
mCallbacks.onCaptionComponentStateChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAccessibilityModeChanged(Boolean showA11yStream) {
|
||||
mCallbacks.onAccessibilityModeChanged(showA11yStream);
|
||||
}
|
||||
@@ -718,6 +767,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
|
||||
private static final int USER_ACTIVITY = 13;
|
||||
private static final int SHOW_SAFETY_WARNING = 14;
|
||||
private static final int ACCESSIBILITY_MODE_CHANGED = 15;
|
||||
private static final int GET_CAPTIONS_COMPONENT_STATE = 16;
|
||||
|
||||
W(Looper looper) {
|
||||
super(looper);
|
||||
@@ -740,8 +790,8 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
|
||||
case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break;
|
||||
case USER_ACTIVITY: onUserActivityW(); break;
|
||||
case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
|
||||
case GET_CAPTIONS_COMPONENT_STATE: onGetCaptionsComponentStateW(); break;
|
||||
case ACCESSIBILITY_MODE_CHANGED: onAccessibilityModeChanged((Boolean) msg.obj);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -881,6 +931,15 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCaptionComponentStateChanged(Boolean isComponentEnabled) {
|
||||
boolean componentEnabled = isComponentEnabled == null ? false : isComponentEnabled;
|
||||
for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
|
||||
entry.getValue().post(
|
||||
() -> entry.getKey().onCaptionComponentStateChanged(componentEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.systemui.volume.Events.DISMISS_REASON_ODI_CAPTIONS_CLICKED;
|
||||
import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
@@ -125,6 +126,8 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
private ViewGroup mDialogRowsView;
|
||||
private ViewGroup mRinger;
|
||||
private ImageButton mRingerIcon;
|
||||
private ViewGroup mODICaptionsView;
|
||||
private ImageButton mODICaptionsIcon;
|
||||
private View mSettingsView;
|
||||
private ImageButton mSettingsIcon;
|
||||
private FrameLayout mZenIcon;
|
||||
@@ -240,6 +243,10 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
|
||||
mZenIcon = mRinger.findViewById(R.id.dnd_icon);
|
||||
}
|
||||
mODICaptionsView = mDialog.findViewById(R.id.odi_captions);
|
||||
if (mODICaptionsView != null) {
|
||||
mODICaptionsIcon = mODICaptionsView.findViewById(R.id.odi_captions_icon);
|
||||
}
|
||||
mSettingsView = mDialog.findViewById(R.id.settings_container);
|
||||
mSettingsIcon = mDialog.findViewById(R.id.settings);
|
||||
|
||||
@@ -270,6 +277,7 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
updateRowsH(getActiveRow());
|
||||
initRingerH();
|
||||
initSettingsH();
|
||||
initODICaptionsH();
|
||||
}
|
||||
|
||||
protected ViewGroup getDialogView() {
|
||||
@@ -478,6 +486,42 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
updateRingerH();
|
||||
}
|
||||
|
||||
private void initODICaptionsH() {
|
||||
if (mODICaptionsIcon != null) {
|
||||
mODICaptionsIcon.setOnClickListener(v -> {
|
||||
onCaptionIconClicked();
|
||||
Events.writeEvent(mContext, Events.EVENT_ODI_CAPTIONS_CLICK);
|
||||
dismissH(DISMISS_REASON_ODI_CAPTIONS_CLICKED);
|
||||
});
|
||||
}
|
||||
|
||||
mController.getCaptionsComponentState();
|
||||
}
|
||||
|
||||
private void updateODICaptionsH(boolean isServiceComponentEnabled) {
|
||||
if (mODICaptionsView != null) {
|
||||
mODICaptionsView.setVisibility(isServiceComponentEnabled ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
if (!isServiceComponentEnabled) return;
|
||||
|
||||
updateCaptionsIcon();
|
||||
}
|
||||
|
||||
private void updateCaptionsIcon() {
|
||||
mHandler.post(
|
||||
mODICaptionsIcon.setImageResourceAsync(
|
||||
mController.areCaptionsEnabled()
|
||||
? R.drawable.ic_volume_odi_captions
|
||||
: R.drawable.ic_volume_odi_captions_disabled));
|
||||
}
|
||||
|
||||
private void onCaptionIconClicked() {
|
||||
boolean isEnabled = mController.areCaptionsEnabled();
|
||||
mController.setCaptionsEnabled(!isEnabled);
|
||||
updateCaptionsIcon();
|
||||
}
|
||||
|
||||
private void incrementManualToggleCount() {
|
||||
ContentResolver cr = mContext.getContentResolver();
|
||||
int ringerCount = Settings.Secure.getInt(cr, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, 0);
|
||||
@@ -558,6 +602,7 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
mDialog.show();
|
||||
Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
|
||||
mController.notifyVisible(true);
|
||||
mController.getCaptionsComponentState();
|
||||
}
|
||||
|
||||
protected void rescheduleTimeoutH() {
|
||||
@@ -1151,6 +1196,11 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCaptionComponentStateChanged(Boolean isComponentEnabled) {
|
||||
updateODICaptionsH(isComponentEnabled);
|
||||
}
|
||||
};
|
||||
|
||||
private final class H extends Handler {
|
||||
|
||||
Reference in New Issue
Block a user