Files
packages_apps_Settings/src/com/android/settings/accessibility/HighContrastTextMigrationReceiver.java
Daniel Norman 1a983ff386 fix(hct): Hardcode the names of Outline text and HCT in our notif.
This should help prevent localization issues caused by capitalization of
this templated string, since these feature names should not be
capitalized unless they are at the beginning of the sentence.

The 'Settings' app name should always be capitalized since it's the
proper name of an app, so that remains templated.

Bug: 399358129
Test: atest HighContrastTextMigrationReceiverTest;
      (this test asserts against a hardcoded version of the entire
       string)
Flag: com.android.graphics.hwui.flags.high_contrast_text_small_text_rect
Change-Id: Iaaa2ac10a56c1e4f7e5a8fd0d1c8eaf8b0293a27
2025-03-06 20:44:21 +00:00

203 lines
9.5 KiB
Java

/*
* Copyright (C) 2024 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.
*/
package com.android.settings.accessibility;
import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import android.annotation.IntDef;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.graphics.hwui.flags.Flags;
import com.android.modules.expresslog.Counter;
import com.android.settings.R;
import com.google.common.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Handling smooth migration to the new high contrast text appearance
*/
public class HighContrastTextMigrationReceiver extends BroadcastReceiver {
private static final String TAG = HighContrastTextMigrationReceiver.class.getSimpleName();
@VisibleForTesting
static final String NOTIFICATION_CHANNEL = "accessibility_notification_channel";
@VisibleForTesting
static final String ACTION_RESTORED =
"com.android.settings.accessibility.ACTION_HIGH_CONTRAST_TEXT_RESTORED";
@VisibleForTesting
static final String ACTION_OPEN_SETTINGS =
"com.android.settings.accessibility.ACTION_OPEN_HIGH_CONTRAST_TEXT_SETTINGS";
private static final String ACTION_NOTIFICATION_DISMISSED =
"com.android.settings.accessibility.ACTION_HIGH_CONTRAST_TEXT_NOTIFICATION_DISMISSED";
@VisibleForTesting
static final int NOTIFICATION_ID = R.string.accessibility_notification_high_contrast_text_title;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PromptState.UNKNOWN,
PromptState.PROMPT_SHOWN,
PromptState.PROMPT_UNNECESSARY,
})
public @interface PromptState {
int UNKNOWN = 0;
int PROMPT_SHOWN = 1;
int PROMPT_UNNECESSARY = 2;
}
@Override
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
if (!Flags.highContrastTextSmallTextRect()) {
return;
}
if (ACTION_OPEN_SETTINGS.equals(intent.getAction())) {
// Close notification drawer before opening the HCT setting.
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
Intent settingsIntent = createHighContrastTextSettingsIntent(context);
settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(settingsIntent);
context.getSystemService(NotificationManager.class).cancel(NOTIFICATION_ID);
} else if (ACTION_NOTIFICATION_DISMISSED.equals(intent.getAction())) {
Counter.logIncrement("accessibility.value_hct_notification_dismissed");
} else if (ACTION_RESTORED.equals(intent.getAction())) {
Log.i(TAG, "HCT attempted to be restored from backup; showing notification for userId: "
+ context.getUserId());
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HCT_RECT_PROMPT_STATUS,
PromptState.PROMPT_SHOWN);
showNotification(context);
} else if (Intent.ACTION_PRE_BOOT_COMPLETED.equals(intent.getAction())) {
final boolean hasSeenPromptIfNecessary = Settings.Secure.getInt(
context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HCT_RECT_PROMPT_STATUS, PromptState.UNKNOWN)
!= PromptState.UNKNOWN;
if (hasSeenPromptIfNecessary) {
Log.i(TAG, "Has seen HCT prompt if necessary; skip HCT migration for userId: "
+ context.getUserId());
return;
}
final boolean isHctEnabled = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, OFF) == ON;
if (isHctEnabled) {
Log.i(TAG, "HCT enabled before OTA update; performing migration for userId: "
+ context.getUserId());
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
OFF);
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HCT_RECT_PROMPT_STATUS,
PromptState.PROMPT_SHOWN);
showNotification(context);
} else {
Log.i(TAG,
"HCT was not enabled before OTA update; not performing migration for "
+ "userId: " + context.getUserId());
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HCT_RECT_PROMPT_STATUS,
PromptState.PROMPT_UNNECESSARY);
}
}
}
private String getNotificationContentText(Context context) {
final String settingsAppName = context.getString(R.string.settings_label);
return context.getString(
R.string.accessibility_notification_high_contrast_text_body_message,
settingsAppName);
}
private void showNotification(Context context) {
Notification.Builder notificationBuilder = new Notification.Builder(context,
NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.ic_settings_24dp)
.setContentTitle(context.getString(
R.string.accessibility_notification_high_contrast_text_title))
.setContentText(getNotificationContentText(context))
.setFlag(Notification.FLAG_NO_CLEAR, true);
Intent settingsIntent = createHighContrastTextSettingsIntent(context);
if (settingsIntent.resolveActivity(context.getPackageManager()) != null) {
PendingIntent settingsPendingIntent = PendingIntent.getActivity(context,
/* requestCode = */ 0, settingsIntent, PendingIntent.FLAG_IMMUTABLE);
Intent actionIntent = new Intent(context, HighContrastTextMigrationReceiver.class);
actionIntent.setAction(ACTION_OPEN_SETTINGS);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0,
actionIntent, PendingIntent.FLAG_IMMUTABLE);
final int actionResId =
R.string.accessibility_notification_high_contrast_text_action_open_settings;
Notification.Action settingsAction = new Notification.Action.Builder(
/* icon= */ null,
context.getString(actionResId, context.getString(R.string.settings_label)),
actionPendingIntent
).build();
notificationBuilder
.setContentIntent(settingsPendingIntent)
.addAction(settingsAction)
.setAutoCancel(true);
}
Intent deleteIntent = new Intent(context, HighContrastTextMigrationReceiver.class);
deleteIntent.setAction(ACTION_NOTIFICATION_DISMISSED);
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0,
deleteIntent, PendingIntent.FLAG_IMMUTABLE);
notificationBuilder.setDeleteIntent(deletePendingIntent);
NotificationManager notificationManager =
context.getSystemService(NotificationManager.class);
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL,
context.getString(R.string.accessibility_settings),
NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
Counter.logIncrement("accessibility.value_hct_notification_posted");
}
private Intent createHighContrastTextSettingsIntent(Context context) {
Intent settingsIntent = new Intent(Settings.ACTION_TEXT_READING_SETTINGS);
settingsIntent.setPackage(context.getPackageName());
Bundle fragmentArgs = new Bundle();
fragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY,
TextReadingPreferenceFragment.HIGH_TEXT_CONTRAST_KEY);
fragmentArgs.putInt(TextReadingPreferenceFragment.EXTRA_LAUNCHED_FROM,
TextReadingPreferenceFragment.EntryPoint.HIGH_CONTRAST_TEXT_NOTIFICATION);
settingsIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
return settingsIntent;
}
}