/*
 * Copyright (C) 2018 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;

import android.content.Context;
import android.os.Binder;
import android.service.runtime.DebugEntryProto;
import android.service.runtime.RuntimeServiceInfoProto;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import libcore.timezone.TimeZoneDataFiles;
import libcore.util.CoreLibraryDebug;
import libcore.util.DebugInfo;

import com.android.internal.util.DumpUtils;
import com.android.timezone.distro.DistroException;
import com.android.timezone.distro.DistroVersion;
import com.android.timezone.distro.FileUtils;
import com.android.timezone.distro.TimeZoneDistro;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * This service exists only as a "dumpsys" target which reports information about the status of the
 * runtime and related libraries.
 */
public class RuntimeService extends Binder {

    private static final String TAG = "RuntimeService";

    private final Context mContext;

    public RuntimeService(Context context) {
        mContext = context;
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) {
            return;
        }

        boolean protoFormat = hasOption(args, "--proto");
        ProtoOutputStream proto = null;

        DebugInfo coreLibraryDebugInfo = CoreLibraryDebug.getDebugInfo();
        addTimeZoneApkDebugInfo(coreLibraryDebugInfo);

        if (protoFormat) {
            proto = new ProtoOutputStream(fd);
            reportTimeZoneInfoProto(coreLibraryDebugInfo, proto);
        } else {
            reportTimeZoneInfo(coreLibraryDebugInfo, pw);
        }

        if (protoFormat) {
            proto.flush();
        }
    }

    /** Returns {@code true} if {@code args} contains {@code arg}. */
    private static boolean hasOption(String[] args, String arg) {
        for (String opt : args) {
            if (arg.equals(opt)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Add information to {@link DebugInfo} about the time zone data supplied by the
     * "Time zone updates via APK" feature.
     */
    private static void addTimeZoneApkDebugInfo(DebugInfo coreLibraryDebugInfo) {
        // Add /data tz data set using the DistroVersion class (which libcore cannot use).
        // This update mechanism will be removed after the time zone APEX is launched so this
        // untidiness will disappear with it.
        String debugKeyPrefix = "core_library.timezone.source.data_";
        String versionFileName = TimeZoneDataFiles.getDataTimeZoneFile(
                TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
        addDistroVersionDebugInfo(versionFileName, debugKeyPrefix, coreLibraryDebugInfo);
    }

    /**
     * Prints {@code coreLibraryDebugInfo} to {@code pw}.
     *
     * <p>If you change this method, make sure to modify
     * {@link #reportTimeZoneInfoProto(DebugInfo, ProtoOutputStream)} as well.
     */
    private static void reportTimeZoneInfo(DebugInfo coreLibraryDebugInfo,
            PrintWriter pw) {
        pw.println("Core Library Debug Info: ");
        for (DebugInfo.DebugEntry debugEntry : coreLibraryDebugInfo.getDebugEntries()) {
            pw.print(debugEntry.getKey());
            pw.print(": \"");
            pw.print(debugEntry.getStringValue());
            pw.println("\"");
        }
    }

    /**
     * Adds {@code coreLibraryDebugInfo} to {@code protoStream}.
     *
     * <p>If you change this method, make sure to modify
     * {@link #reportTimeZoneInfo(DebugInfo, PrintWriter)}.
     */
    private static void reportTimeZoneInfoProto(
            DebugInfo coreLibraryDebugInfo, ProtoOutputStream protoStream) {
        for (DebugInfo.DebugEntry debugEntry : coreLibraryDebugInfo.getDebugEntries()) {
            long entryToken = protoStream.start(RuntimeServiceInfoProto.DEBUG_ENTRY);
            protoStream.write(DebugEntryProto.KEY, debugEntry.getKey());
            protoStream.write(DebugEntryProto.STRING_VALUE, debugEntry.getStringValue());
            protoStream.end(entryToken);
        }
    }

    /**
     * Adds version information to {@code debugInfo} from the distro_version file that may exist
     * at {@code distroVersionFileName}. If the file does not exist or cannot be read this is
     * reported as debug information too.
     */
    private static void addDistroVersionDebugInfo(String distroVersionFileName,
            String debugKeyPrefix, DebugInfo debugInfo) {
        File file = new File(distroVersionFileName);
        String statusKey = debugKeyPrefix + "status";
        if (file.exists()) {
            try {
                byte[] versionBytes =
                        FileUtils.readBytes(file, DistroVersion.DISTRO_VERSION_FILE_LENGTH);
                DistroVersion distroVersion = DistroVersion.fromBytes(versionBytes);
                String formatVersionString = distroVersion.formatMajorVersion + "."
                        + distroVersion.formatMinorVersion;
                debugInfo.addStringEntry(statusKey, "OK")
                        .addStringEntry(debugKeyPrefix + "formatVersion", formatVersionString)
                        .addStringEntry(debugKeyPrefix + "rulesVersion",
                                distroVersion.rulesVersion)
                        .addStringEntry(debugKeyPrefix + "revision",
                                distroVersion.revision);
            } catch (IOException | DistroException e) {
                debugInfo.addStringEntry(statusKey, "ERROR");
                debugInfo.addStringEntry(debugKeyPrefix + "exception_class",
                        e.getClass().getName());
                debugInfo.addStringEntry(debugKeyPrefix + "exception_msg", e.getMessage());
                logMessage("Error reading " + file, e);
            }
        } else {
            debugInfo.addStringEntry(statusKey, "NOT_FOUND");
        }
    }

    private static void logMessage(String msg, Throwable t) {
        Slog.v(TAG, msg, t);
    }
}
