summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java147
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java88
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java115
3 files changed, 349 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 27858cb..cf1340b 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -28,7 +28,9 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
@@ -42,6 +44,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.AlarmClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
@@ -66,6 +69,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.TimeZone;
@@ -79,6 +83,13 @@ import static android.app.AlarmManager.RTC_POWEROFF_WAKEUP;
import com.android.internal.util.LocalLog;
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
+
class AlarmManagerService extends SystemService {
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
@@ -293,6 +304,14 @@ class AlarmManagerService extends SystemService {
final Constants mConstants;
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ processQSChangedLocked();
+ }
+ };
+ private ContentObserver mQSObserver;
+
// Alarm delivery ordering bookkeeping
static final int PRIO_TICK = 0;
static final int PRIO_WAKEUP = 1;
@@ -857,6 +876,8 @@ class AlarmManagerService extends SystemService {
}
publishBinderService(Context.ALARM_SERVICE, mService);
+
+ mQSObserver = QSUtils.registerObserverForQSChanges(getContext(), mQSListener);
}
@Override
@@ -869,6 +890,12 @@ class AlarmManagerService extends SystemService {
@Override
protected void finalize() throws Throwable {
try {
+ QSUtils.unregisterObserverForQSChanges(getContext(), mQSObserver);
+ } catch (Exception ex) {
+ // Ignore
+ }
+
+ try {
close(mNativeData);
} finally {
super.finalize();
@@ -1052,6 +1079,8 @@ class AlarmManagerService extends SystemService {
if (a.alarmClock != null) {
mNextAlarmClockMayChange = true;
+ //Publish as system user
+ publishNextAlarmCustomTile(Process.SYSTEM_UID);
}
boolean needRebatch = false;
@@ -1611,6 +1640,9 @@ class AlarmManagerService extends SystemService {
updateNextAlarmInfoForUserLocked(userId, null);
}
}
+
+ // Process dynamic custom tile
+ processQSChangedLocked();
}
private void updateNextAlarmInfoForUserLocked(int userId,
@@ -2654,6 +2686,121 @@ class AlarmManagerService extends SystemService {
return bs;
}
+ private void publishNextAlarmCustomTile(int userId) {
+ // This action should be performed as system
+ long token = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = new UserHandle(userId);
+ if (!QSUtils.isQSTileEnabledForUser(
+ getContext(), QSConstants.DYNAMIC_TILE_NEXT_ALARM, user.getUserId(userId))) {
+ return;
+ }
+
+ final int icon = QSUtils.getDynamicQSTileResIconId(getContext(), userId,
+ QSConstants.DYNAMIC_TILE_NEXT_ALARM);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(getContext(), userId,
+ QSConstants.DYNAMIC_TILE_NEXT_ALARM);
+ final Context resourceContext = QSUtils.getQSTileContext(getContext(), userId);
+
+ // Create the expanded view with all the user alarms
+ AlarmManager.AlarmClockInfo nextAlarm = null;
+ CustomTile.ListExpandedStyle style = new CustomTile.ListExpandedStyle();
+ ArrayList<CustomTile.ExpandedListItem> items = new ArrayList<>();
+ for (Alarm alarm : getAllUserAlarmsLocked(userId)) {
+ if (nextAlarm == null) {
+ nextAlarm = alarm.alarmClock;
+ }
+
+ final String pkg = alarm.operation.getCreatorPackage();
+ CustomTile.ExpandedListItem item = new CustomTile.ExpandedListItem();
+ item.setExpandedListItemDrawable(icon);
+ item.setExpandedListItemTitle(formatNextAlarm(getContext(), alarm.alarmClock, userId));
+ item.setExpandedListItemSummary(getAlarmApkLabel(pkg));
+ item.setExpandedListItemOnClickIntent(getCustomTilePendingIntent(user, pkg));
+ items.add(item);
+ }
+ style.setListItems(items);
+
+ // Build the custom tile
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(getContext());
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(formatNextAlarm(getContext(), nextAlarm, userId))
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setExpandedStyle(style)
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_NEXT_ALARM,
+ AlarmManagerService.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishNextAlarmCustomTile(int userId) {
+ // This action should be performed as system
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(getContext());
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_NEXT_ALARM,
+ AlarmManagerService.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private List<Alarm> getAllUserAlarmsLocked(int userId) {
+ List<Alarm> userAlarms = new ArrayList<>();
+ synchronized (mLock) {
+ final int N = mAlarmBatches.size();
+ for (int i = 0; i < N; i++) {
+ ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
+ final int M = alarms.size();
+ for (int j = 0; j < M; j++) {
+ Alarm a = alarms.get(j);
+ if (a.alarmClock != null && userId == a.uid) {
+ userAlarms.add(a);
+ }
+ }
+ }
+ }
+ return userAlarms;
+ }
+
+ private String getAlarmApkLabel(String pkg) {
+ final PackageManager pm = getContext().getPackageManager();
+ ApplicationInfo ai = null;
+ try {
+ ai = pm.getApplicationInfo(pkg, 0);
+ } catch (final NameNotFoundException e) {
+ // Ignore
+ }
+ return (String) (ai != null ? pm.getApplicationLabel(ai) : pkg);
+ }
+
+ private PendingIntent getCustomTilePendingIntent(UserHandle user, String pkg) {
+ Intent i = new Intent(AlarmClock.ACTION_SHOW_ALARMS);
+ i.setPackage(pkg);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return PendingIntent.getActivityAsUser(getContext(), 0, i,
+ PendingIntent.FLAG_UPDATE_CURRENT, null, user);
+ }
+
+ private void processQSChangedLocked() {
+ synchronized (mLock) {
+ int count = mNextAlarmClockForUser.size();
+ for (int i = 0; i < count; i++) {
+ int userId = mNextAlarmClockForUser.keyAt(i);
+ boolean enabled = QSUtils.isQSTileEnabledForUser(
+ getContext(), QSConstants.DYNAMIC_TILE_NEXT_ALARM, userId);
+ if (enabled) {
+ publishNextAlarmCustomTile(userId);
+ } else {
+ unpublishNextAlarmCustomTile(userId);
+ }
+ }
+ }
+ }
+
class ResultReceiver implements PendingIntent.OnFinished {
public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
String resultData, Bundle resultExtras) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6d6ca3c..e36d118 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -36,6 +36,9 @@ import com.android.server.pm.UserManagerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.wm.WindowManagerService;
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -142,6 +145,9 @@ import java.util.Locale;
import cyanogenmod.providers.CMSettings;
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
/**
* This class provides a system service that manages input methods.
*/
@@ -199,6 +205,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ processQSChangedLocked();
+ }
+ };
+
// All known input methods. mMethodMap also serves as the global
// lock for this class.
final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
@@ -949,6 +962,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}, filter);
LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl(mHandler));
+ QSUtils.registerObserverForQSChanges(mContext, mQSListener);
}
private void resetDefaultImeLocked(Context context) {
@@ -1822,6 +1836,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
com.android.internal.R.string.select_input_method,
mImeSwitcherNotification.build(), UserHandle.ALL);
mNotificationShown = true;
+ publishImeSelectorCustomTile(imi);
}
} else {
if (mNotificationShown && mNotificationManager != null) {
@@ -1831,6 +1846,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mNotificationManager.cancelAsUser(null,
com.android.internal.R.string.select_input_method, UserHandle.ALL);
mNotificationShown = false;
+ unpublishImeSelectorCustomTile();
}
}
} finally {
@@ -3561,6 +3577,78 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ private void publishImeSelectorCustomTile(InputMethodInfo imi) {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ if (!QSUtils.isQSTileEnabledForUser(
+ mContext, QSConstants.DYNAMIC_TILE_IME_SELECTOR, userId)) {
+ return;
+ }
+
+ final UserHandle user = new UserHandle(userId);
+ final int icon = QSUtils.getDynamicQSTileResIconId(mContext, userId,
+ QSConstants.DYNAMIC_TILE_IME_SELECTOR);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(mContext, userId,
+ QSConstants.DYNAMIC_TILE_IME_SELECTOR);
+ final Context resourceContext = QSUtils.getQSTileContext(mContext, userId);
+ CharSequence inputMethodName = null;
+ if (mCurrentSubtype != null) {
+ inputMethodName = mCurrentSubtype.getDisplayName(mContext,
+ imi.getPackageName(), imi.getServiceInfo().applicationInfo);
+ }
+ final CharSequence label = inputMethodName == null ? contentDesc : inputMethodName;
+
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(label.toString())
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setOnClickIntent(mImeSwitchPendingIntent)
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_IME_SELECTOR,
+ InputMethodManagerService.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishImeSelectorCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_IME_SELECTOR,
+ InputMethodManagerService.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void processQSChangedLocked() {
+ final int userId = UserHandle.myUserId();
+ final boolean isIMEVisible = ((mImeWindowVis & (InputMethodService.IME_ACTIVE)) != 0)
+ && (mWindowManagerService.isHardKeyboardAvailable()
+ || (mImeWindowVis & (InputMethodService.IME_VISIBLE)) != 0);
+ InputMethodInfo imi = null;
+ synchronized (mMethodMap) {
+ if (mCurMethodId != null) {
+ imi = mMethodMap.get(mCurMethodId);
+ }
+ }
+ final boolean hasInputMethod = isIMEVisible && imi != null && mCurrentSubtype != null;
+ final boolean isEnabledForUser = QSUtils.isQSTileEnabledForUser(mContext,
+ QSConstants.DYNAMIC_TILE_NEXT_ALARM, userId);
+ boolean enabled = isEnabledForUser && hasInputMethod;
+ if (enabled) {
+ publishImeSelectorCustomTile(imi);
+ } else {
+ unpublishImeSelectorCustomTile();
+ }
+ }
+
// TODO: Cache the state for each user and reset when the cached user is removed.
private static class InputMethodFileManager {
private static final String SYSTEM_PATH = "system";
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 34a17a2..19e39e7 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -32,6 +32,7 @@ import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
+import android.os.Binder;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -51,8 +52,16 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
+
import cyanogenmod.providers.CMSettings;
+import cyanogenmod.app.CMStatusBarManager;
+import cyanogenmod.app.CustomTile;
+
+import org.cyanogenmod.internal.util.QSUtils;
+import org.cyanogenmod.internal.util.QSUtils.OnQSChanged;
+import org.cyanogenmod.internal.util.QSConstants;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -162,6 +171,13 @@ public class UsbDeviceManager {
}
}
+ private final OnQSChanged mQSListener = new OnQSChanged() {
+ @Override
+ public void onQSChanged() {
+ mHandler.processQSChangedLocked();
+ }
+ };
+
/*
* Listens for uevent messages from the kernel to monitor the USB state
*/
@@ -361,11 +377,13 @@ public class UsbDeviceManager {
false, adbNotificationObserver);
mContentResolver.registerContentObserver(
CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_NOTIFY),
- false, adbNotificationObserver);
+ false, adbNotificationObserver);
// Watch for USB configuration changes
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+
+ QSUtils.registerObserverForQSChanges(mContext, mQSListener);
} catch (Exception e) {
Slog.e(TAG, "Error initializing UsbHandler", e);
}
@@ -865,6 +883,12 @@ public class UsbDeviceManager {
}
mAdbNotificationId = id;
}
+
+ if (id > 0) {
+ publishAdbCustomTile();
+ } else {
+ unpublishAdbCustomTile();
+ }
}
private String getDefaultFunctions() {
@@ -893,6 +917,95 @@ public class UsbDeviceManager {
pw.println("IOException: " + e);
}
}
+
+ private void publishAdbCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ if (!QSUtils.isQSTileEnabledForUser(
+ mContext, QSConstants.DYNAMIC_TILE_ADB, userId)) {
+ return;
+ }
+
+ final UserHandle user = new UserHandle(userId);
+ final int icon = QSUtils.getDynamicQSTileResIconId(mContext, userId,
+ QSConstants.DYNAMIC_TILE_ADB);
+ final String contentDesc = QSUtils.getDynamicQSTileLabel(mContext, userId,
+ QSConstants.DYNAMIC_TILE_ADB);
+ final Context resourceContext = QSUtils.getQSTileContext(mContext, userId);
+
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ CustomTile tile = new CustomTile.Builder(resourceContext)
+ .setLabel(getAdbCustomTileLabel())
+ .setContentDescription(contentDesc)
+ .setIcon(icon)
+ .setOnClickIntent(getCustomTilePendingIntent())
+ .build();
+ statusBarManager.publishTileAsUser(QSConstants.DYNAMIC_TILE_ADB,
+ UsbDeviceManager.class.hashCode(), tile, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void unpublishAdbCustomTile() {
+ // This action should be performed as system
+ final int userId = UserHandle.myUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ CMStatusBarManager statusBarManager = CMStatusBarManager.getInstance(mContext);
+ statusBarManager.removeTileAsUser(QSConstants.DYNAMIC_TILE_ADB,
+ UsbDeviceManager.class.hashCode(), new UserHandle(userId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private PendingIntent getCustomTilePendingIntent() {
+ Intent i = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return PendingIntent.getActivity(mContext, 0, i, PendingIntent.FLAG_UPDATE_CURRENT, null);
+ }
+
+ private String getAdbCustomTileLabel() {
+ boolean usbAdbActive = mAdbEnabled && mConnected;
+ boolean netAdbActive = mAdbEnabled &&
+ CMSettings.Secure.getInt(mContentResolver, CMSettings.Secure.ADB_PORT, -1) > 0;
+
+ int id = 0;
+ if (usbAdbActive && netAdbActive) {
+ id = com.android.internal.R.string.adb_active_custom_tile_both;
+ } else if (usbAdbActive) {
+ id = com.android.internal.R.string.adb_active_custom_tile_usb;
+ } else if (netAdbActive) {
+ id = com.android.internal.R.string.adb_active_custom_tile_net;
+ }
+
+ Resources res = mContext.getResources();
+ return res.getString(
+ com.android.internal.R.string.adb_active_custom_tile,
+ res.getString(id));
+ }
+
+ private void processQSChangedLocked() {
+ final int userId = UserHandle.myUserId();
+ boolean usbAdbActive = mAdbEnabled && mConnected;
+ boolean netAdbActive = mAdbEnabled &&
+ CMSettings.Secure.getInt(mContentResolver, CMSettings.Secure.ADB_PORT, -1) > 0;
+ boolean notifEnabled = "1".equals(SystemProperties.get("persist.adb.notify"))
+ || CMSettings.Secure.getInt(mContext.getContentResolver(),
+ CMSettings.Secure.ADB_NOTIFY, 1) == 1;
+ boolean isActive = notifEnabled && (usbAdbActive || netAdbActive);
+ final boolean isEnabledForUser = QSUtils.isQSTileEnabledForUser(mContext,
+ QSConstants.DYNAMIC_TILE_ADB, userId);
+ boolean enabled = (userId == UserHandle.USER_OWNER) && isEnabledForUser && isActive;
+ if (enabled) {
+ publishAdbCustomTile();
+ } else {
+ unpublishAdbCustomTile();
+ }
+ }
}
/* returns the currently attached USB accessory */