/*
 * Copyright (C) 2017 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.server.wm;

import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;

import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;

import android.net.Uri;
import android.os.Bundle;

import com.android.internal.R;
import com.android.server.policy.IconUtilities;

/** Displays an ongoing notification for a process displaying an alert window */
class AlertWindowNotification {
    private static final String CHANNEL_PREFIX = "com.android.server.wm.AlertWindowNotification - ";
    private static final int NOTIFICATION_ID = 0;

    private static int sNextRequestCode = 0;
    private static NotificationChannelGroup sChannelGroup;
    private final int mRequestCode;
    private final WindowManagerService mService;
    private String mNotificationTag;
    private final NotificationManager mNotificationManager;
    private final String mPackageName;
    private boolean mPosted;
    private IconUtilities mIconUtilities;

    AlertWindowNotification(WindowManagerService service, String packageName) {
        mService = service;
        mPackageName = packageName;
        mNotificationManager =
                (NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
        mNotificationTag = CHANNEL_PREFIX + mPackageName;
        mRequestCode = sNextRequestCode++;
        mIconUtilities = new IconUtilities(mService.mContext);
    }

    void post() {
        // We can't create/post the notification while the window manager lock is held since it will
        // end up calling into activity manager. So, we post a message to do it later.
        mService.mH.post(this::onPostNotification);
    }

    /** Cancels the notification */
    void cancel(boolean deleteChannel) {
        // We can't call into NotificationManager with WM lock held since it might call into AM.
        // So, we post a message to do it later.
        mService.mH.post(() -> onCancelNotification(deleteChannel));
    }

    /** Don't call with the window manager lock held! */
    private void onCancelNotification(boolean deleteChannel) {
        if (!mPosted) {
            // Notification isn't currently posted...
            return;
        }
        mPosted = false;
        mNotificationManager.cancel(mNotificationTag, NOTIFICATION_ID);
        if (deleteChannel) {
            mNotificationManager.deleteNotificationChannel(mNotificationTag);
        }
    }

    /** Don't call with the window manager lock held! */
    private void onPostNotification() {
        if (mPosted) {
            // Notification already posted...
            return;
        }
        mPosted = true;

        final Context context = mService.mContext;
        final PackageManager pm = context.getPackageManager();
        final ApplicationInfo aInfo = getApplicationInfo(pm, mPackageName);
        final String appName = (aInfo != null)
                ? pm.getApplicationLabel(aInfo).toString() : mPackageName;

        createNotificationChannel(context, appName);

        final String message = context.getString(R.string.alert_windows_notification_message,
                appName);
        Bundle extras = new Bundle();
        extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {mPackageName});
        final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
                .setOngoing(true)
                .setContentTitle(
                        context.getString(R.string.alert_windows_notification_title, appName))
                .setContentText(message)
                .setSmallIcon(R.drawable.alert_window_layer)
                .setColor(context.getColor(R.color.system_notification_accent_color))
                .setStyle(new Notification.BigTextStyle().bigText(message))
                .setLocalOnly(true)
                .addExtras(extras)
                .setContentIntent(getContentIntent(context, mPackageName));

        if (aInfo != null) {
            final Drawable drawable = pm.getApplicationIcon(aInfo);
            if (drawable != null) {
                final Bitmap bitmap = mIconUtilities.createIconBitmap(drawable);
                builder.setLargeIcon(bitmap);
            }
        }

        mNotificationManager.notify(mNotificationTag, NOTIFICATION_ID, builder.build());
    }

    private PendingIntent getContentIntent(Context context, String packageName) {
        final Intent intent = new Intent(ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.fromParts("package", packageName, null));
        intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
        // Calls into activity manager...
        return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT);
    }

    private void createNotificationChannel(Context context, String appName) {
        if (sChannelGroup == null) {
            sChannelGroup = new NotificationChannelGroup(CHANNEL_PREFIX,
                    mService.mContext.getString(
                            R.string.alert_windows_notification_channel_group_name));
            mNotificationManager.createNotificationChannelGroup(sChannelGroup);
        }

        final String nameChannel =
                context.getString(R.string.alert_windows_notification_channel_name, appName);

        NotificationChannel channel = mNotificationManager.getNotificationChannel(mNotificationTag);
        if (channel != null) {
            return;
        }
        channel = new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN);
        channel.enableLights(false);
        channel.enableVibration(false);
        channel.setBlockableSystem(true);
        channel.setGroup(sChannelGroup.getId());
        channel.setBypassDnd(true);
        mNotificationManager.createNotificationChannel(channel);
    }


    private ApplicationInfo getApplicationInfo(PackageManager pm, String packageName) {
        try {
            return pm.getApplicationInfo(packageName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }
}
