Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 144e6b34 authored by Danning Chen's avatar Danning Chen
Browse files

Add @hide people service API to access the recent conversations

This @hide API allows the settings to retrieve and remove recent cached
conversations from people service.

Bug: 162593584
Test: test on device
Change-Id: I176d87a0fb1ca3ebcc24bdb1cebcb6d8f4c9bb53
parent 2a267db0
Loading
Loading
Loading
Loading
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.people;

import android.app.NotificationChannel;
import android.content.pm.ShortcutInfo;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * The non-customized notification channel of a conversation. It contains the information to render
 * the conversation and allows the user to open and customize the conversation setting.
 *
 * @hide
 */
public final class ConversationChannel implements Parcelable {

    private ShortcutInfo mShortcutInfo;
    private NotificationChannel mParentNotificationChannel;
    private long mLastEventTimestamp;
    private boolean mHasActiveNotifications;

    public static final Creator<ConversationChannel> CREATOR = new Creator<ConversationChannel>() {
        @Override
        public ConversationChannel createFromParcel(Parcel in) {
            return new ConversationChannel(in);
        }

        @Override
        public ConversationChannel[] newArray(int size) {
            return new ConversationChannel[size];
        }
    };

    public ConversationChannel(ShortcutInfo shortcutInfo,
            NotificationChannel parentNotificationChannel, long lastEventTimestamp,
            boolean hasActiveNotifications) {
        mShortcutInfo = shortcutInfo;
        mParentNotificationChannel = parentNotificationChannel;
        mLastEventTimestamp = lastEventTimestamp;
        mHasActiveNotifications = hasActiveNotifications;
    }

    public ConversationChannel(Parcel in) {
        mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
        mParentNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader());
        mLastEventTimestamp = in.readLong();
        mHasActiveNotifications = in.readBoolean();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(mShortcutInfo, flags);
        dest.writeParcelable(mParentNotificationChannel, flags);
        dest.writeLong(mLastEventTimestamp);
        dest.writeBoolean(mHasActiveNotifications);
    }

    public ShortcutInfo getShortcutInfo() {
        return mShortcutInfo;
    }

    public NotificationChannel getParentNotificationChannel() {
        return mParentNotificationChannel;
    }

    public long getLastEventTimestamp() {
        return mLastEventTimestamp;
    }

    /**
     * Whether this conversation has any active notifications. If it's true, the shortcut for this
     * conversation can't be uncached until all its active notifications are dismissed.
     */
    public boolean hasActiveNotifications() {
        return mHasActiveNotifications;
    }
}
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.people;

import android.content.pm.ParceledListSlice;
import android.net.Uri;
import android.os.IBinder;

/**
 * System private API for talking with the people service.
 * {@hide}
 */
interface IPeopleManager {
    /**
     * Returns the recent conversations. The conversations that have customized notification
     * settings are excluded from the returned list.
     */
    ParceledListSlice getRecentConversations();

    /**
     * Removes the specified conversation from the recent conversations list and uncaches the
     * shortcut associated with the conversation.
     */
    void removeRecentConversation(in String packageName, int userId, in String shortcutId);

    /** Removes all the recent conversations and uncaches their cached shortcuts. */
    void removeAllRecentConversations();
}
+9 −0
Original line number Diff line number Diff line
@@ -3494,6 +3494,7 @@ public abstract class Context {
            //@hide: TIME_ZONE_DETECTOR_SERVICE,
            PERMISSION_SERVICE,
            LIGHTS_SERVICE,
            //@hide: PEOPLE_SERVICE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ServiceName {}
@@ -5183,6 +5184,14 @@ public abstract class Context {
     */
    public static final String SMS_SERVICE = "sms";

    /**
     * Use with {@link #getSystemService(String)} to access people service.
     *
     * @see #getSystemService(String)
     * @hide
     */
    public static final String PEOPLE_SERVICE = "people";

    /**
     * Determine whether the given permission is allowed for a particular
     * process and user ID running in the system.
+39 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.people;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionSessionId;
import android.app.prediction.AppTarget;
@@ -26,8 +28,11 @@ import android.app.prediction.AppTargetEvent;
import android.app.prediction.IPredictionCallback;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;

@@ -35,6 +40,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemService;
import com.android.server.people.data.DataManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@@ -68,6 +74,7 @@ public class PeopleService extends SystemService {

    @Override
    public void onStart() {
        publishBinderService(Context.PEOPLE_SERVICE, new BinderService());
        publishLocalService(PeopleServiceInternal.class, new LocalService());
    }

@@ -81,6 +88,38 @@ public class PeopleService extends SystemService {
        mDataManager.onUserStopping(user.getUserIdentifier());
    }

    /**
     * Enforces that only the system or root UID can make certain calls.
     *
     * @param message used as message if SecurityException is thrown
     * @throws SecurityException if the caller is not system or root
     */
    private static void enforceSystemOrRoot(String message) {
        int uid = Binder.getCallingUid();
        if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
            throw new SecurityException("Only system may " + message);
        }
    }

    private final class BinderService extends IPeopleManager.Stub {

        @Override
        public ParceledListSlice<ConversationChannel> getRecentConversations() {
            enforceSystemOrRoot("get recent conversations");
            return new ParceledListSlice<>(new ArrayList<>());
        }

        @Override
        public void removeRecentConversation(String packageName, int userId, String shortcutId) {
            enforceSystemOrRoot("remove a recent conversation");
        }

        @Override
        public void removeAllRecentConversations() {
            enforceSystemOrRoot("remove all recent conversations");
        }
    }

    @VisibleForTesting
    final class LocalService extends PeopleServiceInternal {