1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.smartspace; 18 19 import static android.Manifest.permission.MANAGE_SMARTSPACE; 20 import static android.Manifest.permission.ACCESS_SMARTSPACE; 21 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; 22 import static android.content.Context.SMARTSPACE_SERVICE; 23 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.UserIdInt; 28 import android.app.ActivityManagerInternal; 29 import android.app.smartspace.ISmartspaceCallback; 30 import android.app.smartspace.ISmartspaceManager; 31 import android.app.smartspace.SmartspaceConfig; 32 import android.app.smartspace.SmartspaceSessionId; 33 import android.app.smartspace.SmartspaceTargetEvent; 34 import android.app.smartspace.flags.Flags; 35 import android.content.Context; 36 import android.os.Binder; 37 import android.os.IBinder; 38 import android.os.ResultReceiver; 39 import android.os.ShellCallback; 40 import android.util.Slog; 41 42 import com.android.server.LocalServices; 43 import com.android.server.infra.AbstractMasterSystemService; 44 import com.android.server.infra.FrameworkResourcesServiceNameResolver; 45 import com.android.server.wm.ActivityTaskManagerInternal; 46 47 import java.io.FileDescriptor; 48 import java.util.function.Consumer; 49 50 /** 51 * A service used to return smartspace targets given a query. 52 */ 53 public class SmartspaceManagerService extends 54 AbstractMasterSystemService<SmartspaceManagerService, SmartspacePerUserService> { 55 56 private static final String TAG = SmartspaceManagerService.class.getSimpleName(); 57 private static final boolean DEBUG = false; 58 59 private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes 60 61 private final ActivityTaskManagerInternal mActivityTaskManagerInternal; 62 SmartspaceManagerService(Context context)63 public SmartspaceManagerService(Context context) { 64 super(context, new FrameworkResourcesServiceNameResolver(context, 65 com.android.internal.R.string.config_defaultSmartspaceService), null, 66 PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH); 67 mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class); 68 } 69 70 @Override newServiceLocked(int resolvedUserId, boolean disabled)71 protected SmartspacePerUserService newServiceLocked(int resolvedUserId, boolean disabled) { 72 return new SmartspacePerUserService(this, mLock, resolvedUserId); 73 } 74 75 @Override onStart()76 public void onStart() { 77 publishBinderService(SMARTSPACE_SERVICE, new SmartspaceManagerStub()); 78 } 79 80 @Override enforceCallingPermissionForManagement()81 protected void enforceCallingPermissionForManagement() { 82 getContext().enforceCallingPermission(MANAGE_SMARTSPACE, TAG); 83 } 84 85 @Override // from AbstractMasterSystemService onServicePackageUpdatedLocked(@serIdInt int userId)86 protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { 87 final SmartspacePerUserService service = peekServiceForUserLocked(userId); 88 if (service != null) { 89 service.onPackageUpdatedLocked(); 90 } 91 } 92 93 @Override // from AbstractMasterSystemService onServicePackageRestartedLocked(@serIdInt int userId)94 protected void onServicePackageRestartedLocked(@UserIdInt int userId) { 95 final SmartspacePerUserService service = peekServiceForUserLocked(userId); 96 if (service != null) { 97 service.onPackageRestartedLocked(); 98 } 99 } 100 101 @Override getMaximumTemporaryServiceDurationMs()102 protected int getMaximumTemporaryServiceDurationMs() { 103 return MAX_TEMP_SERVICE_DURATION_MS; 104 } 105 106 private class SmartspaceManagerStub extends ISmartspaceManager.Stub { 107 108 @Override createSmartspaceSession(@onNull SmartspaceConfig smartspaceConfig, @NonNull SmartspaceSessionId sessionId, @NonNull IBinder token)109 public void createSmartspaceSession(@NonNull SmartspaceConfig smartspaceConfig, 110 @NonNull SmartspaceSessionId sessionId, @NonNull IBinder token) { 111 runForUserLocked("createSmartspaceSession", sessionId, (service) -> 112 service.onCreateSmartspaceSessionLocked(smartspaceConfig, sessionId, token)); 113 } 114 115 @Override notifySmartspaceEvent(SmartspaceSessionId sessionId, SmartspaceTargetEvent event)116 public void notifySmartspaceEvent(SmartspaceSessionId sessionId, 117 SmartspaceTargetEvent event) { 118 runForUserLocked("notifySmartspaceEvent", sessionId, 119 (service) -> service.notifySmartspaceEventLocked(sessionId, event)); 120 } 121 122 @Override requestSmartspaceUpdate(SmartspaceSessionId sessionId)123 public void requestSmartspaceUpdate(SmartspaceSessionId sessionId) { 124 runForUserLocked("requestSmartspaceUpdate", sessionId, 125 (service) -> service.requestSmartspaceUpdateLocked(sessionId)); 126 } 127 128 @Override registerSmartspaceUpdates(@onNull SmartspaceSessionId sessionId, @NonNull ISmartspaceCallback callback)129 public void registerSmartspaceUpdates(@NonNull SmartspaceSessionId sessionId, 130 @NonNull ISmartspaceCallback callback) { 131 runForUserLocked("registerSmartspaceUpdates", sessionId, 132 (service) -> service.registerSmartspaceUpdatesLocked(sessionId, callback)); 133 } 134 135 @Override unregisterSmartspaceUpdates(SmartspaceSessionId sessionId, ISmartspaceCallback callback)136 public void unregisterSmartspaceUpdates(SmartspaceSessionId sessionId, 137 ISmartspaceCallback callback) { 138 runForUserLocked("unregisterSmartspaceUpdates", sessionId, 139 (service) -> service.unregisterSmartspaceUpdatesLocked(sessionId, callback)); 140 } 141 142 @Override destroySmartspaceSession(@onNull SmartspaceSessionId sessionId)143 public void destroySmartspaceSession(@NonNull SmartspaceSessionId sessionId) { 144 runForUserLocked("destroySmartspaceSession", sessionId, 145 (service) -> service.onDestroyLocked(sessionId)); 146 } 147 onShellCommand(@ullable FileDescriptor in, @Nullable FileDescriptor out, @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver)148 public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, 149 @Nullable FileDescriptor err, 150 @NonNull String[] args, @Nullable ShellCallback callback, 151 @NonNull ResultReceiver resultReceiver) { 152 new SmartspaceManagerServiceShellCommand(SmartspaceManagerService.this) 153 .exec(this, in, out, err, args, callback, resultReceiver); 154 } 155 runForUserLocked(@onNull final String func, @NonNull final SmartspaceSessionId sessionId, @NonNull final Consumer<SmartspacePerUserService> c)156 private void runForUserLocked(@NonNull final String func, 157 @NonNull final SmartspaceSessionId sessionId, 158 @NonNull final Consumer<SmartspacePerUserService> c) { 159 ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class); 160 final int userId = am.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 161 sessionId.getUserHandle().getIdentifier(), false, ALLOW_NON_FULL, null, null); 162 163 if (DEBUG) { 164 Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid() 165 + ", uid=" + Binder.getCallingUid()); 166 } 167 Context ctx = getContext(); 168 if (!(ctx.checkCallingPermission(MANAGE_SMARTSPACE) == PERMISSION_GRANTED 169 || (Flags.accessSmartspace() 170 && ctx.checkCallingPermission(ACCESS_SMARTSPACE) == PERMISSION_GRANTED) 171 || mServiceNameResolver.isTemporary(userId) 172 || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) { 173 174 String msg = "Permission Denial: Cannot call " + func + " from pid=" 175 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid(); 176 Slog.w(TAG, msg); 177 throw new SecurityException(msg); 178 } 179 180 final long origId = Binder.clearCallingIdentity(); 181 try { 182 synchronized (mLock) { 183 final SmartspacePerUserService service = getServiceForUserLocked(userId); 184 c.accept(service); 185 } 186 } finally { 187 Binder.restoreCallingIdentity(origId); 188 } 189 } 190 } 191 } 192