• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.development;
18 
19 import android.app.Notification;
20 import android.app.NotificationChannel;
21 import android.app.NotificationManager;
22 import android.app.PendingIntent;
23 import android.app.Service;
24 import android.content.Intent;
25 import android.os.IBinder;
26 import android.os.UserHandle;
27 import android.provider.Settings;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 
32 import com.android.settings.R;
33 
34 public class PageAgnosticNotificationService extends Service {
35 
36     private static final String NOTIFICATION_CHANNEL_ID =
37             "com.android.settings.development.PageAgnosticNotificationService";
38     public static final String INTENT_ACTION_DISMISSED =
39             "com.android.settings.development.NOTIFICATION_DISMISSED";
40 
41     // Updating the notification ID to avoid the notification being dismissed
42     // accidentally by other notifications. ID used is the bug id where this was
43     // reported.
44     private static final int NOTIFICATION_ID = 388678898;
45 
46     static final int DISABLE_UPDATES_SETTING = 1;
47 
48     private NotificationManager mNotificationManager;
49 
50     @Nullable
51     @Override
onBind(@onNull Intent intent)52     public IBinder onBind(@NonNull Intent intent) {
53         return null;
54     }
55 
56     // create a notification channel to post persistent notification
createNotificationChannel()57     private void createNotificationChannel() {
58         NotificationChannel channel =
59                 new NotificationChannel(
60                         NOTIFICATION_CHANNEL_ID,
61                         getString(R.string.page_agnostic_notification_channel_name),
62                         NotificationManager.IMPORTANCE_HIGH);
63         mNotificationManager = getSystemService(NotificationManager.class);
64         if (mNotificationManager != null) {
65             mNotificationManager.createNotificationChannel(channel);
66         }
67     }
68 
69     @Override
onCreate()70     public void onCreate() {
71         super.onCreate();
72         createNotificationChannel();
73 
74         // No updates should be allowed in page-agnostic mode
75         disableAutomaticUpdates();
76     }
77 
buildNotification()78     private Notification buildNotification() {
79         // Get the title and text according to page size
80         boolean isIn16kbMode = Enable16kUtils.isUsing16kbPages();
81         String title =
82                 isIn16kbMode
83                         ? getString(R.string.page_agnostic_16k_pages_title)
84                         : getString(R.string.page_agnostic_4k_pages_title);
85         String text =
86                 isIn16kbMode
87                         ? getString(R.string.page_agnostic_16k_pages_text_short)
88                         : getString(R.string.page_agnostic_4k_pages_text_short);
89 
90         Intent notifyIntent = new Intent(this, PageAgnosticWarningActivity.class);
91         // Set the Activity to start in a new, empty task.
92         notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
93 
94         // Create the PendingIntent.
95         PendingIntent notifyPendingIntent =
96                 PendingIntent.getActivity(
97                         this,
98                         0,
99                         notifyIntent,
100                         PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
101 
102         Intent dismissIntent = new Intent(this, Enable16KBootReceiver.class);
103         dismissIntent.setAction(INTENT_ACTION_DISMISSED);
104         PendingIntent dismissPendingIntent =
105                 PendingIntent.getBroadcast(
106                         this.getApplicationContext(),
107                         0,
108                         dismissIntent,
109                         PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
110 
111         Notification.Action action =
112                 new Notification.Action.Builder(
113                                 R.drawable.empty_icon,
114                                 getString(R.string.page_agnostic_notification_action),
115                                 notifyPendingIntent)
116                         .build();
117 
118         // TODO:(b/349860833) Change text style to BigTextStyle once the ellipsis issue is fixed.
119         Notification.Builder builder =
120                 new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
121                         .setContentTitle(title)
122                         .setContentText(text)
123                         .setOngoing(true)
124                         .setSmallIcon(R.drawable.ic_settings_24dp)
125                         .setContentIntent(notifyPendingIntent)
126                         .setDeleteIntent(dismissPendingIntent)
127                         .addAction(action);
128 
129         return builder.build();
130     }
131 
disableAutomaticUpdates()132     private void disableAutomaticUpdates() {
133         final int currentState =
134                 Settings.Global.getInt(
135                         getApplicationContext().getContentResolver(),
136                         Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE,
137                         0 /* default */);
138         // 0 means enabled, 1 means disabled
139         if (currentState == 0) {
140             // automatic updates are enabled, disable them
141             Settings.Global.putInt(
142                     getApplicationContext().getContentResolver(),
143                     Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE,
144                     DISABLE_UPDATES_SETTING);
145         }
146     }
147 
148     @Override
onStartCommand(@ullable Intent intent, int flags, int startId)149     public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
150         Notification notification = buildNotification();
151         if (mNotificationManager != null) {
152             mNotificationManager.notifyAsUser(null, NOTIFICATION_ID, notification,
153                     UserHandle.ALL);
154         }
155         return Service.START_REDELIVER_INTENT;
156     }
157 }
158