1 /* 2 * Copyright (C) 2017 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 */ 16 package com.android.coretests.apps.bstatstestapp; 17 18 import android.R; 19 import android.app.Notification; 20 import android.app.NotificationChannel; 21 import android.app.NotificationManager; 22 import android.app.Service; 23 import android.content.Intent; 24 import android.graphics.Color; 25 import android.graphics.Point; 26 import android.os.Handler; 27 import android.os.IBinder; 28 import android.os.Process; 29 import android.os.RemoteException; 30 import android.util.Log; 31 import android.view.Gravity; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.view.WindowManager; 35 36 import java.util.concurrent.CountDownLatch; 37 import java.util.concurrent.TimeUnit; 38 39 public class TestService extends Service { 40 private static final String TAG = TestService.class.getSimpleName(); 41 42 private static final int FLAG_START_FOREGROUND = 1; 43 44 private static final String NOTIFICATION_CHANNEL_ID = TAG; 45 private static final int NOTIFICATION_ID = 42; 46 47 private static final int TIMEOUT_OVERLAY_SEC = 2; 48 49 private View mOverlay; 50 51 @Override 52 public void onCreate() { 53 Log.d(TAG, "onCreate called. myUid=" + Process.myUid()); 54 } 55 56 @Override 57 public int onStartCommand(Intent intent, int flags, int startId) { 58 Log.d(TAG, "onStartCommand called. myUid=" + Process.myUid()); 59 if (intent != null && (intent.getFlags() & FLAG_START_FOREGROUND) != 0) { 60 startForeground(); 61 } 62 notifyServiceLaunched(intent); 63 return START_STICKY; 64 } 65 66 @Override 67 public IBinder onBind(Intent intent) { 68 Log.d(TAG, "onBind called. myUid=" + Process.myUid()); 69 return null; 70 } 71 72 @Override 73 public void onDestroy() { 74 Log.d(TAG, "onDestroy called. myUid=" + Process.myUid()); 75 removeOverlays(); 76 } 77 78 private void notifyServiceLaunched(Intent intent) { 79 Common.notifyLaunched(intent, mReceiver.asBinder(), TAG); 80 } 81 82 private void startForeground() { 83 final NotificationManager noMan = getSystemService(NotificationManager.class); 84 noMan.createNotificationChannel(new NotificationChannel( 85 NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, 86 NotificationManager.IMPORTANCE_DEFAULT)); 87 Log.d(TAG, "Starting foreground. myUid=" + Process.myUid()); 88 startForeground(NOTIFICATION_ID, 89 new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) 90 .setSmallIcon(R.drawable.ic_dialog_alert) 91 .build()); 92 } 93 94 private void removeOverlays() { 95 if (mOverlay != null) { 96 final WindowManager wm = TestService.this.getSystemService(WindowManager.class); 97 wm.removeView(mOverlay); 98 mOverlay = null; 99 } 100 } 101 102 private BaseCmdReceiver mReceiver = new BaseCmdReceiver() { 103 @Override 104 public void doSomeWork(int durationMs) { 105 Common.doSomeWork(durationMs); 106 } 107 108 @Override 109 public void showApplicationOverlay() throws RemoteException { 110 final WindowManager wm = TestService.this.getSystemService(WindowManager.class); 111 final Point size = new Point(); 112 wm.getDefaultDisplay().getSize(size); 113 114 final WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams( 115 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 116 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 117 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 118 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); 119 wmlp.width = size.x / 2; 120 wmlp.height = size.y / 2; 121 wmlp.gravity = Gravity.CENTER | Gravity.LEFT; 122 wmlp.setTitle(TAG); 123 124 final ViewGroup.LayoutParams vglp = new ViewGroup.LayoutParams( 125 ViewGroup.LayoutParams.MATCH_PARENT, 126 ViewGroup.LayoutParams.MATCH_PARENT); 127 128 mOverlay = new View(TestService.this); 129 mOverlay.setBackgroundColor(Color.GREEN); 130 mOverlay.setLayoutParams(vglp); 131 132 final CountDownLatch latch = new CountDownLatch(1); 133 final Handler handler = new Handler(TestService.this.getMainLooper()); 134 handler.post(() -> { 135 wm.addView(mOverlay, wmlp); 136 latch.countDown(); 137 }); 138 try { 139 if (!latch.await(TIMEOUT_OVERLAY_SEC, TimeUnit.SECONDS)) { 140 throw new RemoteException("Timed out waiting for the overlay"); 141 } 142 } catch (InterruptedException e) { 143 throw new RemoteException("Error while adding overlay: " + e.toString()); 144 } 145 Log.d(TAG, "Overlay displayed, myUid=" + Process.myUid()); 146 } 147 148 @Override 149 public void finishHost() { 150 removeOverlays(); 151 stopSelf(); 152 } 153 }; 154 } 155