227 lines
8.1 KiB
Java
227 lines
8.1 KiB
Java
/*
|
|
* 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 cyanogenmod.app;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.app.AppGlobals;
|
|
import android.app.Service;
|
|
import android.content.Intent;
|
|
import android.content.pm.ApplicationInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.os.Binder;
|
|
import android.os.IBinder;
|
|
import android.os.RemoteCallbackList;
|
|
import android.os.RemoteException;
|
|
import android.os.UserHandle;
|
|
import android.util.Log;
|
|
|
|
import cyanogenmod.platform.Manifest;
|
|
|
|
/**
|
|
* Base Live lock screen manager service to be extended by applications that implement the
|
|
* {@link LiveLockScreenManager#SERVICE_INTERFACE}
|
|
*
|
|
* @hide
|
|
*/
|
|
abstract public class BaseLiveLockManagerService extends Service
|
|
implements ILiveLockScreenManagerProvider {
|
|
private static final String TAG = BaseLiveLockManagerService.class.getSimpleName();
|
|
|
|
private final RemoteCallbackList<ILiveLockScreenChangeListener> mChangeListeners =
|
|
new RemoteCallbackList<>();
|
|
|
|
@Override
|
|
public final IBinder onBind(Intent intent) {
|
|
return mService;
|
|
}
|
|
|
|
@Override
|
|
public final IBinder asBinder() {
|
|
return mService;
|
|
}
|
|
|
|
@Override
|
|
abstract public void enqueueLiveLockScreen(String pkg, int id, LiveLockScreenInfo lls,
|
|
int[] idReceived, int userId) throws RemoteException;
|
|
|
|
@Override
|
|
abstract public void cancelLiveLockScreen(String pkg, int id, int userId)
|
|
throws RemoteException;
|
|
|
|
@Override
|
|
abstract public LiveLockScreenInfo getCurrentLiveLockScreen() throws RemoteException;
|
|
|
|
@Override
|
|
abstract public void updateDefaultLiveLockScreen(LiveLockScreenInfo llsInfo)
|
|
throws RemoteException;
|
|
|
|
@Override
|
|
public boolean getLiveLockScreenEnabled() throws RemoteException {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public final boolean registerChangeListener(
|
|
ILiveLockScreenChangeListener listener) throws RemoteException {
|
|
return mChangeListeners.register(listener);
|
|
}
|
|
|
|
@Override
|
|
public final boolean unregisterChangeListener(
|
|
ILiveLockScreenChangeListener listener) throws RemoteException {
|
|
return mChangeListeners.unregister(listener);
|
|
}
|
|
|
|
/**
|
|
* This method should be called whenever there is an update to the current Live lock screen
|
|
* to be displayed.
|
|
*
|
|
* @param llsInfo LiveLockScreenInfo for the current Live lock screen
|
|
*/
|
|
protected final void notifyChangeListeners(LiveLockScreenInfo llsInfo) {
|
|
int N = mChangeListeners.beginBroadcast();
|
|
for (int i = 0; i < N; i++) {
|
|
ILiveLockScreenChangeListener listener = mChangeListeners.getBroadcastItem(i);
|
|
try {
|
|
listener.onLiveLockScreenChanged(llsInfo);
|
|
} catch (RemoteException e) {
|
|
Log.w(TAG, "Unable to notifiy change listener", e);
|
|
}
|
|
}
|
|
mChangeListeners.finishBroadcast();
|
|
}
|
|
|
|
/**
|
|
* Returns true if the caller has been granted the
|
|
* {@link cyanogenmod.platform.Manifest.permission#LIVE_LOCK_SCREEN_MANAGER_ACCESS_PRIVATE}
|
|
* permission.
|
|
*
|
|
* @return
|
|
*/
|
|
private final boolean hasPrivatePermissions() {
|
|
return checkCallingPermission(Manifest.permission
|
|
.LIVE_LOCK_SCREEN_MANAGER_ACCESS_PRIVATE) == PackageManager.PERMISSION_GRANTED;
|
|
}
|
|
|
|
/**
|
|
* Enforces the {@link cyanogenmod.platform.Manifest.permission#LIVE_LOCK_SCREEN_MANAGER_ACCESS}
|
|
* permission.
|
|
*/
|
|
protected final void enforceAccessPermission() {
|
|
if (hasPrivatePermissions()) return;
|
|
|
|
enforceCallingPermission(Manifest.permission.LIVE_LOCK_SCREEN_MANAGER_ACCESS,
|
|
null);
|
|
}
|
|
|
|
/**
|
|
* Enforces the
|
|
* {@link cyanogenmod.platform.Manifest.permission#LIVE_LOCK_SCREEN_MANAGER_ACCESS_PRIVATE}
|
|
* permission.
|
|
*/
|
|
protected final void enforcePrivateAccessPermission() {
|
|
enforceCallingPermission(
|
|
Manifest.permission.LIVE_LOCK_SCREEN_MANAGER_ACCESS_PRIVATE, null);
|
|
}
|
|
|
|
/**
|
|
* Enforces the LLS being shown/canceled is from the calling package or from a system app that
|
|
* has the
|
|
* {@link cyanogenmod.platform.Manifest.permission#LIVE_LOCK_SCREEN_MANAGER_ACCESS_PRIVATE}
|
|
* permission.
|
|
*
|
|
* @param pkg Package name of caller
|
|
* @param llsInfo Live lock screen info with component to check
|
|
*/
|
|
protected final void enforceSamePackageOrSystem(String pkg,
|
|
@NonNull LiveLockScreenInfo llsInfo) {
|
|
// only apps with the private permission can show/cancel live lock screens from other
|
|
// packages
|
|
if (hasPrivatePermissions()) return;
|
|
|
|
if (llsInfo.component != null && !llsInfo.component.getPackageName().equals(pkg)) {
|
|
throw new SecurityException("Modifying Live lock screen from different packages not " +
|
|
"allowed. Calling package: " + pkg + " LLS package: " +
|
|
llsInfo.component.getPackageName());
|
|
}
|
|
|
|
final int uid = Binder.getCallingUid();
|
|
try {
|
|
ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
|
|
pkg, 0, UserHandle.getCallingUserId());
|
|
if (ai == null) {
|
|
throw new SecurityException("Unknown package " + pkg);
|
|
}
|
|
if (!UserHandle.isSameApp(ai.uid, uid)) {
|
|
throw new SecurityException("Calling uid " + uid + " gave package"
|
|
+ pkg + " which is owned by uid " + ai.uid);
|
|
}
|
|
} catch (RemoteException re) {
|
|
throw new SecurityException("Unknown package " + pkg + "\n" + re);
|
|
}
|
|
}
|
|
|
|
private final IBinder mService = new ILiveLockScreenManagerProvider.Stub() {
|
|
@Override
|
|
public void enqueueLiveLockScreen(String pkg, int id, LiveLockScreenInfo llsInfo,
|
|
int[] idReceived, int userId) throws RemoteException {
|
|
enforceAccessPermission();
|
|
enforceSamePackageOrSystem(pkg, llsInfo);
|
|
BaseLiveLockManagerService.this.enqueueLiveLockScreen(pkg, id, llsInfo, idReceived,
|
|
userId);
|
|
}
|
|
|
|
@Override
|
|
public void cancelLiveLockScreen(String pkg, int id, int userId) throws RemoteException {
|
|
enforceAccessPermission();
|
|
BaseLiveLockManagerService.this.cancelLiveLockScreen(pkg, id, userId);
|
|
}
|
|
|
|
@Override
|
|
public LiveLockScreenInfo getCurrentLiveLockScreen() throws RemoteException {
|
|
enforceAccessPermission();
|
|
return BaseLiveLockManagerService.this.getCurrentLiveLockScreen();
|
|
}
|
|
|
|
@Override
|
|
public void updateDefaultLiveLockScreen(LiveLockScreenInfo llsInfo) throws RemoteException {
|
|
enforcePrivateAccessPermission();
|
|
BaseLiveLockManagerService.this.updateDefaultLiveLockScreen(llsInfo);
|
|
}
|
|
|
|
@Override
|
|
public boolean getLiveLockScreenEnabled() throws RemoteException {
|
|
enforceAccessPermission();
|
|
return BaseLiveLockManagerService.this.getLiveLockScreenEnabled();
|
|
}
|
|
|
|
@Override
|
|
public boolean registerChangeListener(
|
|
ILiveLockScreenChangeListener listener) throws RemoteException {
|
|
enforcePrivateAccessPermission();
|
|
return BaseLiveLockManagerService.this.registerChangeListener(listener);
|
|
}
|
|
|
|
@Override
|
|
public boolean unregisterChangeListener(
|
|
ILiveLockScreenChangeListener listener) throws RemoteException {
|
|
enforcePrivateAccessPermission();
|
|
return BaseLiveLockManagerService.this.unregisterChangeListener(listener);
|
|
}
|
|
};
|
|
}
|