| /* |
| * 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.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 (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, |
| Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); |
| fragmentArgs.putInt(TextReadingPreferenceFragment.EXTRA_LAUNCHED_FROM, |
| TextReadingPreferenceFragment.EntryPoint.HIGH_CONTRAST_TEXT_NOTIFICATION); |
| settingsIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs); |
| return settingsIntent; |
| } |
| } |