1e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler/* 2e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * Copyright (C) 2008 The Android Open Source Project 3e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * 4e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 5e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * you may not use this file except in compliance with the License. 6e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * You may obtain a copy of the License at 7e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * 8e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 9e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * 10e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * Unless required by applicable law or agreed to in writing, software 11e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 12e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * See the License for the specific language governing permissions and 14e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler * limitations under the License. 15e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler */ 16e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 17e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerpackage com.android.systemui.statusbar.policy; 18e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 19e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport java.util.ArrayList; 20e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 21e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.app.Notification; 22e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.app.NotificationManager; 23e5e764ad0bb74d8c1405d018b4e0fe92d6554660Romain Guyimport android.app.PendingIntent; 24e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.content.BroadcastReceiver; 25e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.content.Context; 26e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.content.Intent; 27e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.content.IntentFilter; 28e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.location.LocationManager; 294120375d46091df8527bb701882e056fbb0e6b06Dianne Hackbornimport android.os.UserHandle; 30e5e764ad0bb74d8c1405d018b4e0fe92d6554660Romain Guyimport android.provider.Settings; 31e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.util.Slog; 32e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.view.View; 33e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.widget.ImageView; 34e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 35e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler// private NM API 36e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport android.app.INotificationManager; 37e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport com.android.internal.statusbar.StatusBarNotification; 38e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 39e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerimport com.android.systemui.R; 40d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 41e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 42e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandlerpublic class LocationController extends BroadcastReceiver { 43e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler private static final String TAG = "StatusBar.LocationController"; 44e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 45e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler private static final int GPS_NOTIFICATION_ID = 374203-122084; 46e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 47e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler private Context mContext; 48e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 49e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler private INotificationManager mNotificationService; 50e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 51d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung private ArrayList<LocationGpsStateChangeCallback> mChangeCallbacks = 52d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung new ArrayList<LocationGpsStateChangeCallback>(); 53d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung 54d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung public interface LocationGpsStateChangeCallback { 55d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung public void onLocationGpsStateChanged(boolean inUse, String description); 56d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung } 57d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung 58e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler public LocationController(Context context) { 59e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler mContext = context; 60e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 61e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler IntentFilter filter = new IntentFilter(); 62e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION); 63e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION); 64e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler context.registerReceiver(this, filter); 65e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 66e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler NotificationManager nm = (NotificationManager)context.getSystemService( 67e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler Context.NOTIFICATION_SERVICE); 68e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler mNotificationService = nm.getService(); 69e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } 70e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 71d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung public void addStateChangedCallback(LocationGpsStateChangeCallback cb) { 72d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung mChangeCallbacks.add(cb); 73d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung } 74d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung 75e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler @Override 76e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler public void onReceive(Context context, Intent intent) { 77e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler final String action = intent.getAction(); 78e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false); 79e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 80e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler boolean visible; 81e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler int iconId, textResId; 82e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 83e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) { 84e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler // GPS is getting fixes 85e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler iconId = com.android.internal.R.drawable.stat_sys_gps_on; 86e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler textResId = R.string.gps_notification_found_text; 87e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler visible = true; 88e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) { 89e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler // GPS is off 90e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler visible = false; 91e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler iconId = textResId = 0; 92e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } else { 93e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler // GPS is on, but not receiving fixes 94e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler iconId = R.drawable.stat_sys_gps_acquiring_anim; 95e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler textResId = R.string.gps_notification_searching_text; 96e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler visible = true; 97e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } 98e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 99e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler try { 100e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler if (visible) { 101e5e764ad0bb74d8c1405d018b4e0fe92d6554660Romain Guy Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 102e5e764ad0bb74d8c1405d018b4e0fe92d6554660Romain Guy gpsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 103d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung 1044120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0, 1054120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn gpsIntent, 0, null, UserHandle.CURRENT); 106d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung String text = mContext.getText(textResId).toString(); 107e5e764ad0bb74d8c1405d018b4e0fe92d6554660Romain Guy 108e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler Notification n = new Notification.Builder(mContext) 109e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler .setSmallIcon(iconId) 110d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung .setContentTitle(text) 111e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler .setOngoing(true) 112e5e764ad0bb74d8c1405d018b4e0fe92d6554660Romain Guy .setContentIntent(pendingIntent) 113e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler .getNotification(); 114e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 115e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler // Notification.Builder will helpfully fill these out for you no matter what you do 116e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler n.tickerView = null; 117e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler n.tickerText = null; 1182561b0b10a55841a08e0e1d467e73e10b1bf256dDaniel Sandler 1192561b0b10a55841a08e0e1d467e73e10b1bf256dDaniel Sandler n.priority = Notification.PRIORITY_HIGH; 120e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 121e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler int[] idOut = new int[1]; 1222561b0b10a55841a08e0e1d467e73e10b1bf256dDaniel Sandler mNotificationService.enqueueNotificationWithTag( 123e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler mContext.getPackageName(), 124e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler null, 125e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler GPS_NOTIFICATION_ID, 126e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler n, 1274120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn idOut, 12838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease UserHandle.USER_ALL); 129e641b6a99cabad7076e10694a5b1b30f449de462Winson Chung 130e641b6a99cabad7076e10694a5b1b30f449de462Winson Chung for (LocationGpsStateChangeCallback cb : mChangeCallbacks) { 131e641b6a99cabad7076e10694a5b1b30f449de462Winson Chung cb.onLocationGpsStateChanged(true, text); 132e641b6a99cabad7076e10694a5b1b30f449de462Winson Chung } 133e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } else { 1344120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn mNotificationService.cancelNotificationWithTag( 1354120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn mContext.getPackageName(), null, 13638389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease GPS_NOTIFICATION_ID, UserHandle.USER_ALL); 137d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung 138d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung for (LocationGpsStateChangeCallback cb : mChangeCallbacks) { 139d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung cb.onLocationGpsStateChanged(false, null); 140d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung } 141e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } 142e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } catch (android.os.RemoteException ex) { 143e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler // well, it was worth a shot 144e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } 145e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler } 146e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler} 147e40451a89dc91dfd636af7cb32a23b4a4cc93fdcDaniel Sandler 148