/*
 * 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.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.Icon;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;

import libcore.io.IoUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Deque;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Class to save shortcut bitmaps on a worker thread.
 *
 * The methods with the "Locked" prefix must be called with the service lock held.
 */
public class ShortcutBitmapSaver {
    private static final String TAG = ShortcutService.TAG;
    private static final boolean DEBUG = ShortcutService.DEBUG;

    private static final boolean ADD_DELAY_BEFORE_SAVE_FOR_TEST = false; // DO NOT submit with true.
    private static final long SAVE_DELAY_MS_FOR_TEST = 1000; // DO NOT submit with true.

    /**
     * Before saving shortcuts.xml, and returning icons to the launcher, we wait for all pending
     * saves to finish.  However if it takes more than this long, we just give up and proceed.
     */
    private final long SAVE_WAIT_TIMEOUT_MS = 30 * 1000;

    private final ShortcutService mService;

    /**
     * Bitmaps are saved on this thread.
     *
     * Note: Just before saving shortcuts into the XML, we need to wait on all pending saves to
     * finish, and we need to do it with the service lock held, which would still block incoming
     * binder calls, meaning saving bitmaps *will* still actually block API calls too, which is
     * not ideal but fixing it would be tricky, so this is still a known issue on the current
     * version.
     *
     * In order to reduce the conflict, we use an own thread for this purpose, rather than
     * reusing existing background threads, and also to avoid possible deadlocks.
     */
    private final Executor mExecutor = new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>());

    /** Represents a bitmap to save. */
    private static class PendingItem {
        /** Hosting shortcut. */
        public final ShortcutInfo shortcut;

        /** Compressed bitmap data. */
        public final byte[] bytes;

        /** Instantiated time, only for dogfooding. */
        private final long mInstantiatedUptimeMillis; // Only for dumpsys.

        private PendingItem(ShortcutInfo shortcut, byte[] bytes) {
            this.shortcut = shortcut;
            this.bytes = bytes;
            mInstantiatedUptimeMillis = SystemClock.uptimeMillis();
        }

        @Override
        public String toString() {
            return "PendingItem{size=" + bytes.length
                    + " age=" + (SystemClock.uptimeMillis() - mInstantiatedUptimeMillis) + "ms"
                    + " shortcut=" + shortcut.toInsecureString()
                    + "}";
        }
    }

    @GuardedBy("mPendingItems")
    private final Deque<PendingItem> mPendingItems = new LinkedBlockingDeque<>();

    public ShortcutBitmapSaver(ShortcutService service) {
        mService = service;
        // mLock = lock;
    }

    public boolean waitForAllSavesLocked() {
        final CountDownLatch latch = new CountDownLatch(1);

        mExecutor.execute(() -> latch.countDown());

        try {
            if (latch.await(SAVE_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                return true;
            }
            mService.wtf("Timed out waiting on saving bitmaps.");
        } catch (InterruptedException e) {
            Slog.w(TAG, "interrupted");
        }
        return false;
    }

    /**
     * Wait for all pending saves to finish, and then return the given shortcut's bitmap path.
     */
    @Nullable
    public String getBitmapPathMayWaitLocked(ShortcutInfo shortcut) {
        final boolean success = waitForAllSavesLocked();
        if (success && shortcut.hasIconFile()) {
            return shortcut.getBitmapPath();
        } else {
            return null;
        }
    }

    public void removeIcon(ShortcutInfo shortcut) {
        // Do not remove the actual bitmap file yet, because if the device crashes before saving
        // the XML we'd lose the icon.  We just remove all dangling files after saving the XML.
        shortcut.setIconResourceId(0);
        shortcut.setIconResName(null);
        shortcut.setBitmapPath(null);
        shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE |
                ShortcutInfo.FLAG_ADAPTIVE_BITMAP | ShortcutInfo.FLAG_HAS_ICON_RES |
                ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
    }

    public void saveBitmapLocked(ShortcutInfo shortcut,
            int maxDimension, CompressFormat format, int quality) {
        final Icon icon = shortcut.getIcon();
        Preconditions.checkNotNull(icon);

        final Bitmap original = icon.getBitmap();
        if (original == null) {
            Log.e(TAG, "Missing icon: " + shortcut);
            return;
        }

        // Compress it and enqueue to the requests.
        final byte[] bytes;
        final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
        try {
            // compress() triggers a slow call, but in this case it's needed to save RAM and also
            // the target bitmap is of an icon size, so let's just permit it.
            StrictMode.setThreadPolicy(new ThreadPolicy.Builder(oldPolicy)
                    .permitCustomSlowCalls()
                    .build());
            final Bitmap shrunk = mService.shrinkBitmap(original, maxDimension);
            try {
                try (final ByteArrayOutputStream out = new ByteArrayOutputStream(64 * 1024)) {
                    if (!shrunk.compress(format, quality, out)) {
                        Slog.wtf(ShortcutService.TAG, "Unable to compress bitmap");
                    }
                    out.flush();
                    bytes = out.toByteArray();
                    out.close();
                }
            } finally {
                if (shrunk != original) {
                    shrunk.recycle();
                }
            }
        } catch (IOException | RuntimeException | OutOfMemoryError e) {
            Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
            return;
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }

        shortcut.addFlags(
                ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);

        if (icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
            shortcut.addFlags(ShortcutInfo.FLAG_ADAPTIVE_BITMAP);
        }

        // Enqueue a pending save.
        final PendingItem item = new PendingItem(shortcut, bytes);
        synchronized (mPendingItems) {
            mPendingItems.add(item);
        }

        if (DEBUG) {
            Slog.d(TAG, "Scheduling to save: " + item);
        }

        mExecutor.execute(mRunnable);
    }

    private final Runnable mRunnable = () -> {
        // Process all pending items.
        while (processPendingItems()) {
        }
    };

    /**
     * Takes a {@link PendingItem} from {@link #mPendingItems} and process it.
     *
     * Must be called {@link #mExecutor}.
     *
     * @return true if it processed an item, false if the queue is empty.
     */
    private boolean processPendingItems() {
        if (ADD_DELAY_BEFORE_SAVE_FOR_TEST) {
            Slog.w(TAG, "*** ARTIFICIAL SLEEP ***");
            try {
                Thread.sleep(SAVE_DELAY_MS_FOR_TEST);
            } catch (InterruptedException e) {
            }
        }

        // NOTE:
        // Ideally we should be holding the service lock when accessing shortcut instances,
        // but that could cause a deadlock so we don't do it.
        //
        // Instead, waitForAllSavesLocked() uses a latch to make sure changes made on this
        // thread is visible on the caller thread.

        ShortcutInfo shortcut = null;
        try {
            final PendingItem item;

            synchronized (mPendingItems) {
                if (mPendingItems.size() == 0) {
                    return false;
                }
                item = mPendingItems.pop();
            }

            shortcut = item.shortcut;

            // See if the shortcut is still relevant. (It might have been removed already.)
            if (!shortcut.isIconPendingSave()) {
                return true;
            }

            if (DEBUG) {
                Slog.d(TAG, "Saving bitmap: " + item);
            }

            File file = null;
            try {
                final FileOutputStreamWithPath out = mService.openIconFileForWrite(
                        shortcut.getUserId(), shortcut);
                file = out.getFile();

                try {
                    out.write(item.bytes);
                } finally {
                    IoUtils.closeQuietly(out);
                }

                shortcut.setBitmapPath(file.getAbsolutePath());

            } catch (IOException | RuntimeException e) {
                Slog.e(ShortcutService.TAG, "Unable to write bitmap to file", e);

                if (file != null && file.exists()) {
                    file.delete();
                }
                return true;
            }
        } finally {
            if (DEBUG) {
                Slog.d(TAG, "Saved bitmap.");
            }
            if (shortcut != null) {
                if (shortcut.getBitmapPath() == null) {
                    removeIcon(shortcut);
                }

                // Whatever happened, remove this flag.
                shortcut.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
            }
        }
        return true;
    }

    public void dumpLocked(@NonNull PrintWriter pw, @NonNull String prefix) {
        synchronized (mPendingItems) {
            final int N = mPendingItems.size();
            pw.print(prefix);
            pw.println("Pending saves: Num=" + N + " Executor=" + mExecutor);

            for (PendingItem item : mPendingItems) {
                pw.print(prefix);
                pw.print("  ");
                pw.println(item);
            }
        }
    }
}
