/*
 * 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 android.app.slice;

import static android.content.pm.PackageManager.PERMISSION_DENIED;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
import android.annotation.WorkerThread;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PermissionResult;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Log;

import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * Class to handle interactions with {@link Slice}s.
 * <p>
 * The SliceManager manages permissions and pinned state for slices.
 */
@SystemService(Context.SLICE_SERVICE)
public class SliceManager {

    private static final String TAG = "SliceManager";

    /**
     * @hide
     */
    public static final String ACTION_REQUEST_SLICE_PERMISSION =
            "com.android.intent.action.REQUEST_SLICE_PERMISSION";

    /**
     * Category used to resolve intents that can be rendered as slices.
     * <p>
     * This category should be included on intent filters on providers that extend
     * {@link SliceProvider}.
     * @see SliceProvider
     * @see SliceProvider#onMapIntentToUri(Intent)
     * @see #mapIntentToUri(Intent)
     */
    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_SLICE = "android.app.slice.category.SLICE";

    /**
     * The meta-data key that allows an activity to easily be linked directly to a slice.
     * <p>
     * An activity can be statically linked to a slice uri by including a meta-data item
     * for this key that contains a valid slice uri for the same application declaring
     * the activity.
     *
     * <pre class="prettyprint">
     * {@literal
     * <activity android:name="com.example.mypkg.MyActivity">
     *     <meta-data android:name="android.metadata.SLICE_URI"
     *                android:value="content://com.example.mypkg/main_slice" />
     *  </activity>}
     * </pre>
     *
     * @see #mapIntentToUri(Intent)
     * @see SliceProvider#onMapIntentToUri(Intent)
     */
    public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";

    private final ISliceManager mService;
    private final Context mContext;
    private final IBinder mToken = new Binder();

    /**
     * @hide
     */
    public SliceManager(Context context, Handler handler) throws ServiceNotFoundException {
        mContext = context;
        mService = ISliceManager.Stub.asInterface(
                ServiceManager.getServiceOrThrow(Context.SLICE_SERVICE));
    }

    /**
     * Ensures that a slice is in a pinned state.
     * <p>
     * Pinned state is not persisted across reboots, so apps are expected to re-pin any slices
     * they still care about after a reboot.
     * <p>
     * This may only be called by apps that are the default launcher for the device
     * or the default voice interaction service. Otherwise will throw {@link SecurityException}.
     *
     * @param uri The uri of the slice being pinned.
     * @param specs The list of supported {@link SliceSpec}s of the callback.
     * @see SliceProvider#onSlicePinned(Uri)
     * @see Intent#ACTION_ASSIST
     * @see Intent#CATEGORY_HOME
     */
    public void pinSlice(@NonNull Uri uri, @NonNull Set<SliceSpec> specs) {
        try {
            mService.pinSlice(mContext.getPackageName(), uri,
                    specs.toArray(new SliceSpec[specs.size()]), mToken);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @deprecated TO BE REMOVED
     * @removed
     */
    @Deprecated
    public void pinSlice(@NonNull Uri uri, @NonNull List<SliceSpec> specs) {
        pinSlice(uri, new ArraySet<>(specs));
    }

    /**
     * Remove a pin for a slice.
     * <p>
     * If the slice has no other pins/callbacks then the slice will be unpinned.
     * <p>
     * This may only be called by apps that are the default launcher for the device
     * or the default voice interaction service. Otherwise will throw {@link SecurityException}.
     *
     * @param uri The uri of the slice being unpinned.
     * @see #pinSlice
     * @see SliceProvider#onSliceUnpinned(Uri)
     * @see Intent#ACTION_ASSIST
     * @see Intent#CATEGORY_HOME
     */
    public void unpinSlice(@NonNull Uri uri) {
        try {
            mService.unpinSlice(mContext.getPackageName(), uri, mToken);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     */
    public boolean hasSliceAccess() {
        try {
            return mService.hasSliceAccess(mContext.getPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the current set of specs for a pinned slice.
     * <p>
     * This is the set of specs supported for a specific pinned slice. It will take
     * into account all clients and returns only specs supported by all.
     * @see SliceSpec
     */
    public @NonNull Set<SliceSpec> getPinnedSpecs(Uri uri) {
        try {
            return new ArraySet<>(Arrays.asList(mService.getPinnedSpecs(uri,
                    mContext.getPackageName())));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the list of currently pinned slices for this app.
     * @see SliceProvider#onSlicePinned
     */
    public @NonNull List<Uri> getPinnedSlices() {
        try {
            return Arrays.asList(mService.getPinnedSlices(mContext.getPackageName()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Obtains a list of slices that are descendants of the specified Uri.
     * <p>
     * Not all slice providers will implement this functionality, in which case,
     * an empty collection will be returned.
     *
     * @param uri The uri to look for descendants under.
     * @return All slices within the space.
     * @see SliceProvider#onGetSliceDescendants(Uri)
     */
    @WorkerThread
    public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) {
        ContentResolver resolver = mContext.getContentResolver();
        try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
            Bundle extras = new Bundle();
            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
            final Bundle res = provider.call(SliceProvider.METHOD_GET_DESCENDANTS, null, extras);
            return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS);
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to get slice descendants", e);
        }
        return Collections.emptyList();
    }

    /**
     * Turns a slice Uri into slice content.
     *
     * @param uri The URI to a slice provider
     * @param supportedSpecs List of supported specs.
     * @return The Slice provided by the app or null if none is given.
     * @see Slice
     */
    public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull Set<SliceSpec> supportedSpecs) {
        Preconditions.checkNotNull(uri, "uri");
        ContentResolver resolver = mContext.getContentResolver();
        try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
            if (provider == null) {
                Log.w(TAG, String.format("Unknown URI: %s", uri));
                return null;
            }
            Bundle extras = new Bundle();
            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
                    new ArrayList<>(supportedSpecs));
            final Bundle res = provider.call(SliceProvider.METHOD_SLICE, null, extras);
            Bundle.setDefusable(res, true);
            if (res == null) {
                return null;
            }
            return res.getParcelable(SliceProvider.EXTRA_SLICE);
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
            return null;
        }
    }

    /**
     * @deprecated TO BE REMOVED
     * @removed
     */
    @Deprecated
    public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) {
        return bindSlice(uri, new ArraySet<>(supportedSpecs));
    }

    /**
     * Turns a slice intent into a slice uri. Expects an explicit intent.
     * <p>
     * This goes through a several stage resolution process to determine if any slice
     * can represent this intent.
     * <ol>
     *  <li> If the intent contains data that {@link ContentResolver#getType} is
     *  {@link SliceProvider#SLICE_TYPE} then the data will be returned.</li>
     *  <li>If the intent explicitly points at an activity, and that activity has
     *  meta-data for key {@link #SLICE_METADATA_KEY}, then the Uri specified there will be
     *  returned.</li>
     *  <li>Lastly, if the intent with {@link #CATEGORY_SLICE} added resolves to a provider, then
     *  the provider will be asked to {@link SliceProvider#onMapIntentToUri} and that result
     *  will be returned.</li>
     *  <li>If no slice is found, then {@code null} is returned.</li>
     * </ol>
     * @param intent The intent associated with a slice.
     * @return The Slice Uri provided by the app or null if none exists.
     * @see Slice
     * @see SliceProvider#onMapIntentToUri(Intent)
     * @see Intent
     */
    public @Nullable Uri mapIntentToUri(@NonNull Intent intent) {
        ContentResolver resolver = mContext.getContentResolver();
        final Uri staticUri = resolveStatic(intent, resolver);
        if (staticUri != null) return staticUri;
        // Otherwise ask the app
        String authority = getAuthority(intent);
        if (authority == null) return null;
        Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
                .authority(authority).build();
        try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
            if (provider == null) {
                Log.w(TAG, String.format("Unknown URI: %s", uri));
                return null;
            }
            Bundle extras = new Bundle();
            extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
            final Bundle res = provider.call(SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras);
            if (res == null) {
                return null;
            }
            return res.getParcelable(SliceProvider.EXTRA_SLICE);
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
            return null;
        }
    }

    private String getAuthority(Intent intent) {
        Intent queryIntent = new Intent(intent);
        if (!queryIntent.hasCategory(CATEGORY_SLICE)) {
            queryIntent.addCategory(CATEGORY_SLICE);
        }
        List<ResolveInfo> providers =
                mContext.getPackageManager().queryIntentContentProviders(queryIntent, 0);
        return providers != null && !providers.isEmpty() ? providers.get(0).providerInfo.authority
                : null;
    }

    private Uri resolveStatic(@NonNull Intent intent, ContentResolver resolver) {
        Preconditions.checkNotNull(intent, "intent");
        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
                || intent.getData() != null,
                "Slice intent must be explicit %s", intent);

        // Check if the intent has data for the slice uri on it and use that
        final Uri intentData = intent.getData();
        if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) {
            return intentData;
        }
        // There are no providers, see if this activity has a direct link.
        ResolveInfo resolve = mContext.getPackageManager().resolveActivity(intent,
                PackageManager.GET_META_DATA);
        if (resolve != null && resolve.activityInfo != null
                && resolve.activityInfo.metaData != null
                && resolve.activityInfo.metaData.containsKey(SLICE_METADATA_KEY)) {
            return Uri.parse(
                    resolve.activityInfo.metaData.getString(SLICE_METADATA_KEY));
        }
        return null;
    }

    /**
     * Turns a slice intent into slice content. Is a shortcut to perform the action
     * of both {@link #mapIntentToUri(Intent)} and {@link #bindSlice(Uri, Set)} at once.
     *
     * @param intent The intent associated with a slice.
     * @param supportedSpecs List of supported specs.
     * @return The Slice provided by the app or null if none is given.
     * @see Slice
     * @see SliceProvider#onMapIntentToUri(Intent)
     * @see Intent
     */
    public @Nullable Slice bindSlice(@NonNull Intent intent,
            @NonNull Set<SliceSpec> supportedSpecs) {
        Preconditions.checkNotNull(intent, "intent");
        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
                || intent.getData() != null,
                "Slice intent must be explicit %s", intent);
        ContentResolver resolver = mContext.getContentResolver();
        final Uri staticUri = resolveStatic(intent, resolver);
        if (staticUri != null) return bindSlice(staticUri, supportedSpecs);
        // Otherwise ask the app
        String authority = getAuthority(intent);
        if (authority == null) return null;
        Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
                .authority(authority).build();
        try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
            if (provider == null) {
                Log.w(TAG, String.format("Unknown URI: %s", uri));
                return null;
            }
            Bundle extras = new Bundle();
            extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
            final Bundle res = provider.call(SliceProvider.METHOD_MAP_INTENT, null, extras);
            if (res == null) {
                return null;
            }
            return res.getParcelable(SliceProvider.EXTRA_SLICE);
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
            return null;
        }
    }

    /**
     * @deprecated TO BE REMOVED.
     * @removed
     */
    @Deprecated
    @Nullable
    public Slice bindSlice(@NonNull Intent intent,
            @NonNull List<SliceSpec> supportedSpecs) {
        return bindSlice(intent, new ArraySet<>(supportedSpecs));
    }

    /**
     * Determine whether a particular process and user ID has been granted
     * permission to access a specific slice URI.
     *
     * @param uri The uri that is being checked.
     * @param pid The process ID being checked against.  Must be &gt; 0.
     * @param uid The user ID being checked against.  A uid of 0 is the root
     * user, which will pass every permission check.
     *
     * @return {@link PackageManager#PERMISSION_GRANTED} if the given
     * pid/uid is allowed to access that uri, or
     * {@link PackageManager#PERMISSION_DENIED} if it is not.
     *
     * @see #grantSlicePermission(String, Uri)
     */
    public @PermissionResult int checkSlicePermission(@NonNull Uri uri, int pid, int uid) {
        try {
            return mService.checkSlicePermission(uri, mContext.getPackageName(), null, pid, uid,
                    null);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Grant permission to access a specific slice Uri to another package.
     *
     * @param toPackage The package you would like to allow to access the Uri.
     * @param uri The Uri you would like to grant access to.
     *
     * @see #revokeSlicePermission
     */
    public void grantSlicePermission(@NonNull String toPackage, @NonNull Uri uri) {
        try {
            mService.grantSlicePermission(mContext.getPackageName(), toPackage, uri);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove permissions to access a particular content provider Uri
     * that were previously added with {@link #grantSlicePermission} for a specific target
     * package.  The given Uri will match all previously granted Uris that are the same or a
     * sub-path of the given Uri.  That is, revoking "content://foo/target" will
     * revoke both "content://foo/target" and "content://foo/target/sub", but not
     * "content://foo".  It will not remove any prefix grants that exist at a
     * higher level.
     *
     * @param toPackage The package you would like to allow to access the Uri.
     * @param uri The Uri you would like to revoke access to.
     *
     * @see #grantSlicePermission
     */
    public void revokeSlicePermission(@NonNull String toPackage, @NonNull Uri uri) {
        try {
            mService.revokeSlicePermission(mContext.getPackageName(), toPackage, uri);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Does the permission check to see if a caller has access to a specific slice.
     * @hide
     */
    public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid,
            String[] autoGrantPermissions) {
        try {
            if (UserHandle.isSameApp(uid, Process.myUid())) {
                return;
            }
            if (pkg == null) {
                throw new SecurityException("No pkg specified");
            }
            int result = mService.checkSlicePermission(uri, mContext.getPackageName(), pkg, pid,
                    uid, autoGrantPermissions);
            if (result == PERMISSION_DENIED) {
                throw new SecurityException("User " + uid + " does not have slice permission for "
                        + uri + ".");
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Called by SystemUI to grant a slice permission after a dialog is shown.
     * @hide
     */
    public void grantPermissionFromUser(Uri uri, String pkg, boolean allSlices) {
        try {
            mService.grantPermissionFromUser(uri, pkg, mContext.getPackageName(), allSlices);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
