blob: 9347c241bb4edb64f12b28fee88868bf7c0988f9 [file] [log] [blame]
Ruben Brunk9d21ee52015-03-20 22:18:55 -07001/*
2 * Copyright 2015 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 */
16package com.android.server.camera;
17
Ruben Brunk7f75da22015-04-30 17:46:30 -070018import android.app.ActivityManager;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070019import android.content.Context;
Ruben Brunk7f75da22015-04-30 17:46:30 -070020import android.content.pm.UserInfo;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070021import android.hardware.ICameraService;
Ruben Brunk6664aee2015-05-19 17:20:24 -070022import android.hardware.ICameraServiceProxy;
Ruben Brunk28388e82015-06-01 18:41:28 -070023import android.os.Handler;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070024import android.os.IBinder;
Ruben Brunk28388e82015-06-01 18:41:28 -070025import android.os.Message;
26import android.os.Process;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070027import android.os.RemoteException;
Ruben Brunk7f75da22015-04-30 17:46:30 -070028import android.os.UserManager;
Ruben Brunk28388e82015-06-01 18:41:28 -070029import android.util.Slog;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070030
Ruben Brunk28388e82015-06-01 18:41:28 -070031import com.android.server.ServiceThread;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070032import com.android.server.SystemService;
33
Ruben Brunk7f75da22015-04-30 17:46:30 -070034import java.util.Collection;
35import java.util.HashSet;
36import java.util.List;
37import java.util.Set;
38
Ruben Brunk9d21ee52015-03-20 22:18:55 -070039/**
40 * CameraService is the system_server analog to the camera service running in mediaserver.
41 *
42 * @hide
43 */
Ruben Brunk28388e82015-06-01 18:41:28 -070044public class CameraService extends SystemService implements Handler.Callback {
45 private static final String TAG = "CameraService_proxy";
Ruben Brunk9d21ee52015-03-20 22:18:55 -070046
47 /**
48 * This must match the ICameraService.aidl definition
49 */
50 private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
51
Ruben Brunk6664aee2015-05-19 17:20:24 -070052 public static final String CAMERA_SERVICE_PROXY_BINDER_NAME = "media.camera.proxy";
53
Ruben Brunk9d21ee52015-03-20 22:18:55 -070054 // Event arguments to use with the camera service notifySystemEvent call:
55 public static final int NO_EVENT = 0; // NOOP
56 public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
57
Ruben Brunk28388e82015-06-01 18:41:28 -070058 // Handler message codes
59 private static final int MSG_SWITCH_USER = 1;
60
61 private static final int RETRY_DELAY_TIME = 20; //ms
62
Ruben Brunk7f75da22015-04-30 17:46:30 -070063 private final Context mContext;
Ruben Brunk28388e82015-06-01 18:41:28 -070064 private final ServiceThread mHandlerThread;
65 private final Handler mHandler;
Ruben Brunk7f75da22015-04-30 17:46:30 -070066 private UserManager mUserManager;
Ruben Brunk6664aee2015-05-19 17:20:24 -070067
68 private final Object mLock = new Object();
Ruben Brunk7f75da22015-04-30 17:46:30 -070069 private Set<Integer> mEnabledCameraUsers;
70
Ruben Brunk6664aee2015-05-19 17:20:24 -070071 private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
72 @Override
73 public void pingForUserUpdate() {
Ruben Brunk28388e82015-06-01 18:41:28 -070074 notifySwitchWithRetries(30);
Ruben Brunk6664aee2015-05-19 17:20:24 -070075 }
76 };
77
Ruben Brunk9d21ee52015-03-20 22:18:55 -070078 public CameraService(Context context) {
79 super(context);
Ruben Brunk7f75da22015-04-30 17:46:30 -070080 mContext = context;
Ruben Brunk28388e82015-06-01 18:41:28 -070081 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false);
82 mHandlerThread.start();
83 mHandler = new Handler(mHandlerThread.getLooper(), this);
84 }
85
86 @Override
87 public boolean handleMessage(Message msg) {
88 switch(msg.what) {
89 case MSG_SWITCH_USER: {
90 notifySwitchWithRetries(msg.arg1);
91 } break;
92 default: {
93 Slog.e(TAG, "CameraService error, invalid message: " + msg.what);
94 } break;
95 }
96 return true;
Ruben Brunk9d21ee52015-03-20 22:18:55 -070097 }
98
99 @Override
Ruben Brunk7f75da22015-04-30 17:46:30 -0700100 public void onStart() {
101 mUserManager = UserManager.get(mContext);
102 if (mUserManager == null) {
103 // Should never see this unless someone messes up the SystemServer service boot order.
104 throw new IllegalStateException("UserManagerService must start before CameraService!");
105 }
Ruben Brunk6664aee2015-05-19 17:20:24 -0700106 publishBinderService(CAMERA_SERVICE_PROXY_BINDER_NAME, mCameraServiceProxy);
Ruben Brunk7f75da22015-04-30 17:46:30 -0700107 }
108
109 @Override
110 public void onStartUser(int userHandle) {
Ruben Brunk6664aee2015-05-19 17:20:24 -0700111 synchronized(mLock) {
112 if (mEnabledCameraUsers == null) {
113 // Initialize mediaserver, or update mediaserver if we are recovering from a crash.
114 switchUserLocked(userHandle);
115 }
Ruben Brunk7f75da22015-04-30 17:46:30 -0700116 }
117 }
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700118
119 @Override
120 public void onSwitchUser(int userHandle) {
Ruben Brunk6664aee2015-05-19 17:20:24 -0700121 synchronized(mLock) {
122 switchUserLocked(userHandle);
123 }
124 }
125
126 private void switchUserLocked(int userHandle) {
Ruben Brunk7f75da22015-04-30 17:46:30 -0700127 Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
128 if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
129 // Some user handles have been added or removed, update mediaserver.
130 mEnabledCameraUsers = currentUserHandles;
131 notifyMediaserver(USER_SWITCHED, currentUserHandles);
132 }
133 }
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700134
Ruben Brunk7f75da22015-04-30 17:46:30 -0700135 private Set<Integer> getEnabledUserHandles(int currentUserHandle) {
136 List<UserInfo> userProfiles = mUserManager.getEnabledProfiles(currentUserHandle);
137 Set<Integer> handles = new HashSet<>(userProfiles.size());
138
139 for (UserInfo i : userProfiles) {
140 handles.add(i.id);
141 }
142
143 return handles;
144 }
145
Ruben Brunk28388e82015-06-01 18:41:28 -0700146 private void notifySwitchWithRetries(int retries) {
147 synchronized(mLock) {
148 if (mEnabledCameraUsers == null) {
149 return;
150 }
151 if (notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers)) {
152 retries = 0;
153 }
154 }
155 if (retries <= 0) {
156 return;
157 }
158 Slog.i(TAG, "Could not notify camera service of user switch, retrying...");
159 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null),
160 RETRY_DELAY_TIME);
161 }
162
163 private boolean notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) {
Ruben Brunk7f75da22015-04-30 17:46:30 -0700164 // Forward the user switch event to the native camera service running in the mediaserver
165 // process.
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700166 IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
167 if (cameraServiceBinder == null) {
Ruben Brunk28388e82015-06-01 18:41:28 -0700168 Slog.w(TAG, "Could not notify mediaserver, camera service not available.");
169 return false; // Camera service not active, cannot evict user clients.
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700170 }
Ruben Brunk7f75da22015-04-30 17:46:30 -0700171
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700172 ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
Ruben Brunk7f75da22015-04-30 17:46:30 -0700173
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700174 try {
Ruben Brunk7f75da22015-04-30 17:46:30 -0700175 cameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700176 } catch (RemoteException e) {
Ruben Brunk28388e82015-06-01 18:41:28 -0700177 Slog.w(TAG, "Could not notify mediaserver, remote exception: " + e);
Ruben Brunk7f75da22015-04-30 17:46:30 -0700178 // Not much we can do if camera service is dead.
Ruben Brunk28388e82015-06-01 18:41:28 -0700179 return false;
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700180 }
Ruben Brunk28388e82015-06-01 18:41:28 -0700181 return true;
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700182 }
Ruben Brunk7f75da22015-04-30 17:46:30 -0700183
184 private static int[] toArray(Collection<Integer> c) {
185 int len = c.size();
186 int[] ret = new int[len];
187 int idx = 0;
188 for (Integer i : c) {
189 ret[idx++] = i;
190 }
191 return ret;
192 }
Ruben Brunk9d21ee52015-03-20 22:18:55 -0700193}