/*
 * Copyright (C) 2013 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 static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import android.annotation.UserIdInt;
import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.IBinder;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;

import com.android.server.pm.UserManagerService;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/**
 * The base class for services running in the system process. Override and implement
 * the lifecycle event callback methods as needed.
 * <p>
 * The lifecycle of a SystemService:
 * </p><ul>
 * <li>The constructor is called and provided with the system {@link Context}
 * to initialize the system service.
 * <li>{@link #onStart()} is called to get the service running.  The service should
 * publish its binder interface at this point using
 * {@link #publishBinderService(String, IBinder)}.  It may also publish additional
 * local interfaces that other services within the system server may use to access
 * privileged internal functions.
 * <li>Then {@link #onBootPhase(int)} is called as many times as there are boot phases
 * until {@link #PHASE_BOOT_COMPLETED} is sent, which is the last boot phase. Each phase
 * is an opportunity to do special work, like acquiring optional service dependencies,
 * waiting to see if SafeMode is enabled, or registering with a service that gets
 * started after this one.
 * </ul><p>
 * NOTE: All lifecycle methods are called from the system server's main looper thread.
 * </p>
 *
 * {@hide}
 */
@SystemApi(client = Client.SYSTEM_SERVER)
public abstract class SystemService {

    /** @hide */
    // TODO(b/133242016) STOPSHIP: change to false before R ships
    protected static final boolean DEBUG_USER = true;

    /*
     * The earliest boot phase the system send to system services on boot.
     */
    public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100;

    /**
     * After receiving this boot phase, services can obtain lock settings data.
     */
    public static final int PHASE_LOCK_SETTINGS_READY = 480;

    /**
     * After receiving this boot phase, services can safely call into core system services
     * such as the PowerManager or PackageManager.
     */
    public static final int PHASE_SYSTEM_SERVICES_READY = 500;

    /**
     * After receiving this boot phase, services can safely call into device specific services.
     */
    public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520;

    /**
     * After receiving this boot phase, services can broadcast Intents.
     */
    public static final int PHASE_ACTIVITY_MANAGER_READY = 550;

    /**
     * After receiving this boot phase, services can start/bind to third party apps.
     * Apps will be able to make Binder calls into services at this point.
     */
    public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;

    /**
     * After receiving this boot phase, services can allow user interaction with the device.
     * This phase occurs when boot has completed and the home application has started.
     * System services may prefer to listen to this phase rather than registering a
     * broadcast receiver for {@link android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED}
     * to reduce overall latency.
     */
    public static final int PHASE_BOOT_COMPLETED = 1000;

    /** @hide */
    @IntDef(flag = true, prefix = { "PHASE_" }, value = {
            PHASE_WAIT_FOR_DEFAULT_DISPLAY,
            PHASE_LOCK_SETTINGS_READY,
            PHASE_SYSTEM_SERVICES_READY,
            PHASE_DEVICE_SPECIFIC_SERVICES_READY,
            PHASE_ACTIVITY_MANAGER_READY,
            PHASE_THIRD_PARTY_APPS_CAN_START,
            PHASE_BOOT_COMPLETED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface BootPhase {}

    private final Context mContext;

    /**
     * Class representing user in question in the lifecycle callbacks.
     * @hide
     */
    @SystemApi(client = Client.SYSTEM_SERVER)
    public static final class TargetUser {
        @NonNull
        private final UserInfo mUserInfo;

        /** @hide */
        public TargetUser(@NonNull UserInfo userInfo) {
            mUserInfo = userInfo;
        }

        /**
         * @return The information about the user. <b>NOTE: </b> this is a "live" object
         * referenced by {@link UserManagerService} and hence should not be modified.
         *
         * @hide
         */
        @NonNull
        public UserInfo getUserInfo() {
            return mUserInfo;
        }

        /**
         * @return the target {@link UserHandle}.
         */
        @NonNull
        public UserHandle getUserHandle() {
            return mUserInfo.getUserHandle();
        }

        /**
         * @return the integer user id
         *
         * @hide
         */
        public int getUserIdentifier() {
            return mUserInfo.id;
        }
    }

    /**
     * Initializes the system service.
     * <p>
     * Subclasses must define a single argument constructor that accepts the context
     * and passes it to super.
     * </p>
     *
     * @param context The system server context.
     */
    public SystemService(@NonNull Context context) {
        mContext = context;
    }

    /**
     * Gets the system context.
     */
    @NonNull
    public final Context getContext() {
        return mContext;
    }

    /**
     * Get the system UI context. This context is to be used for displaying UI. It is themable,
     * which means resources can be overridden at runtime. Do not use to retrieve properties that
     * configure the behavior of the device that is not UX related.
     *
     * @hide
     */
    public final Context getUiContext() {
        // This has already been set up by the time any SystemServices are created.
        return ActivityThread.currentActivityThread().getSystemUiContext();
    }

    /**
     * Returns true if the system is running in safe mode.
     * TODO: we should define in which phase this becomes valid
     *
     * @hide
     */
    public final boolean isSafeMode() {
        return getManager().isSafeMode();
    }

    /**
     * Called when the system service should publish a binder service using
     * {@link #publishBinderService(String, IBinder).}
     */
    public abstract void onStart();

    /**
     * Called on each phase of the boot process. Phases before the service's start phase
     * (as defined in the @Service annotation) are never received.
     *
     * @param phase The current boot phase.
     */
    public void onBootPhase(@BootPhase int phase) {}

    /**
     * Checks if the service should be available for the given user.
     *
     * <p>By default returns {@code true}, but subclasses should extend for optimization, if they
     * don't support some types (like headless system user).
     */
    public boolean isSupportedUser(@NonNull TargetUser user) {
        return true;
    }

    /**
     * Helper method used to dump which users are {@link #onStartUser(TargetUser) supported}.
     *
     * @hide
     */
    protected void dumpSupportedUsers(@NonNull PrintWriter pw, @NonNull String prefix) {
        final List<UserInfo> allUsers = UserManager.get(mContext).getUsers();
        final List<Integer> supportedUsers = new ArrayList<>(allUsers.size());
        for (UserInfo user : allUsers) {
            supportedUsers.add(user.id);
        }
        if (allUsers.isEmpty()) {
            pw.print(prefix); pw.println("No supported users");
        } else {
            final int size = supportedUsers.size();
            pw.print(prefix); pw.print(size); pw.print(" supported user");
            if (size > 1) pw.print("s");
            pw.print(": "); pw.println(supportedUsers);
        }
    }

    /**
     * @deprecated subclasses should extend {@link #onStartUser(TargetUser)} instead
     * (which by default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onStartUser(@UserIdInt int userId) {}

    /**
     * @deprecated subclasses should extend {@link #onStartUser(TargetUser)} instead
     * (which by default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onStartUser(@NonNull UserInfo userInfo) {
        onStartUser(userInfo.id);
    }

    /**
     * Called when a new user is starting, for system services to initialize any per-user
     * state they maintain for running users.
     *
     * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
     * this user.
     *
     * @param user target user
     */
    public void onStartUser(@NonNull TargetUser user) {
        onStartUser(user.getUserInfo());
    }

    /**
     * @deprecated subclasses should extend {@link #onUnlockUser(TargetUser)} instead (which by
     * default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onUnlockUser(@UserIdInt int userId) {}

    /**
     * @deprecated subclasses should extend {@link #onUnlockUser(TargetUser)} instead (which by
     * default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onUnlockUser(@NonNull UserInfo userInfo) {
        onUnlockUser(userInfo.id);
    }

    /**
     * Called when an existing user is in the process of being unlocked. This
     * means the credential-encrypted storage for that user is now available,
     * and encryption-aware component filtering is no longer in effect.
     * <p>
     * While dispatching this event to services, the user is in the
     * {@code STATE_RUNNING_UNLOCKING} state, and once dispatching is finished
     * the user will transition into the {@code STATE_RUNNING_UNLOCKED} state.
     * Code written inside system services should use
     * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of
     * these states.
     * <p>
     * This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
     * this user.
     *
     * @param user target user
     */
    public void onUnlockUser(@NonNull TargetUser user) {
        onUnlockUser(user.getUserInfo());
    }

    /**
     * @deprecated subclasses should extend {@link #onSwitchUser(TargetUser, TargetUser)} instead
     * (which by default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onSwitchUser(@UserIdInt int toUserId) {}

    /**
     * @deprecated subclasses should extend {@link #onSwitchUser(TargetUser, TargetUser)} instead
     * (which by default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onSwitchUser(@Nullable UserInfo from, @NonNull UserInfo to) {
        onSwitchUser(to.id);
    }

    /**
     * Called when switching to a different foreground user, for system services that have
     * special behavior for whichever user is currently in the foreground.  This is called
     * before any application processes are aware of the new user.
     *
     * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
     * either of the users ({@code from} or {@code to}).
     *
     * <b>NOTE: </b> both {@code from} and {@code to} are "live" objects
     * referenced by {@link UserManagerService} and hence should not be modified.
     *
     * @param from the user switching from
     * @param to the user switching to
     */
    public void onSwitchUser(@Nullable TargetUser from, @NonNull TargetUser to) {
        onSwitchUser((from == null ? null : from.getUserInfo()), to.getUserInfo());
    }

    /**
     * @deprecated subclasses should extend {@link #onStopUser(TargetUser)} instead
     * (which by default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onStopUser(@UserIdInt int userId) {}

    /**
     * @deprecated subclasses should extend {@link #onStopUser(TargetUser)} instead
     * (which by default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onStopUser(@NonNull UserInfo user) {
        onStopUser(user.id);

    }

    /**
     * Called when an existing user is stopping, for system services to finalize any per-user
     * state they maintain for running users.  This is called prior to sending the SHUTDOWN
     * broadcast to the user; it is a good place to stop making use of any resources of that
     * user (such as binding to a service running in the user).
     *
     * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
     * this user.
     *
     * <p>NOTE: This is the last callback where the callee may access the target user's CE storage.
     *
     * @param user target user
     */
    public void onStopUser(@NonNull TargetUser user) {
        onStopUser(user.getUserInfo());
    }

    /**
     * @deprecated subclasses should extend {@link #onCleanupUser(TargetUser)} instead (which by
     * default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onCleanupUser(@UserIdInt int userId) {}

    /**
     * @deprecated subclasses should extend {@link #onCleanupUser(TargetUser)} instead (which by
     * default calls this method).
     *
     * @hide
     */
    @Deprecated
    public void onCleanupUser(@NonNull UserInfo user) {
        onCleanupUser(user.id);
    }

    /**
     * Called when an existing user is stopping, for system services to finalize any per-user
     * state they maintain for running users.  This is called after all application process
     * teardown of the user is complete.
     *
     * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
     * this user.
     *
     * <p>NOTE: When this callback is called, the CE storage for the target user may not be
     * accessible already.  Use {@link #onStopUser(TargetUser)} instead if you need to access the CE
     * storage.
     *
     * @param user target user
     */
    public void onCleanupUser(@NonNull TargetUser user) {
        onCleanupUser(user.getUserInfo());
    }

    /**
     * Publish the service so it is accessible to other services and apps.
     *
     * @param name the name of the new service
     * @param service the service object
     */
    protected final void publishBinderService(@NonNull String name, @NonNull IBinder service) {
        publishBinderService(name, service, false);
    }

    /**
     * Publish the service so it is accessible to other services and apps.
     *
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * to access this service
     */
    protected final void publishBinderService(@NonNull String name, @NonNull IBinder service,
            boolean allowIsolated) {
        publishBinderService(name, service, allowIsolated, DUMP_FLAG_PRIORITY_DEFAULT);
    }

    /**
     * Publish the service so it is accessible to other services and apps.
     *
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * to access this service
     * @param dumpPriority supported dump priority levels as a bitmask
     *
     * @hide
     */
    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated, int dumpPriority) {
        ServiceManager.addService(name, service, allowIsolated, dumpPriority);
    }

    /**
     * Get a binder service by its name.
     *
     * @hide
     */
    protected final IBinder getBinderService(String name) {
        return ServiceManager.getService(name);
    }

    /**
     * Publish the service so it is only accessible to the system process.
     *
     * @hide
     */
    protected final <T> void publishLocalService(Class<T> type, T service) {
        LocalServices.addService(type, service);
    }

    /**
     * Get a local service by interface.
     *
     * @hide
     */
    protected final <T> T getLocalService(Class<T> type) {
        return LocalServices.getService(type);
    }

    private SystemServiceManager getManager() {
        return LocalServices.getService(SystemServiceManager.class);
    }
}
