cmsdk: Create brokerablecmsystemservice concept.
Extending the BrokerableCMSystemService allows a core system service to declare a delegate provider interface that can exist in another package, either in the same or an external process. Change-Id: Idf8d170b1504528b0d3aafb23895951e26459c98
This commit is contained in:
parent
551b377da9
commit
b62a4550c3
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* Copyright (C) 2016 The CyanogenMod 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 org.cyanogenmod.platform.internal;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Slog;
|
||||
|
||||
import cyanogenmod.platform.Manifest;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import org.cyanogenmod.platform.internal.common.BrokeredServiceConnection;
|
||||
|
||||
public abstract class BrokerableCMSystemService<T extends IInterface> extends CMSystemService {
|
||||
private static final String TAG = BrokerableCMSystemService.class.getSimpleName();
|
||||
|
||||
private static final int MSG_TRY_CONNECTING = 1;
|
||||
private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
|
||||
private Context mContext;
|
||||
|
||||
private BrokeredServiceConnection mBrokeredServiceConnection;
|
||||
private T mImplementingBinderInterface;
|
||||
|
||||
public BrokerableCMSystemService(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the {@link IInterface} contract for the given {@link IBinder} is to
|
||||
* be assigned for the implementing service {@link T}
|
||||
* @param service
|
||||
* @return {@link T}
|
||||
*/
|
||||
protected abstract T getIBinderAsIInterface(@NonNull IBinder service);
|
||||
|
||||
/**
|
||||
* Called when necessary as the default implementation. (usually a failure implementation)
|
||||
* For when an implementing service is not found, is updating, or is failing.
|
||||
* @return {@link T}
|
||||
*/
|
||||
protected abstract T getDefaultImplementation();
|
||||
|
||||
/**
|
||||
* Called when attempting to connect to the a given {@link T} implementation. Defines
|
||||
* the {@link ComponentName} to be used for the binding operation.
|
||||
*
|
||||
* By default, the calling component MUST gate its implementation by the
|
||||
* {@link Manifest.permission.BIND_CORE_SERVICE} permission as well as using,
|
||||
* the permission granted to its own package.
|
||||
*
|
||||
* This permission can be overridden via {@link #getComponentFilteringPermission()}
|
||||
*
|
||||
* @return {@link ComponentName}
|
||||
*/
|
||||
@Nullable
|
||||
protected abstract ComponentName getServiceComponent();
|
||||
|
||||
/**
|
||||
* Override this method if your broker will provide its own permission for guarding a vertical
|
||||
* api defintion. Otherwise, the component from {@link #getServiceComponent()}
|
||||
* will be gated via the {@link Manifest.permission.BIND_CORE_SERVICE} permission.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@NonNull
|
||||
protected String getComponentFilteringPermission() {
|
||||
return Manifest.permission.BIND_CORE_SERVICE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link BrokeredServiceConnection} to receive callbacks when an implementation is
|
||||
* connected or disconnected.
|
||||
* @param brokeredServiceComponent
|
||||
*/
|
||||
public final void setBrokeredServiceConnection(
|
||||
@NonNull BrokeredServiceConnection brokeredServiceComponent) {
|
||||
Preconditions.checkNotNull(brokeredServiceComponent);
|
||||
Slog.e(TAG, "Setting brokered service connection "
|
||||
+ brokeredServiceComponent.toString());
|
||||
mBrokeredServiceConnection = brokeredServiceComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the implementing service for the given binder invocation. Usually called from a binder
|
||||
* thread in a subclassed service.
|
||||
* @return {@link T} that represents the implementing service
|
||||
*/
|
||||
public final T getBrokeredService() {
|
||||
final T service = getOrConnectService();
|
||||
if (service != null) {
|
||||
return service;
|
||||
}
|
||||
return getDefaultImplementation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBootPhase(int phase) {
|
||||
super.onBootPhase(phase);
|
||||
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||
Slog.d(TAG, "Third party apps ready");
|
||||
tryConnecting();
|
||||
}
|
||||
}
|
||||
|
||||
private T getOrConnectService() {
|
||||
synchronized (this) {
|
||||
if (mImplementingBinderInterface != null) {
|
||||
return mImplementingBinderInterface;
|
||||
}
|
||||
// Service is not connected. Try blocking connecting.
|
||||
mConnectionHandler.sendMessage(
|
||||
mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
|
||||
final long shouldEnd =
|
||||
SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
|
||||
long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
|
||||
while (waitTime > 0) {
|
||||
try {
|
||||
// TODO: consider using Java concurrent construct instead of raw object wait
|
||||
this.wait(waitTime);
|
||||
} catch (InterruptedException e) {
|
||||
Slog.w(TAG, "Connection wait interrupted", e);
|
||||
}
|
||||
if (mImplementingBinderInterface != null) {
|
||||
// Success
|
||||
return mImplementingBinderInterface;
|
||||
}
|
||||
// Calculate remaining waiting time to make sure we wait the full timeout period
|
||||
waitTime = shouldEnd - SystemClock.elapsedRealtime();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final Handler mConnectionHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_TRY_CONNECTING:
|
||||
tryConnecting();
|
||||
break;
|
||||
default:
|
||||
Slog.e(TAG, "Unknown message");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to connect to the component which is going to serve {@link T}
|
||||
* interface contract implementation.
|
||||
*/
|
||||
public final void tryConnecting() {
|
||||
Slog.i(TAG, "Connecting to implementation");
|
||||
synchronized (this) {
|
||||
if (mImplementingBinderInterface != null) {
|
||||
Slog.d(TAG, "Already connected");
|
||||
return;
|
||||
}
|
||||
final Intent intent = new Intent();
|
||||
final ComponentName cn = getServiceComponent();
|
||||
if (cn == null) {
|
||||
Slog.e(TAG, "No implementation service found");
|
||||
return;
|
||||
}
|
||||
intent.setComponent(cn);
|
||||
try {
|
||||
if (mContext.getPackageManager().checkPermission(
|
||||
getComponentFilteringPermission(),
|
||||
cn.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.e(TAG, "Target component lacks " + getComponentFilteringPermission()
|
||||
+ " service permission, failing " + cn);
|
||||
return;
|
||||
}
|
||||
if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
|
||||
Slog.e(TAG, "Failed to bind to implementation " + cn);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Slog.e(TAG, "Forbidden to bind to implementation " + cn, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
Slog.i(TAG, "Implementation service connected");
|
||||
synchronized (BrokerableCMSystemService.this) {
|
||||
mImplementingBinderInterface = getIBinderAsIInterface(service);
|
||||
BrokerableCMSystemService.this.notifyAll();
|
||||
if (mBrokeredServiceConnection != null) {
|
||||
Slog.i(TAG, "Notifying service connected");
|
||||
mBrokeredServiceConnection.onBrokeredServiceConnected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
Slog.i(TAG, "Implementation service unexpectedly disconnected");
|
||||
synchronized (BrokerableCMSystemService.this) {
|
||||
mImplementingBinderInterface = null;
|
||||
BrokerableCMSystemService.this.notifyAll();
|
||||
if (mBrokeredServiceConnection != null) {
|
||||
mBrokeredServiceConnection.onBrokeredServiceDisconnected();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo;
|
|||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
|
@ -44,6 +45,8 @@ import cyanogenmod.app.LiveLockScreenManager;
|
|||
import cyanogenmod.platform.Manifest;
|
||||
import cyanogenmod.providers.CMSettings;
|
||||
|
||||
import org.cyanogenmod.platform.internal.common.BrokeredServiceConnection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -52,20 +55,15 @@ import java.util.List;
|
|||
*
|
||||
* @hide
|
||||
*/
|
||||
public class LiveLockScreenServiceBroker extends CMSystemService {
|
||||
public class LiveLockScreenServiceBroker extends
|
||||
BrokerableCMSystemService<ILiveLockScreenManagerProvider> {
|
||||
private static final String TAG = LiveLockScreenServiceBroker.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int MSG_TRY_CONNECTING = 1;
|
||||
|
||||
private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
|
||||
|
||||
private static final String DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION =
|
||||
"android.permission.THIRD_PARTY_KEYGUARD";
|
||||
|
||||
private Context mContext;
|
||||
// The actual LLS service to invoke
|
||||
private ILiveLockScreenManagerProvider mService;
|
||||
|
||||
// Cached change listeners
|
||||
private final RemoteCallbackList<ILiveLockScreenChangeListener> mChangeListeners =
|
||||
|
@ -73,53 +71,6 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
|
||||
private LiveLockScreenInfo mDefaultLlsInfo;
|
||||
|
||||
private final Handler mConnectionHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_TRY_CONNECTING:
|
||||
tryConnecting();
|
||||
break;
|
||||
default:
|
||||
Slog.e(TAG, "Unknown message");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
Slog.i(TAG, "LiveLockScreenManagerService connected");
|
||||
synchronized (LiveLockScreenServiceBroker.this) {
|
||||
mService = ILiveLockScreenManagerProvider.Stub.asInterface(service);
|
||||
LiveLockScreenServiceBroker.this.notifyAll();
|
||||
// If any change listeners are cached, register them with the newly connected
|
||||
// service.
|
||||
try {
|
||||
int N = mChangeListeners.beginBroadcast();
|
||||
if (mService != null && N > 0) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
mService.registerChangeListener(mChangeListeners.getBroadcastItem(i));
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
/* ignore */
|
||||
} finally {
|
||||
mChangeListeners.finishBroadcast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
Slog.i(TAG, "LiveLockScreenManagerService unexpectedly disconnected");
|
||||
synchronized (LiveLockScreenServiceBroker.this) {
|
||||
mService = null;
|
||||
LiveLockScreenServiceBroker.this.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ILiveLockScreenManager implementation to use when no backing service can be found.
|
||||
*/
|
||||
|
@ -172,17 +123,17 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
@Override
|
||||
public void enqueueLiveLockScreen(String pkg, int id,
|
||||
LiveLockScreenInfo lls, int[] idReceived, int userId) throws RemoteException {
|
||||
getServiceGuarded().enqueueLiveLockScreen(pkg, id, lls, idReceived, userId);
|
||||
getBrokeredService().enqueueLiveLockScreen(pkg, id, lls, idReceived, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelLiveLockScreen(String pkg, int id, int userId) throws RemoteException {
|
||||
getServiceGuarded().cancelLiveLockScreen(pkg, id, userId);
|
||||
getBrokeredService().cancelLiveLockScreen(pkg, id, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveLockScreenInfo getCurrentLiveLockScreen() throws RemoteException {
|
||||
return getServiceGuarded().getCurrentLiveLockScreen();
|
||||
return getBrokeredService().getCurrentLiveLockScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,23 +156,23 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
|
||||
@Override
|
||||
public boolean getLiveLockScreenEnabled() throws RemoteException {
|
||||
return getServiceGuarded().getLiveLockScreenEnabled();
|
||||
return getBrokeredService().getLiveLockScreenEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerChangeListener(
|
||||
ILiveLockScreenChangeListener listener) throws RemoteException {
|
||||
boolean registered = getServiceGuarded().registerChangeListener(listener);
|
||||
boolean registered = getBrokeredService().registerChangeListener(listener);
|
||||
if (registered) {
|
||||
mChangeListeners.register(listener);
|
||||
}
|
||||
return getServiceGuarded().registerChangeListener(listener);
|
||||
return registered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unregisterChangeListener(
|
||||
ILiveLockScreenChangeListener listener) throws RemoteException {
|
||||
boolean unregistered = getServiceGuarded().unregisterChangeListener(listener);
|
||||
boolean unregistered = getBrokeredService().unregisterChangeListener(listener);
|
||||
if (unregistered) {
|
||||
mChangeListeners.unregister(listener);
|
||||
}
|
||||
|
@ -232,6 +183,7 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
public LiveLockScreenServiceBroker(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
setBrokeredServiceConnection(mServiceConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -245,6 +197,65 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
publishBinderService(CMContextConstants.CM_LIVE_LOCK_SCREEN_SERVICE, new BinderService());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ILiveLockScreenManagerProvider getIBinderAsIInterface(IBinder service) {
|
||||
return ILiveLockScreenManagerProvider.Stub.asInterface(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILiveLockScreenManagerProvider getDefaultImplementation() {
|
||||
return mServiceStubForFailure;
|
||||
}
|
||||
|
||||
private BrokeredServiceConnection mServiceConnection = new BrokeredServiceConnection() {
|
||||
@Override
|
||||
public void onBrokeredServiceConnected() {
|
||||
// If any change listeners are cached, register them with the newly connected
|
||||
// service.
|
||||
try {
|
||||
int N = mChangeListeners.beginBroadcast();
|
||||
ILiveLockScreenManagerProvider iLiveLockScreenManagerProvider =
|
||||
getBrokeredService();
|
||||
if (iLiveLockScreenManagerProvider != null && N > 0) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
iLiveLockScreenManagerProvider
|
||||
.registerChangeListener(mChangeListeners.getBroadcastItem(i));
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
/* ignore */
|
||||
} finally {
|
||||
mChangeListeners.finishBroadcast();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrokeredServiceDisconnected() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected String getComponentFilteringPermission() {
|
||||
// Live lock screen service has its own vertical providing permission
|
||||
return Manifest.permission.LIVE_LOCK_SCREEN_MANAGER_PROVIDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ComponentName getServiceComponent() {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
Intent intent = new Intent(LiveLockScreenManager.SERVICE_INTERFACE);
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent, 0);
|
||||
for (ResolveInfo info : resolveInfos) {
|
||||
if (info != null) {
|
||||
if (info.serviceInfo.isEnabled()) {
|
||||
return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBootPhase(int phase) {
|
||||
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||
|
@ -258,109 +269,8 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
.setComponent(ComponentName.unflattenFromString(defComponent))
|
||||
.build();
|
||||
}
|
||||
// Now that 3rd party apps are ready, try connecting to the backing service
|
||||
tryConnecting();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds to the backing service if one is found
|
||||
*/
|
||||
private void tryConnecting() {
|
||||
Slog.i(TAG, "Connecting to LiveLockScreenManagerService");
|
||||
synchronized (this) {
|
||||
if (mService != null) {
|
||||
Slog.d(TAG, "Already connected");
|
||||
return;
|
||||
}
|
||||
final Intent intent = new Intent();
|
||||
final ComponentName cn = getLiveLockScreenServiceComponent();
|
||||
if (cn == null) {
|
||||
Slog.e(TAG, "No live lock screen manager service found");
|
||||
return;
|
||||
}
|
||||
intent.setComponent(getLiveLockScreenServiceComponent());
|
||||
try {
|
||||
if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
|
||||
Slog.e(TAG, "Failed to bind to LiveLockScreenManagerService");
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Slog.e(TAG, "Forbidden to bind to LiveLockScreenManagerService", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries package manager for the component which handles the
|
||||
* {@link LiveLockScreenManager#SERVICE_INTERFACE} and has been granted the
|
||||
* {@link org.cyanogenmod.platform.internal.Manifest.permission#LIVE_LOCK_SCREEN_MANAGER_PROVIDER}
|
||||
* permission.
|
||||
*
|
||||
* @return A valid component that supports {@link LiveLockScreenManager#SERVICE_INTERFACE} or
|
||||
* null if no component can be found.
|
||||
*/
|
||||
@Nullable private ComponentName getLiveLockScreenServiceComponent() {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
Intent intent = new Intent(LiveLockScreenManager.SERVICE_INTERFACE);
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent, 0);
|
||||
for (ResolveInfo info : resolveInfos) {
|
||||
if (info != null) {
|
||||
if (pm.checkPermission(Manifest.permission.LIVE_LOCK_SCREEN_MANAGER_PROVIDER,
|
||||
info.serviceInfo.packageName) == PackageManager.PERMISSION_GRANTED &&
|
||||
info.serviceInfo.isEnabled()) {
|
||||
return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ILiveLockScreenManagerProvider getOrConnectService() {
|
||||
synchronized (this) {
|
||||
if (mService != null) {
|
||||
return mService;
|
||||
}
|
||||
// Service is not connected. Try blocking connecting.
|
||||
Slog.w(TAG, "LiveLockScreenManagerService not connected. Try connecting...");
|
||||
mConnectionHandler.sendMessage(
|
||||
mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
|
||||
final long shouldEnd =
|
||||
SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
|
||||
long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
|
||||
while (waitTime > 0) {
|
||||
try {
|
||||
// TODO: consider using Java concurrent construct instead of raw object wait
|
||||
this.wait(waitTime);
|
||||
} catch (InterruptedException e) {
|
||||
Slog.w(TAG, "Connection wait interrupted", e);
|
||||
}
|
||||
if (mService != null) {
|
||||
// Success
|
||||
return mService;
|
||||
}
|
||||
// Calculate remaining waiting time to make sure we wait the full timeout period
|
||||
waitTime = shouldEnd - SystemClock.elapsedRealtime();
|
||||
}
|
||||
// Timed out. Something's really wrong.
|
||||
Slog.e(TAG, "Can not connect to LiveLockScreenManagerService (timed out)");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure to return a non-empty service instance. Return the connected LiveLockScreenManager
|
||||
* instance, if not connected, try connecting. If fail to connect, return a fake service
|
||||
* instance which returns failure to service caller.
|
||||
*
|
||||
* @return a non-empty service instance, real or fake
|
||||
*/
|
||||
private ILiveLockScreenManagerProvider getServiceGuarded() {
|
||||
final ILiveLockScreenManagerProvider service = getOrConnectService();
|
||||
if (service != null) {
|
||||
return service;
|
||||
}
|
||||
return mServiceStubForFailure;
|
||||
super.onBootPhase(phase);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -406,7 +316,7 @@ public class LiveLockScreenServiceBroker extends CMSystemService {
|
|||
|
||||
mDefaultLlsInfo = llsInfo;
|
||||
try {
|
||||
getServiceGuarded().updateDefaultLiveLockScreen(llsInfo);
|
||||
getBrokeredService().updateDefaultLiveLockScreen(llsInfo);
|
||||
} catch (RemoteException e) {
|
||||
/* ignore */
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (C) 2016 The CyanogenMod 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 org.cyanogenmod.platform.internal.common;
|
||||
|
||||
/**
|
||||
* The {@link BrokeredServiceConnection} provides callbacks for when a
|
||||
* {@link org.cyanogenmod.platform.internal.BrokerableCMSystemService} interface
|
||||
* contract is either fulfilled and connected to an implementation or disconnected.
|
||||
*/
|
||||
public interface BrokeredServiceConnection {
|
||||
|
||||
/**
|
||||
* Callback that signifies that the given interface contract passed into the
|
||||
* {@link org.cyanogenmod.platform.internal.BrokerableCMSystemService} is implemented
|
||||
* and connected.
|
||||
*/
|
||||
void onBrokeredServiceConnected();
|
||||
|
||||
/**
|
||||
* Callback that signifies that the given implementation for the interface contract passed
|
||||
* into the {@link org.cyanogenmod.platform.internal.BrokerableCMSystemService} is disconnected.
|
||||
*/
|
||||
void onBrokeredServiceDisconnected();
|
||||
}
|
|
@ -220,7 +220,6 @@
|
|||
android:description="@string/permdesc_observe_audio_sessions"
|
||||
android:protectionLevel="normal"/>
|
||||
|
||||
|
||||
<!-- Allows an application to access the weather service.
|
||||
<p>Although the protection is normal, this permission should be required ONLY by those apps
|
||||
meant to do something meaningful with the data provided by the service (LockClock, SysUI)-->
|
||||
|
@ -236,6 +235,11 @@
|
|||
android:icon="@drawable/ic_launcher_cyanogenmod"
|
||||
android:protectionLevel="normal" />
|
||||
|
||||
<!-- Not meant for third parties. Allows brokering core services to other
|
||||
processes @hide -->
|
||||
<permission android:name="cyanogenmod.permission.BIND_CORE_SERVICE"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<application android:process="system"
|
||||
android:persistent="true"
|
||||
android:hasCode="false"
|
||||
|
|
Loading…
Reference in New Issue