120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen/*
220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Copyright (C) 2017 The Android Open Source Project
320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen *
420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Licensed under the Apache License, Version 2.0 (the "License");
520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * you may not use this file except in compliance with the License.
620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * You may obtain a copy of the License at
720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen *
820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen *      http://www.apache.org/licenses/LICENSE-2.0
920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen *
1020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Unless required by applicable law or agreed to in writing, software
1120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * distributed under the License is distributed on an "AS IS" BASIS,
1220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * See the License for the specific language governing permissions and
1420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * limitations under the License.
1520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */
1620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
1720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenpackage com.android.server.wifi;
1820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
1920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.app.Notification;
2020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.app.PendingIntent;
2120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.content.Context;
2220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.content.Intent;
2320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.content.res.Resources;
2420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.net.wifi.ScanResult;
25664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadehimport android.util.Log;
2620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
2720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport com.android.internal.R;
2820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport com.android.internal.notification.SystemNotificationChannels;
2920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
3020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen/**
3120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Helper to create notifications for {@link OpenNetworkNotifier}.
3220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */
3320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenpublic class ConnectToNetworkNotificationBuilder {
3420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
3520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /** Intent when user dismissed the "Connect to Network" notification. */
3620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    public static final String ACTION_USER_DISMISSED_NOTIFICATION =
3720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen            "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION";
3820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
3920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /** Intent when user tapped action button to connect to recommended network. */
4020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    public static final String ACTION_CONNECT_TO_NETWORK =
4120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen            "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK";
4220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
4320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /** Intent when user tapped action button to open Wi-Fi Settings. */
4420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    public static final String ACTION_PICK_WIFI_NETWORK =
4520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen            "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK";
4620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
4720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /** Intent when user tapped "Failed to connect" notification to open Wi-Fi Settings. */
4820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    public static final String ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE =
4920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen            "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE";
5020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
51664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /** Extra data added to the Intent to specify the registering network notifier. */
52664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public static final String AVAILABLE_NETWORK_NOTIFIER_TAG =
53664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            "com.android.server.wifi.ConnectToNetworkNotification.AVAILABLE_NETWORK_NOTIFIER_TAG";
54664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
5520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    private Context mContext;
5620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    private Resources mResources;
5720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    private FrameworkFacade mFrameworkFacade;
5820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
5920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    public ConnectToNetworkNotificationBuilder(
6020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen            Context context,
6120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen            FrameworkFacade framework) {
6220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        mContext = context;
6320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        mResources = context.getResources();
6420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        mFrameworkFacade = framework;
6520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
6620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
6720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /**
6820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * Creates the connect to network notification that alerts users of a recommended connectable
6920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * network.
7020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     *
71b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen     * There are two actions - "Options" link to the Wi-Fi picker activity, and "Connect" prompts
72b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen     * the connection to the recommended network.
73b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen     *
74664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * @param notifierTag Unique tag of calling network notifier
75b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen     * @param network The network to be recommended
7620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     */
77664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public Notification createConnectToAvailableNetworkNotification(String notifierTag,
78664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            ScanResult network) {
79664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        CharSequence title;
80664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        switch (notifierTag) {
81664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            case OpenNetworkNotifier.TAG:
82664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                title = mContext.getText(R.string.wifi_available_title);
83664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                break;
84664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            case CarrierNetworkNotifier.TAG:
85664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                title = mContext.getText(R.string.wifi_available_carrier_network_title);
86664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                break;
87664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            default:
88664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                Log.wtf("ConnectToNetworkNotificationBuilder", "Unknown network notifier."
89664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                        + notifierTag);
90664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                return null;
91664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        }
92664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        Notification.Action connectAction = new Notification.Action.Builder(null /* icon */,
93b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen                mResources.getText(R.string.wifi_available_action_connect),
9478e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                getPrivateBroadcast(ACTION_CONNECT_TO_NETWORK, notifierTag)).build();
95664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        Notification.Action allNetworksAction = new Notification.Action.Builder(null /* icon */,
96b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen                mResources.getText(R.string.wifi_available_action_all_networks),
9778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)).build();
9878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh        return createNotificationBuilder(title, network.SSID, notifierTag)
9992c1165b80f0b74421c8d8871fcce1d7d123ac57Mehdi Alizadeh                .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag))
10078e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                .addAction(connectAction)
10178e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                .addAction(allNetworksAction)
10278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                .build();
10320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
10420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
10520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /**
10620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * Creates the notification that indicates the controller is attempting to connect to the
10720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * recommended network.
10820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     *
10978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh     * @param notifierTag Unique tag of the calling network notifier
11020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * @param network The network to be recommended
11120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     */
11278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh    public Notification createNetworkConnectingNotification(String notifierTag,
11378e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh            ScanResult network) {
11420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        return createNotificationBuilder(
11578e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                mContext.getText(R.string.wifi_available_title_connecting), network.SSID,
11678e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                        notifierTag)
11720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */)
11820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .build();
11920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
12020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
12120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /**
12220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * Creates the notification that indicates the controller successfully connected to the
12320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * recommended network.
12420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     *
12578e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh     * @param notifierTag Unique tag of the calling network notifier
12620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * @param network The network to be recommended
12720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     */
12878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh    public Notification createNetworkConnectedNotification(String notifierTag, ScanResult network) {
12920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        return createNotificationBuilder(
13078e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                mContext.getText(R.string.wifi_available_title_connected), network.SSID,
13178e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                        notifierTag)
13220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .build();
13320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
13420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
13520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    /**
13620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * Creates the notification that indicates the controller failed to connect to the recommended
13720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     * network. Tapping this notification opens the wifi picker.
13878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh     *
13978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh     * @param notifierTag Unique tag of the calling network notifier
14020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen     */
14178e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh    public Notification createNetworkFailedNotification(String notifierTag) {
14220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        return createNotificationBuilder(
14320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                mContext.getText(R.string.wifi_available_title_failed_to_connect),
14478e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                mContext.getText(R.string.wifi_available_content_failed_to_connect), notifierTag)
14520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setContentIntent(
14678e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                        getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE,
14778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                                notifierTag))
148b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen                .setAutoCancel(true)
14920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .build();
15020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
15120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
15278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh    private int getNotifierRequestCode(String notifierTag) {
15378e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh        switch (notifierTag) {
15478e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh            case OpenNetworkNotifier.TAG:
15578e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                return 1;
15678e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh            case CarrierNetworkNotifier.TAG:
15778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                return 2;
15878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh        }
15978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh        return 0;
160664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
161664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
162664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    private Notification.Builder createNotificationBuilder(
16378e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh            CharSequence title, CharSequence content, String extraData) {
16420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        return mFrameworkFacade.makeNotificationBuilder(mContext,
16520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                SystemNotificationChannels.NETWORK_AVAILABLE)
16620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setSmallIcon(R.drawable.stat_notify_wifi_in_range)
16720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setTicker(title)
16820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setContentTitle(title)
16920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setContentText(content)
17078e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh                .setDeleteIntent(getPrivateBroadcast(ACTION_USER_DISMISSED_NOTIFICATION, extraData))
17120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setShowWhen(false)
17220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setLocalOnly(true)
17320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                .setColor(mResources.getColor(R.color.system_notification_accent_color,
17420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen                        mContext.getTheme()));
17520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
17620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen
17778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh    private PendingIntent getPrivateBroadcast(String action, String extraData) {
17820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen        Intent intent = new Intent(action).setPackage("android");
17978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh        int requestCode = 0;  // Makes the different kinds of notifications distinguishable
180664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        if (extraData != null) {
181664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            intent.putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, extraData);
18278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh            requestCode = getNotifierRequestCode(extraData);
183664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        }
184664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        return mFrameworkFacade.getBroadcast(mContext, requestCode, intent,
185664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                PendingIntent.FLAG_UPDATE_CURRENT);
18620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen    }
18720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen}
188