Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0ea2347 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11051137 from 590301f4 to 24Q1-release

Change-Id: Id1861dd1619e9613c52179f454318f608dbd307a
parents 6b49cce5 590301f4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ cc_library_shared {
        "libstatslog_bt",
        "libudrv-uipc",
        "libutils",
        "server_configurable_flags",
    ],
    shared_libs: [
        "libaaudio",
@@ -144,7 +145,6 @@ cc_library_shared {
        "libnativehelper",
        "libstatssocket",
        "libvndksupport",
        "server_configurable_flags",
    ],
    sanitize: {
        scs: true,
@@ -208,6 +208,7 @@ android_app {
    srcs: [
        ":statslog-bluetooth-java-gen",
        ":statslog-bt-restricted-java-gen",
        ":system-messages-proto-src",
        "proto/keystore.proto",
        "src/**/*.java",
    ],
+10 −0
Original line number Diff line number Diff line
@@ -103,6 +103,16 @@
            </intent-filter>
        </service>

        <service android:process="@string/process"
             android:name="com.android.bluetooth.airplane.NotificationHelperService"
             android:label="Airplane Notification Helper"
             android:exported="true"
             android:permission="android.permission.BLUETOOTH_PRIVILEGED">
            <intent-filter>
                <action android:name="android.bluetooth.airplane.action.SEND_NOTIFICATION"/>
            </intent-filter>
        </service>

        <!--  Advanced Audio Distribution Profile (A2DP) source Profile Service  -->
        <service android:process="@string/process"
             android:name="com.android.bluetooth.a2dp.A2dpService"
+142 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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.bluetooth.airplane;

import static java.util.Objects.requireNonNull;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.IBinder;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.Pair;

import com.android.bluetooth.R;
import com.android.internal.messages.SystemMessageProto.SystemMessage;

import java.util.Map;

public class NotificationHelperService extends Service {
    private static final String TAG = NotificationHelperService.class.getSimpleName();

    // Keeps track of whether wifi and bt remains on notification was shown
    private static final String APM_WIFI_BT_NOTIFICATION = "apm_wifi_bt_notification";
    // Keeps track of whether bt remains on notification was shown
    private static final String APM_BT_NOTIFICATION = "apm_bt_notification";
    // Keeps track of whether user enabling bt notification was shown
    private static final String APM_BT_ENABLED_NOTIFICATION = "apm_bt_enabled_notification";

    private static final String NOTIFICATION_TAG = "com.android.bluetooth";
    private static final String APM_NOTIFICATION_CHANNEL = "apm_notification_channel";
    private static final String APM_NOTIFICATION_GROUP = "apm_notification_group";
    private static final String HELP_PAGE_URL =
            "https://support.google.com/pixelphone/answer/12639358";

    private static final Map<String, Pair<Integer /* titleId */, Integer /* messageId */>>
            NOTIFICATION_MAP =
                    Map.of(
                            APM_WIFI_BT_NOTIFICATION,
                            Pair.create(
                                    R.string.bluetooth_and_wifi_stays_on_title,
                                    R.string.bluetooth_and_wifi_stays_on_message),
                            APM_BT_NOTIFICATION,
                            Pair.create(
                                    R.string.bluetooth_stays_on_title,
                                    R.string.bluetooth_stays_on_message),
                            APM_BT_ENABLED_NOTIFICATION,
                            Pair.create(
                                    R.string.bluetooth_enabled_apm_title,
                                    R.string.bluetooth_enabled_apm_message));

    @Override
    public IBinder onBind(Intent intent) {
        return null; // This is not a bound service
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sendAirplaneModeNotification(
                intent.getStringExtra("android.bluetooth.airplane.extra.NOTIFICATION_STATE"));
        return Service.START_NOT_STICKY;
    }

    private void sendAirplaneModeNotification(String notificationState) {
        String logHeader = "sendAirplaneModeNotification(" + notificationState + "): ";
        Pair<Integer, Integer> notificationContent = NOTIFICATION_MAP.get(notificationState);
        if (notificationContent == null) {
            Log.e(TAG, logHeader + "unknown action");
            return;
        }

        if (!isFirstTimeNotification(notificationState)) {
            Log.d(TAG, logHeader + "already displayed");
            return;
        }
        Settings.Secure.putInt(getContentResolver(), notificationState, 1);

        Log.d(TAG, logHeader + "sending");

        NotificationManager notificationManager =
                requireNonNull(getSystemService(NotificationManager.class));
        for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
            if (NOTIFICATION_TAG.equals(notification.getTag())) {
                notificationManager.cancel(NOTIFICATION_TAG, notification.getId());
            }
        }

        notificationManager.createNotificationChannel(
                new NotificationChannel(
                        APM_NOTIFICATION_CHANNEL,
                        APM_NOTIFICATION_GROUP,
                        NotificationManager.IMPORTANCE_HIGH));

        String title = getString(notificationContent.first);
        String message = getString(notificationContent.second);

        notificationManager.notify(
                NOTIFICATION_TAG,
                SystemMessage.ID.NOTE_BT_APM_NOTIFICATION_VALUE,
                new Notification.Builder(this, APM_NOTIFICATION_CHANNEL)
                        .setAutoCancel(true)
                        .setLocalOnly(true)
                        .setContentTitle(title)
                        .setContentText(message)
                        .setContentIntent(
                                PendingIntent.getActivity(
                                        this,
                                        PendingIntent.FLAG_UPDATE_CURRENT,
                                        new Intent(Intent.ACTION_VIEW)
                                                .setData(Uri.parse(HELP_PAGE_URL))
                                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
                                        PendingIntent.FLAG_IMMUTABLE))
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setStyle(new Notification.BigTextStyle().bigText(message))
                        .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
                        .build());
    }

    /** Return whether the notification has been shown */
    private boolean isFirstTimeNotification(String name) {
        return Settings.Secure.getInt(getContentResolver(), name, 0) == 0;
    }
}
+11 −5
Original line number Diff line number Diff line
@@ -555,11 +555,17 @@ public class AtPhonebook {
                // try caller id lookup
                // TODO: This code is horribly inefficient. I saw it
                // take 7 seconds to process 100 missed calls.
                Cursor c = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver,
                        Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, number),
                        new String[]{
                                PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE
                        }, null, null, null);
                Cursor c =
                        BluetoothMethodProxy.getInstance()
                                .contentResolverQuery(
                                        mContentResolver,
                                        Uri.withAppendedPath(
                                                PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
                                                Uri.encode(number)),
                                        new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE},
                                        null,
                                        null,
                                        null);
                if (c != null) {
                    if (c.moveToFirst()) {
                        name = c.getString(0);
+32 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -40,6 +41,7 @@ import com.android.bluetooth.BluetoothMethodProxy;
import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.util.DevicePolicyUtils;
import com.android.internal.telephony.GsmAlphabet;

import org.junit.After;
@@ -284,6 +286,35 @@ public class AtPhonebookTest {
        verify(mNativeInterface).atResponseString(mTestDevice, expected);
    }

    @Test
    public void processCpbrCommand_doesNotCrashWithEncodingNeededNumber() {
        final String encodingNeededNumber = "###0102124";

        Cursor mockCursorOne = mock(Cursor.class);
        when(mockCursorOne.getCount()).thenReturn(1);
        when(mockCursorOne.getColumnIndex(Phone.TYPE)).thenReturn(1); // TypeColumn
        when(mockCursorOne.getColumnIndex(Phone.NUMBER)).thenReturn(2); // numberColumn
        when(mockCursorOne.getColumnIndex(Phone.DISPLAY_NAME)).thenReturn(-1); // nameColumn
        when(mockCursorOne.getInt(1)).thenReturn(Phone.TYPE_WORK);
        when(mockCursorOne.getString(2)).thenReturn(encodingNeededNumber);
        when(mockCursorOne.moveToNext()).thenReturn(false);
        doReturn(mockCursorOne)
                .when(mHfpMethodProxy)
                .contentResolverQuery(
                        any(),
                        eq(DevicePolicyUtils.getEnterprisePhoneUri(mTargetContext)),
                        any(),
                        any(),
                        any());

        mAtPhonebook.mCurrentPhonebook = "ME";
        mAtPhonebook.mCpbrIndex1 = 1;
        mAtPhonebook.mCpbrIndex2 = 2;

        // This call should not crash
        mAtPhonebook.processCpbrCommand(mTestDevice);
    }

    @Test
    public void setCpbrIndex() {
        int index = 1;
Loading