Loading core/java/android/app/people/ConversationChannel.java 0 → 100644 +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; } } core/java/android/app/people/IPeopleManager.aidl 0 → 100644 +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(); } core/java/android/content/Context.java +9 −0 Original line number Diff line number Diff line Loading @@ -3496,6 +3496,7 @@ public abstract class Context { //@hide: TIME_ZONE_DETECTOR_SERVICE, PERMISSION_SERVICE, LIGHTS_SERVICE, //@hide: PEOPLE_SERVICE, }) @Retention(RetentionPolicy.SOURCE) public @interface ServiceName {} Loading Loading @@ -5188,6 +5189,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. Loading services/people/java/com/android/server/people/PeopleService.java +39 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -68,6 +74,7 @@ public class PeopleService extends SystemService { @Override public void onStart() { publishBinderService(Context.PEOPLE_SERVICE, new BinderService()); publishLocalService(PeopleServiceInternal.class, new LocalService()); } Loading @@ -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 { Loading Loading
core/java/android/app/people/ConversationChannel.java 0 → 100644 +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; } }
core/java/android/app/people/IPeopleManager.aidl 0 → 100644 +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(); }
core/java/android/content/Context.java +9 −0 Original line number Diff line number Diff line Loading @@ -3496,6 +3496,7 @@ public abstract class Context { //@hide: TIME_ZONE_DETECTOR_SERVICE, PERMISSION_SERVICE, LIGHTS_SERVICE, //@hide: PEOPLE_SERVICE, }) @Retention(RetentionPolicy.SOURCE) public @interface ServiceName {} Loading Loading @@ -5188,6 +5189,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. Loading
services/people/java/com/android/server/people/PeopleService.java +39 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -68,6 +74,7 @@ public class PeopleService extends SystemService { @Override public void onStart() { publishBinderService(Context.PEOPLE_SERVICE, new BinderService()); publishLocalService(PeopleServiceInternal.class, new LocalService()); } Loading @@ -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 { Loading